过滤recyclerview在刷卡时没有得到正确的卡片位置

Posted

技术标签:

【中文标题】过滤recyclerview在刷卡时没有得到正确的卡片位置【英文标题】:filtered recycler view not getting correct card position on swipe 【发布时间】:2018-07-28 06:23:36 【问题描述】:

所以,我有一个使用“滑动关闭”并实现可过滤的 RecyclerView。

什么有效:滑动以消除和过滤按预期单独工作。我可以滑动以使用适当的动画来关闭(在此操作时,我还从我的 SQLite 数据库中删除了一行)。我还可以使用原生 filterable 过滤卡片。

什么不起作用:当我在过滤后滑动关闭时,位置不正确,然后按预期从我的数据库中删除相应的错误行。

我的想法:我相信我需要在过滤过程之后/期间以某种方式更新我的 Activity arrayList。

我在 Activity 中的搜索代码

//create options menu
@Override
public boolean onCreateOptionsMenu(Menu menu) 
    getMenuInflater().inflate(R.menu.menu_jar_options, menu);
    /*return super.onCreateOptionsMenu(menu);*/

    action_search = menu.findItem(R.id.menu_jar_action_search);
    SearchView searchView = (SearchView) action_search.getActionView();
    searchView.setBackgroundColor(0xffffffff);
    search(searchView);
    return true;

@Override
public boolean onOptionsItemSelected(MenuItem item) 
    return super.onOptionsItemSelected(item);


//search
private void search(SearchView searchView) 
    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() 
        @Override
        public boolean onQueryTextSubmit(String query) 
            return false;
        
        @Override
        public boolean onQueryTextChange(String newText) 
            adapter.getFilter().filter(newText.toLowerCase());
            return true;
        
    );

我在 Activity 中的滑动代码(为了清晰起见已清理)

        @Override
        public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction)
            if (direction ==ItemTouchHelper.RIGHT)
                //swipe right - delete card
                final int position = viewHolder.getAdapterPosition();
                //get necessary data from item
                s_deleteIdentifier = arrayList.get(position).getIdentifier();
                s_deleteIdentifier = (!FormatHelper.isStringEmpty(s_deleteIdentifier)) ? s_deleteIdentifier : "";
                s_deleteName = arrayList.get(position).getName();
                s_deleteName = (!FormatHelper.isStringEmpty(s_deleteName)) ? s_deleteName : "";

                //REMOVE ME after testing
                Toast.makeText(JarActivity.this, "" +position +" " +s_deleteName, Toast.LENGTH_SHORT).show();

                adapter.notifyItemRemoved(position);
                arrayList.remove(position);

                //user confirms delete, so delete row from db
                DatabaseHelper.getInstance(JarActivity.this).deleteRow(
                                    "table",
                                    "IDENTIFIER = ?",
                                    new String[] s_deleteIdentifier
                );
        

我在适配器中的过滤器代码

@Override
public Filter getFilter()
    return new Filter() 
        @Override
        protected FilterResults performFiltering(CharSequence charSequence)
            String charString;

            if (charSequence != null) charString = charSequence.toString();
            else charString = "";

            if (charString.isEmpty())
                arrayListFiltered = arrayList;
            else
                ArrayList<JarObject> filteredList = new ArrayList<>();
                for (JarObject jarObject : arrayList) 
                    if (jarObject.getName().toLowerCase().contains(charString) ||
                            jarObject.getLocation().toLowerCase().contains(charString) ||
                            jarObject.getUserNote().toLowerCase().contains(charString) ||
                            jarObject.getSummary().toLowerCase().contains(charString)
                            )
                        filteredList.add(jarObject);
                
                arrayListFiltered = filteredList;
            

            FilterResults filterResults = new FilterResults();
            filterResults.values = arrayListFiltered;
            return filterResults;
        

        @Override
        protected void publishResults(CharSequence charSequence, FilterResults filterResults) 
            arrayListFiltered = (ArrayList<JarObject>) filterResults.values;
            notifyDataSetChanged();
        
    ;

【问题讨论】:

【参考方案1】:

原始列表和过滤列表中的项目不会位于相同的位置。我现在无法整理一个示例,但是您应该能够覆盖适配器 getItemId() 方法以返回有意义的内容并使用 ViewHolder.getItemId() 获取您要删除的实际项目,而不是依赖于位置。

您还可以公开您的过滤列表,以便您可以从您的活动中访问它,以根据位置从过滤列表中获取项目,然后搜索您的原始列表以获得正确的位置。

【讨论】:

我正在尝试使用getItemId(),它每次都返回-1。不知道那告诉我什么。我现在正在寻找答案。 您是否覆盖了适配器中的getItemId() 是的,我相信。 @Override public long getItemId(int position) return position; 在适配器中 我觉得你也需要用developer.android.com/reference/android/support/v7/widget/… 哇。我的代码不喜欢这样:)。我一刷卡,它就在运行时崩溃了。也许我的其余代码都为使用 getAdapterPosition() 进行了调整。不确定。

以上是关于过滤recyclerview在刷卡时没有得到正确的卡片位置的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Recyclerview 中正确使用 DiffUtil 更新数组列表?

如何在场景动画中正确处理 RecyclerView 适配器

Android:无法正确显示 RecyclerView

Android:RecyclerView onClick 监听器没有得到

如何使用 SearchView 过滤 RecyclerView

可过滤在 Recyclerview 中无法按预期工作