RecyclerView:过滤列表中的错误位置

时间:2017-09-03 19:27:34

标签: android android-recyclerview onclicklistener

我有一个CardView项目的RecyclerView列表。然后,我使用带有SearchView小部件的简单过滤方法来过滤列表。当我单击已过滤的CardView以启动CardViewDetails活动时,UI将显示原始列表中的CardView,而不是已过滤的列表。例如,我在原始列表中有20个项目的列表。当我输入搜索约束时,已过滤的列表会在RecyclerView中正确显示三个CardView。当我单击列表中的第三个CardView时,UI将返回原始列表中的第三个CardView,而不是来自已过滤列表的第三个CardView。我在这里缺少什么?

Adapter:

public class MyRecylerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private List<ListItem> mListItems, filteredList;
Context mContext;
private RecyclerItemClickListener recyclerItemClickListener;
private RecyclerView mRecyclerView;
/**********************************************************/
private String searchString = "";
/**********************************************************/

public MyRecylerAdapter(Context context, List<ListItem> listItems) {
    this.mContext = context;
    this.mListItems = listItems;
    this.filteredList = new ArrayList<>();
    this.filteredList.addAll(this.mListItems);
}

// RecyclerItemClickListener is the public interface file used to reach the MainActivity
public void setOnItemClickListener(RecyclerItemClickListener recyclerItemClickListener) {
    this.recyclerItemClickListener = recyclerItemClickListener;
}

// Get the Item's position.
public ListItem getItem(int position) {
    return filteredList.get(position);
}

@Override
public int getItemCount() {
    if (filteredList.size() >0) {
        return filteredList.size();
    }
    else {
        return mListItems.size();
    }
}

public void setFilter(List<ListItem> listItems, String searchString) {
    // Note: the String is to get s.toString() from the Main Activity SearchView.
    filteredList = new ArrayList<>();
    filteredList.addAll(listItems);
    this.searchString = searchString;
    notifyDataSetChanged();
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_contact_item, parent, false);
    final ItemHolder itemHolder = new ItemHolder(view);

        // Attach a Click listener to the items's (row) view.
        // itemView is from the ItemHolder() below.
        // onItemClick is the click method in MainActivity.
        itemHolder.itemView.setOnClickListener(new View.OnClickListener() {                
            @Override
            public void onClick(View view) {

                int adapterPos = itemHolder.getAdapterPosition(); // get the item position.                    
                if (adapterPos != RecyclerView.NO_POSITION) {
                    if (recyclerItemClickListener != null) {
                        // pass the item to the Main Activity
                        // through the RecyclerItemClickListener file and its
                        // public interface.
                        recyclerItemClickListener.onItemClick(itemHolder.itemView,adapterPos);
                    }
                }
            }
        });            
    return itemHolder;
}

private static class ItemHolder extends RecyclerView.ViewHolder {

    private TextView cardBlankText2; 

    private ItemHolder(View itemView) {
        super(itemView);

        cardBlankText2 = (TextView) itemView.findViewById(R.id.cardBlankText2);            
}

public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {

    final ListItem listItem = filteredList.get(position);
    final ItemHolder itemHolder = (ItemHolder) holder;

    itemHolder.cardBlankText2.setText(listItem.getTodo());
}

Activity:

public class MainActivity extends AppCompatActivity implements
    RecyclerItemClickListener {

private List<ListItem> allList = new ArrayList<>();
private RecyclerView mRecyclerView;
private SQLiteDB sqLiteDB;
private MyRecylerAdapter adapter;    
private CardView cardview;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    sqLiteDB = SQLiteDB.getInstance(this);        
    mRecyclerView = (RecyclerView)findViewById(R.id.list_recyclerview);        
    final LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);        
    mRecyclerView.setLayoutManager(layoutManager);
    allList = sqLiteDB.getAllDBItems();

    adapter = new MyRecylerAdapter(this, allList);
    adapter.setOnItemClickListener(this);
    mRecyclerView.setAdapter(adapter);
}

@Override
public void onItemClick(View view, int position) {
    cardview = (CardView) view;
    cardview.setEnabled(false);

    // Create a new intent to send data from this MainActivity to the CardViewDetails
    // Activity.
    Intent intent = new Intent(this,CardViewDetails.class);
    ListItem listItem = adapter.getItem(position);
    // Add the item object to the Intent.  The item object can be used because the
    // model class implements Parcelable so it holds all of the getters
    // that can be snagged in the next Activity with the
    // getParcelableExtra method.
    intent.putExtra("item",listItem);
    intent.putExtra("position",position);
    startActivity(intent);
    finish();
}

// SearchView
final EditText mSearchEditText = (EditText) mSearchView.findViewById(android.support.v7.appcompat.R.id.search_src_text);

    mSearchEditText.addTextChangedListener(new TextWatcher() {

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

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }

        @Override
        public void afterTextChanged(Editable s) {

             final ArrayList<ListItem> filteredModelList = filter(allList, s.toString());

                if (!mSearchView.isIconified() && filteredModelList.size() == 0) {
                    Toast.makeText(MainActivity.this, "Not Found", Toast.LENGTH_SHORT).show();
                    // re-load the list so the Adapter refreshes the RecyclerView list View.
                    adapter.clear();
                    adapter.addAll(allList);
                } else if (!mSearchView.isIconified() && filteredModelList.size() > 0) {                            
                    adapter.setFilter(filteredModelList, s.toString());
                    mRecyclerView.scrollToPosition(0);
                }
            }
        }
    });

private ArrayList<ListItem> filter(List<ListItem> models, String query) {

    query = query.toLowerCase();

    final ArrayList<ListItem> filteredModelList = new ArrayList<>();
    for (ListItem listItem : models) {
        final String text = listItem.getTodo().toLowerCase();
        final String text2 = listItem.getNote1().toLowerCase();
        final String text3 = listItem.getNote2().toLowerCase();
        if (text.contains(query) || text2.contains(query) ||
            text3.contains(query)) {
            filteredModelList.add(listItem);
        }
    }
    return filteredModelList;
}

RecyclerItemClickListener:

public interface RecyclerItemClickListener {

    void onItemClick(View view, int position);
}

CardViewDetails:

public class CardViewDetails extends AppCompatActivity {

private int position;
private SQLiteDB helper;
List<ListItem> listItems;
private CardView cardview;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_details);

    final CardView cardView = (CardView) findViewById(R.id.dets);

    // Create a variable for the skychill footer text.
    final TextView skychilltext5;

    // A db helper instance is needed for the removeItem() below
    // when the user Longclicks the skycard for deletion.
    helper = new SQLiteDB(this);

    // Get the position of the clicked on R. list CardView from
    // the MainActivity's intent bundle.
    Bundle extras = getIntent().getExtras();
    if (extras != null) {
        // get the CardView item using the int position from the
        // MainActivity's onItemClick() and the putExtra in the intent.
        position = extras.getInt("position",0); // 0 is default value
    }

    cb2 = (TextView) findViewById(R.id.cb2);

    helper = new SQLiteDB(this);
    listItems = new ArrayList<>();
    listItems = helper.getAllDBItems(); 

    cb2.setText(listItems.get(position).getTodo());

    ...

}   

1 个答案:

答案 0 :(得分:1)

  

应用过滤器后,sql DB( getAllDBItems )数据保持不变。您只是将position传递给 CardViewDetail 。并且sql数据是原始列表。

您应该将 ListItem作为parcelable 传递给CardViewDetails而不是位置。你的问题将得到解决。