在我的应用程序中,我在SearchView中有一个Toolbar

当用户单击搜索图标时,SearchView会展开并开始输入。搜索查询按标题过滤RecyclerView列表。这一切都很好。

但是,当我对RecyclerView项之一执行OnLongClick操作时,筛选器功能停止工作。

我在每个RecyclerView持有者上都附加了一个OnClickListener和OnLongClickListener,但是只有OnLongClick操作阻止了SearchView进行过滤。我不明白为什么。我尝试重新实例化SearchView并将RecyclerView重置为无效。

这是我的代码:

为了节省空间,已删除了不影响SearchView的功能。

MainActivity.java

public class MainActivity extends AppCompatActivity {

    //LONG CLICK ACTION MODE VARIABLES
    boolean isInActionMode = false;
    TextView selectedCounterText;

    //SEARCH BAR
    SearchView searchView;

    //INSERT DIALOG TEXTVIEWS
    EditText editTitle, editCategory, editSignifier, editDate, editRecurs, editDetails;
    Button btnCreate, btnCancel;

    RecyclerView recyclerView;
    RecyclerView.LayoutManager layoutManager;
    CardAdapter adapter;
    Toolbar toolbar;

    ArrayList<Bullet> bullets = new ArrayList<>();
    ArrayList<Bullet> selectedBullets = new ArrayList<>();
    int counter = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        //SET DEFAULT VIEW STATES
        selectedCounterText = (TextView) findViewById(R.id.selected_counter);
        appName = (TextView) findViewById(R.id.app_name);
        selectedCounterText.setVisibility(View.GONE);
        appName.setVisibility(View.VISIBLE);
        noBulletsMessage = (TextView) findViewById(R.id.noBullets_message);
        noBulletsMessage.setVisibility(View.GONE);

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        //RECYCLERVIEW PROPERTIES
        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setHasFixedSize(true);

        //ACTION MODE ON LONG CLICK VIEW STATES
        selectedCounterText = (TextView) findViewById(R.id.selected_counter);
        selectedCounterText.setVisibility(View.GONE);

        //ADAPTER
        adapter = new CardAdapter(this, bullets);

        //RETRIEVE DATA
        retrieveData();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_activity_main, menu);

        //SEARCH
        final MenuItem searchItem = menu.findItem(R.id.item_search);
        searchView = (SearchView) searchItem.getActionView();
        searchView.setIconifiedByDefault(true);
        searchView.setOnCloseListener(new SearchView.OnCloseListener() {
            @Override
            public boolean onClose() {
                return false;
            }
        });
        searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String query) {
                //FILTER AS YOU TYPE
                adapter.getFilter().filter(query);
                return false;
            }
        });

        return true;
    }

    @Override
    protected void onResume() {
        super.onResume();
        retrieveData();
    }

    /**
     * @param item
     * @return This method includes behavior for all action toolbar menu items: Add, search, edit,
     * and delete.
     * <p>
     * It detects which button is pressed and performs the appropriate action.
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

            //IF HOME (BACK ARROW) IS PRESSED
        } else if (item.getItemId() == android.R.id.home) {
            clearActionMode();
            adapter.notifyDataSetChanged();
        }

        return true;
    }

    public void clearActionMode() {
        isInActionMode = false;
        toolbar.getMenu().clear();
        toolbar.inflateMenu(R.menu.menu_activity_main);
        getSupportActionBar().setDisplayHomeAsUpEnabled(false);
        selectedCounterText.setVisibility(View.GONE);
        appName.setVisibility(View.VISIBLE);
        selectedCounterText.setText("0 Item(s) Selected");
        counter = 0;
        selectedBullets.clear();
    }

    @Override
    public void onBackPressed() {
        if (isInActionMode) {
            clearActionMode();
            adapter.notifyDataSetChanged();
        } else {
            super.onBackPressed();
        }
    }
}


CardHolder.java

public CardHolder(final View itemView, final MainActivity mainActivity) {
        super(itemView);
        signifier_img = (ImageView) itemView.findViewById(R.id.img_id);
        titleText = (TextView) itemView.findViewById(R.id.title);
        categoryText = (TextView) itemView.findViewById(R.id.category);
        cardView = (CardView) itemView.findViewById(R.id.bulletCardView);
        checkBox = (CheckBox) itemView.findViewById(R.id.check_list_item);
        this.mainActivity = mainActivity;

        //CLICK LISTENERS
        cardView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                mainActivity.toolbar.getMenu().clear();
                mainActivity.toolbar.inflateMenu(R.menu.menu_action_mode);
                mainActivity.selectedCounterText.setVisibility(View.VISIBLE);
                mainActivity.appName.setVisibility(View.GONE);
                mainActivity.isInActionMode = true;
                mainActivity.adapter.notifyDataSetChanged();
                mainActivity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);

                return true;
            }
        });
        cardView.setOnClickListener(this);
        checkBox.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mainActivity.prepareSelection(view, getAdapterPosition());
            }
        });

    }

    @Override
    public void onClick(View view) {
        this.itemClickListener.onItemClick(view, getLayoutPosition());
    }

    public void setItemClickListener(ItemClickListener itemClick) {
        this.itemClickListener = itemClick;
    }
}


CardAdapter.java

public class CardAdapter extends RecyclerView.Adapter<CardHolder> implements Filterable {

    Context context;
    ArrayList<Bullet> bullets, filterList;
    SearchFilter filter;
    MainActivity mainActivity;

    public CardAdapter(Context context, ArrayList<Bullet> bullets) {
        this.context = context;
        this.bullets = bullets;
        this.filterList = bullets;
        mainActivity = (MainActivity) context;
    }

    //INITIALIZE VIEWHOLDER
    @Override
    public CardHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //VIEW OBJ FROM XML
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_card_view, parent, false);

        //HOLDER
        CardHolder holder = new CardHolder(view, mainActivity);

        return holder;
    }

    //BIND DATA TO VIEWS
    @Override
    public void onBindViewHolder(final CardHolder holder, int position) {
        holder.signifier_img.setImageResource(R.drawable.asterisk_48px);
        holder.titleText.setText(bullets.get(position).getTitle());

        if (!mainActivity.isInActionMode) {
            holder.checkBox.setVisibility(View.GONE);
        } else {
            holder.checkBox.setVisibility(View.VISIBLE);
            holder.checkBox.setChecked(false);
        }

        //CARD CLICKED
        holder.setItemClickListener(new ItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                //DISPLAY POPUP OF FULL INFO OF BULLET
                //OPEN DETAIL VIEW
                //PASS DATA TO VIEW

                if (!mainActivity.isInActionMode) {
                    //CREATE INTENT
                    Intent intent = new Intent(context, DetailView.class);

                    //LOAD DATA TO INTENT
                    intent.putExtra("ID", bullets.get(position).getId());
                    intent.putExtra("TITLE", bullets.get(position).getTitle());
                    intent.putExtra("CATEGORY", bullets.get(position).getCategory());
                    intent.putExtra("SIGNIFIER", bullets.get(position).getSignifier());
                    intent.putExtra("DATE", bullets.get(position).getDate());
                    intent.putExtra("RECURS", bullets.get(position).getRecurs());
                    intent.putExtra("DETAILS", bullets.get(position).getDetails());

                    //START ACTIVITY
                    context.startActivity(intent);
                } else {
                    //DO NOTHING
                }
            }
        });
    }

    @Override
    public int getItemCount() {
        return bullets.size();
    }

    //RETURN FILTER OBJ
    @Override
    public Filter getFilter() {
        if (filter == null) {
            filter = new SearchFilter(filterList, this);
        }

        return filter;
    }
}


SearchFilter.java

public class SearchFilter extends Filter {

    CardAdapter adapter;
    ArrayList<Bullet> filterList;

    public SearchFilter(ArrayList<Bullet> filterList, CardAdapter adapter) {
        this.adapter = adapter;
        this.filterList = filterList;
    }

    //FILTER OCCURS HERE
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        FilterResults results = new FilterResults();

        //CHECK CONSTRAINT VALIDITY
        if (constraint != null && constraint.length() > 0) {

            //CHANGE TO UPPER
            constraint = constraint.toString().toUpperCase();

            //STORE FILTERED BULLETS
            ArrayList<Bullet> filteredBullets = new ArrayList<>();

            for (int i = 0; i < filterList.size(); i++) {
                //CHECK
                if (filterList.get(i).getTitle().toUpperCase().contains(constraint)) {
                    //ADD BULLET TO FILTERED BULLETS
                    filteredBullets.add(filterList.get(i));
                }
            }

            results.count = filteredBullets.size();
            results.values = filteredBullets;

        } else {
            results.count = filterList.size();
            results.values = filterList;
        }

        return results;
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results) {
        adapter.bullets = (ArrayList<Bullet>) results.values;

        //REFRESH RECYCLERVIEW
        adapter.notifyDataSetChanged();
    }
}


menu_activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/item_search"
        android:icon="@drawable/ic_action_search"
        android:title="Search..."
        app:actionViewClass="android.support.v7.widget.SearchView"
        app:showAsAction="collapseActionView|ifRoom" />

    <item
        android:id="@+id/item_add"
        android:icon="@drawable/ic_action_add2"
        android:title="Add"
        app:showAsAction="always" />

</menu>


我相信所有影响它的代码,但是如果还有其他需要告诉我。

这是堆栈跟踪:

我不太清楚这是什么意思,但是当我尝试在LongClick事件后过滤一些查询时,就会发生这种情况。


09-07 01:46:38.184 17027-17104 / com.curtiswhite.www.sqlitedatabaseforephemeris I / OpenGLRenderer:初始化的EGL版本1.4
09-07 01:47:40.066 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris E / SpannableStringBuilder:SPAN_EXCLUSIVE_EXCLUSIVE跨度不能为零长度
09-07 01:47:40.066 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris E / SpannableStringBuilder:SPAN_EXCLUSIVE_EXCLUSIVE跨度不能为零长度
09-07 01:47:45.036 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris E / SpannableStringBuilder:SPAN_EXCLUSIVE_EXCLUSIVE跨度不能为零长度
09-07 01:47:45.036 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris E / SpannableStringBuilder:SPAN_EXCLUSIVE_EXCLUSIVE跨度不能为零长度
09-07 01:47:45.991 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:非活动InputConnection上的beginBatchEdit
09-07 01:47:45.991 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:非活动InputConnection上的getSelectedText
09-07 01:47:46.0​​03 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:在非活动InputConnection上的endBatchEdit
09-07 01:47:46.0​​03 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:非活动InputConnection上的getTextBeforeCursor
09-07 01:47:46.0​​15 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:非活动InputConnection上的getTextAfterCursor
09-07 01:47:46.0​​22 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:非活动InputConnection上的beginBatchEdit
09-07 01:47:46.0​​23 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:非活动InputConnection上的getSelectedText
09-07 01:47:46.0​​23 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:在非活动InputConnection上的endBatchEdit
09-07 01:47:46.0​​23 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:非活动InputConnection上的getTextBeforeCursor
09-07 01:47:46.0​​24 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:非活动InputConnection上的getTextAfterCursor
09-07 01:47:46.0​​27 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:非活动InputConnection上的beginBatchEdit
09-07 01:47:46.0​​27 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:非活动InputConnection上的getSelectedText
09-07 01:47:46.0​​27 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:在非活动InputConnection上的endBatchEdit
09-07 01:47:46.0​​28 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:非活动InputConnection上的getTextBeforeCursor
09-07 01:47:46.0​​30 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:非活动InputConnection上的getTextAfterCursor
09-07 01:47:46.0​​62 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:非活动InputConnection上的beginBatchEdit
09-07 01:47:46.0​​62 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:非活动InputConnection上的getSelectedText
09-07 01:47:46.0​​62 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:在非活动InputConnection上的endBatchEdit
09-07 01:47:46.0​​63 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:非活动InputConnection上的getTextBeforeCursor
09-07 01:47:46.0​​63 17027-17027 / com.curtiswhite.www.sqlitedatabaseforephemeris W / IInputConnectionWrapper:非活动InputConnection上的getTextAfterCursor

最佳答案

我解决了这个问题。

事实证明,此问题是在对LongClick扩展新菜单时引起的。这导致SearchView缩小(按预期方式),但是在按回(调用OnBackPressed)时,原始菜单会膨胀,但是放置的SearchView上有一个尚未实例化的新菜单。

为了解决这个问题,我只是简单地调用OnCreateMenuOptions(toolbar.getMenu());。在onBackPressed方法中。这将重新实例化SearchView,因此在菜单膨胀后它将再次运行。

10-04 12:24