java - SearchView 在 LongClick 操作后停止过滤

标签 java android searchview onlongclicklistener onitemlongclicklistener

在我的应用中,工具栏中有一个SearchView

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

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

我将 OnClickListener 和 OnLongClickListener 附加到每个 RecyclerView 持有者,但只有 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: Initialized EGL, version 1.4 09-07 01:47:40.066 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris E/SpannableStringBuilder: SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length 09-07 01:47:40.066 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris E/SpannableStringBuilder: SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length 09-07 01:47:45.036 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris E/SpannableStringBuilder: SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length 09-07 01:47:45.036 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris E/SpannableStringBuilder: SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length 09-07 01:47:45.991 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: beginBatchEdit on inactive InputConnection 09-07 01:47:45.991 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: getSelectedText on inactive InputConnection 09-07 01:47:46.003 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: endBatchEdit on inactive InputConnection 09-07 01:47:46.003 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: getTextBeforeCursor on inactive InputConnection 09-07 01:47:46.015 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: getTextAfterCursor on inactive InputConnection 09-07 01:47:46.022 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: beginBatchEdit on inactive InputConnection 09-07 01:47:46.023 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: getSelectedText on inactive InputConnection 09-07 01:47:46.023 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: endBatchEdit on inactive InputConnection 09-07 01:47:46.023 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: getTextBeforeCursor on inactive InputConnection 09-07 01:47:46.024 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: getTextAfterCursor on inactive InputConnection 09-07 01:47:46.027 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: beginBatchEdit on inactive InputConnection 09-07 01:47:46.027 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: getSelectedText on inactive InputConnection 09-07 01:47:46.027 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: endBatchEdit on inactive InputConnection 09-07 01:47:46.028 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: getTextBeforeCursor on inactive InputConnection 09-07 01:47:46.030 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: getTextAfterCursor on inactive InputConnection 09-07 01:47:46.062 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: beginBatchEdit on inactive InputConnection 09-07 01:47:46.062 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: getSelectedText on inactive InputConnection 09-07 01:47:46.062 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: endBatchEdit on inactive InputConnection 09-07 01:47:46.063 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: getTextBeforeCursor on inactive InputConnection 09-07 01:47:46.063 17027-17027/com.curtiswhite.www.sqlitedatabaseforephemeris W/IInputConnectionWrapper: getTextAfterCursor on inactive InputConnection

最佳答案

我解决了这个问题。

事实证明,该问题是在 LongClick 上扩展新菜单时引起的。这导致 SearchView 收缩(如预期),但按下回键(调用 OnBackPressed)后,原始菜单会膨胀,但放置在那里的 SearchView尚未实例化的新的。

为了纠正这个问题,我简单地调用了 OnCreateMenuOptions(toolbar.getMenu());在 onBackPressed 方法中。这将重新实例化 SearchView,以便它在菜单展开后再次工作。

关于java - SearchView 在 LongClick 操作后停止过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39361145/

相关文章:

java - Java 中使用对象作为参数的 AND 短路运算符

java - 编程记事本 - 使用 Java 打开新文件

android - 在哪里保存 Android GPS(纬度,经度)点?

android - ActionBarSherlock - SearchView 为空?

android - 使用 AppCompat 22.1.0 设置 AppCompat SearchView 样式不起作用

java - 在ide之外编辑的文件

java - 阻塞队列将等待元素出队多长时间?

android - Android Studio 测试中的颜色含义

android - android中通过url传递多个参数并在PHP中获取

android - 未调用可搜索 Activity