使用游标适配器,带过滤器实现多个列表视图选择 [英] Implementing a listview with multiple select with filter using a Cursor Adapter

查看:198
本文介绍了使用游标适配器,带过滤器实现多个列表视图选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题是在这个问题<一个讨论href="http://stackoverflow.com/questions/7874668/android-wrong-item-checked-when-filtering-listview">Android:当过滤列表视图错误的项目进行检查。要总结问题,使用具有的CursorAdapter和过滤器的列表视图时,在过滤列表中选择的项目失去了选择过滤器被删除,取而代之,在未过滤列表中的位置的项目将选定之后。

This problem is discussed in this question Android: Wrong item checked when filtering listview. To summarize the problem, when using a listview with a CursorAdapter and a filter, items selected on a filtered list lose their selection after the filter is removed and instead, items at that position in the unfiltered list get selected.

在链接的问题上面,我们应该在这里把code标记的复选框使用code样本。我相信它应该是在CustomCursorAdapter的getView()方法,但我不知道。此外,我们怎么访问的HashSet来保存所有selectedIds在自定义适配器类,因为它会被初始化和修改的主要活动拿着的名单。

Using the code sample in the linked question above, where should we put the code to mark the checkboxes. I believe it should be in the getView() method of the CustomCursorAdapter, but I am not sure. Also, how do we access the HashSet holding all the selectedIds in the custom adapter class, because it will be initialized and modified in the main activity holding the list.

我的活动实施的ListView

My activity implementing the ListView

@Override
public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.selectfriends);

      Log.v(TAG, "onCreate called") ;

      selectedIds = new ArrayList<String>() ;
      selectedLines = new ArrayList<Integer>()  ;

      mDbHelper = new FriendsDbAdapter(this);
      mDbHelper.open() ;

      Log.v(TAG, "database opened") ;

      Cursor c = mDbHelper.fetchAllFriends();
      startManagingCursor(c);

      Log.v(TAG, "fetchAllFriends Over") ;


      String[] from = new String[] {mDbHelper.KEY_NAME};
      int[] to = new int[] { R.id.text1 };

      final ListView listView = getListView();
      Log.d(TAG, "Got listView");

   // Now initialize the  adapter and set it to display using our row
       adapter =
           new FriendsSimpleCursorAdapter(this, R.layout.selectfriendsrow, c, from, to);

       Log.d(TAG, "we have got an adapter");
     // Initialize the filter-text box 
     //Code adapted from http://stackoverflow.com/questions/1737009/how-to-make-a-nice-looking-listview-filter-on-android

       filterText = (EditText) findViewById(R.id.filtertext) ;
       filterText.addTextChangedListener(filterTextWatcher) ;

     /* Set the FilterQueryProvider, to run queries for choices
     * that match the specified input.
     *  Code adapted from http://stackoverflow.com/questions/2002607/android-how-to-text-filter-a-listview-based-on-a-simplecursoradapter
     */

       adapter.setFilterQueryProvider(new FilterQueryProvider() {
            public Cursor runQuery(CharSequence constraint) {
                // Search for friends whose names begin with the specified letters.
                Log.v(TAG, "runQuery Constraint = " + constraint) ;
                String selection = mDbHelper.KEY_NAME + " LIKE '%"+constraint+"%'";

                mDbHelper.open(); 
                Cursor c = mDbHelper.fetchFriendsWithSelection(
                 (constraint != null ? constraint.toString() : null));
                return c;
     }
 });




       setListAdapter(adapter);

       Log.d(TAG, "setListAdapter worked") ;


       listView.setItemsCanFocus(false);
       listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

       // listView.setOnItemClickListener(mListener);

       Button btn;
       btn = (Button)findViewById(R.id.buttondone);

       mDbHelper.close();

  }


    @Override   
    protected void onListItemClick(ListView parent, View v, int position, long id) {

        String item = (String) getListAdapter().getItem(position);
        Toast.makeText(this, item + " selected", Toast.LENGTH_LONG).show();

        //gets the Bookmark ID of selected position
         Cursor cursor = (Cursor)parent.getItemAtPosition(position);
         String bookmarkID = cursor.getString(0);

         Log.d(TAG, "mListener -> bookmarkID = " + bookmarkID);

         Log.d(TAG, "mListener -> position = " + position);

 //        boolean currentlyChecked = checkedStates.get(position);
 //        checkedStates.set(position, !currentlyChecked);


         if (!selectedIds.contains(bookmarkID)) {

             selectedIds.add(bookmarkID);
             selectedLines.add(position);

         } else {

             selectedIds.remove(bookmarkID);
             selectedLines.remove(position);


             }

     }



  private TextWatcher filterTextWatcher = new TextWatcher() {

      public void afterTextChanged(Editable s)  {

      }

      public void beforeTextChanged(CharSequence s, int start, int count, int after)    {

      }

      public void onTextChanged(CharSequence s, int start, int before, int count)   {
          Log.v(TAG, "onTextChanged called. s = " + s);
          adapter.getFilter().filter(s);
      }
  };

  @Override
  protected void onDestroy()    {
        super.onDestroy();
        filterText.removeTextChangedListener(filterTextWatcher);
  }

我的自定义光标适配器:

My Custom Cursor Adapter:

public class FriendsSimpleCursorAdapter extends SimpleCursorAdapter implements Filterable {

private static final String TAG = "FriendsSimpleCursorAdapter";
private final Context context ;
private final String[] values ;
private final int layout ;
private final Cursor cursor ;

static class ViewHolder {
    public CheckedTextView checkedText ;
}

public FriendsSimpleCursorAdapter(Context context, int layout, Cursor c,
        String[] from, int[] to) {
    super(context, layout, c, from, to);
    this.context = context ;
    this.values = from ;
    this.layout = layout ;
    this.cursor = c ;
    Log.d(TAG, "At the end of the constructor") ;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)   {
    Log.d(TAG, "At the start of rowView. position = " + position) ;
    View rowView = convertView ;
    if(rowView == null) {
        Log.d(TAG, "rowView = null");
        try {
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        rowView = inflater.inflate(layout, parent, false);
        Log.d(TAG, "rowView inflated. rowView = " + rowView);
        ViewHolder viewHolder = new ViewHolder() ;
        viewHolder.checkedText = (CheckedTextView) rowView.findViewById(R.id.text1) ;
        rowView.setTag(viewHolder);
        }
        catch (Exception e) {
            Log.e(TAG, "exception = " + e);
        }
    }

    ViewHolder holder = (ViewHolder) rowView.getTag();

    int nameCol = cursor.getColumnIndex(FriendsDbAdapter.KEY_NAME) ;
    String name = cursor.getString(nameCol);
    holder.checkedText.setText(name);

    Log.d(TAG, "At the end of rowView");
    return rowView;

}

}

推荐答案

我所做的是解决它:

CUR =光标。 c为simplecursoradapter内光标。

cur = cursor. c = the simplecursoradapter inner cursor.

在我MainActivity:

(members)
static ArrayList<Boolean> checkedStates = new ArrayList<Boolean>();
static HashSet<String> selectedIds = new HashSet<String>();
static HashSet<Integer> selectedLines = new HashSet<Integer>();

在ListView onItemClickListener:

if (!selectedIds.contains(bookmarkID)) {

    selectedIds.add(bookmarkID);
    selectedLines.add(position);


} else {

     selectedIds.remove(bookmarkID);
     selectedLines.remove(position);



 if (selectedIds.isEmpty()) {
    //clear everything
        selectedIds.clear();
        checkedStates.clear();      
        selectedLines.clear();

        //refill checkedStates to avoid force close bug - out of bounds
        if (cur.moveToFirst()) {
            while (!cur.isAfterLast()) {    
                MainActivity.checkedStates.add(false);

                cur.moveToNext();
            }
        }                       

 }

在SimpleCursorAdapter我加了(无论是在getView):

// fill the checkedStates array with amount of bookmarks (prevent OutOfBounds Force close)
        if (c.moveToFirst()) {
            while (!c.isAfterLast()) {  
                MainActivity.checkedStates.add(false);
                c.moveToNext();
            }
        }

String bookmarkID = c.getString(0);
        CheckedTextView markedItem = (CheckedTextView) row.findViewById(R.id.btitle);
        if (MainActivity.selectedIds.contains(new String(bookmarkID))) {
            markedItem.setChecked(true);
            MainActivity.selectedLines.add(pos);

        } else {
            markedItem.setChecked(false);
            MainActivity.selectedLines.remove(pos);
        }

希望这有助于...当然,你需要将其调整到您的需要。

Hope this helps... you'll of course need to adjust it to your needs.

编辑:

下载FB SDK,无法获得通过FB登录。你有一个错误的地方,你没有得到一个有效的access_token如果FB的应用程序安装在设备上。删除了FB的应用程序,并得到了在 getFriends一个FC()。通过包装其范围与 runOnUiThread(新的Runnable ...)

Downloaded FB SDK, couldn't get pass the FB login. you have a bug where you don't get a valid access_token if the FB app is installed on the device. Removed the FB app and got a FC in getFriends(). Solved it by wrapping its scope with runOnUiThread(new Runnable...).

你无关不良过滤错误,糟糕的复选框的状态...你得到它,因为你试图查询之前访问光标(已关闭)。 好像你关闭游标适配器在使用它之前。通过将验证它:

The error you get has nothing to do with bad filtering, bad checkbox states... You get it because you're trying to access the cursor before querying it (already closed). It seems like you're closing the cursor before the adapter is using it. Verified it by adding:

mDbHelper = new FriendsDbAdapter(context);

        mDbHelper.open() ;
        cursor = mDbHelper.fetchAllFriends();

在SelectFriendsAdapter的getView范围。

to the getView scope in SelectFriendsAdapter.

在添加此,它不会FC,你可以开始考虑您的过滤器的照顾。 确保光标未关闭,基本上,如果你使用 startManagingCursor()管理​​它,有没有需要手动关闭它。

After you add this, it won't FC and you can start taking care of your filter. Make sure the cursor is not closed and basically if you're managing it with startManagingCursor(), there's not need to manually close it.

希望你可以把它从这里开始!

Hope you can take it from here!

这篇关于使用游标适配器,带过滤器实现多个列表视图选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆