当前位置: 首页 > 知识库问答 >
问题:

RecyclerView:筛选列表中的位置错误

钱震博
2023-03-14

我有一个CardView项目的RecolyerView列表。然后我使用一个带有SearchView小部件的简单筛选方法来筛选列表。然后,当我单击一个经过过滤的CardView启动CardViewDetails活动时,UI显示的是原始列表中的CardView,而不是经过过滤的列表。例如,我有一个列表,在原来的列表中有二十个项目。当我输入搜索约束时,筛选的列表在RecyclerView中正确地显示了三个CardViews。当我单击列表中的第三个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个答案

罗昱
2023-03-14

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

您应该将ListItem作为parcelable传递给CardViewDetails而不是position。你的问题就解决了。

 类似资料:
  • 在中,我需要更改每个行列表中的,即在选择每个位置后才指定的行更改。 所有的事情都是正确的,但当滚动回收视图,所选行的位置会自动改变! 这是我的适配器类: 我在输出中看到的: 正如所看到的,我选择了第一行图标,但滚动RecyclerView后,选择的位置改变了。 然后尝试使用更改和在中的位置再次错误! 我也看到了这个解决方案:获取点击的项目及其在RecyclerView中的位置

  • 问题内容: 有没有一种方法可以针对具有指向ArrayList或List的where子句的数据源(可以是sql,oracle或access)创建查询? 例子: 我已经看到了使用Linq的一些方法,但是如果可以避免的话,我宁愿不诉诸于此。 问题答案: 您可以使用。尝试这样的事情: 附带说明,这不能保护您免受SQL注入的侵害-希望本示例将为您指明正确的方向。

  • 本文向大家介绍Kotlin 筛选列表,包括了Kotlin 筛选列表的使用技巧和注意事项,需要的朋友参考一下 示例            

  • 列表筛选可以对地图中的数据按照事先设置好的列表模板进行查询。在第一次点击列表筛选时,会进入筛选定制页面,如下图: 点击确认后,开始进行筛选设置:点击新增按钮,可对某个字段添加筛选要求,添加后然后选择条件旁边加号按钮,以设置对某一列的具体筛选要求。 如上图的筛选条件为“名称包含迪亚”的售点,继续单击加号可以对名称列继续添加条件。如果需要对其他字段进行筛选,可以再次单击新增按钮增加条件,点击确定及保存

  • 我有一个带有FireBaseRecyclerAdapter的RecyclerView。当用户开始输入SearchView时,我想用一个名称列表填充RecycerView。 也是对查询进行忽略的方法吗?

  • 本文向大家介绍C ++中的按位筛选,包括了C ++中的按位筛选的使用技巧和注意事项,需要的朋友参考一下 在这个问题中,给我们一个数字N。我们的任务是使用按位筛选找到所有小于N的素数。 按位筛是Eratosthenes筛的优化版本,用于查找所有小于给定数的素数。 让我们举个例子来了解这个问题, 输入-N = 25 输出-2 3 5 7 11 13 17 19 23 按位筛子的工作方式与普通筛子相同。