【问题标题】:Searchview in actionbar in fragment片段中操作栏中的搜索视图
【发布时间】:2023-04-06 05:44:01
【问题描述】:

我正在创建一个安卓应用程序。在应用程序中,我有一个登录页面。登录后会显示一个用户列表。用户列表活动是 HomeActivity.java,其中包含两个名为 UserListFragment.javaChatFragment.java 的片段。用户列表正在从 firebase 显示。

UserListFragment.java 包含一个带有搜索菜单和注销菜单的操作栏。注销菜单工作正常,但搜索不起作用。搜索图标会显示,但是当我搜索某些内容时,它不会显示任何内容,即没有过滤器。我正在使用 firebase 来显示用户列表。

我不希望在 ChatFragment.java 中显示搜索视图

我尝试了各种不同的解决方案。但没有一个对我有用。

这里是代码。

UserListFragment.java

public class UsersListFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
Activity activity;
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private static final String TAG = "UsersListFragment";
private OnFragmentInteractionListener mListener;
private ListView listView;
private List<UserData> users;
private CustomAdapter adapter;
SharedPreferences.Editor preferenceEditor;
Timer myTimer;
View view;
ActionBar actionBar;
private static final String PREFRENCES_NAME = "setPreferences";
private ProgressDialog progressBar;
String partnerKeyValue;

// TODO: Rename and change types and number of parameters
public static UsersListFragment newInstance(String param1, String param2) {
    UsersListFragment fragment = new UsersListFragment();
    Bundle args = new Bundle();
    args.putString(ARG_PARAM1, param1);
    args.putString(ARG_PARAM2, param2);
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
   Global.getInstance().unreadMessageUsers.clear();
    progressBar = new ProgressDialog(getActivity());
    progressBar.setCancelable(false);
    progressBar.setMessage("Loading...");
    progressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    progressBar.setProgress(0);
    }

@Override
public void onCreateOptionsMenu(Menu menu,MenuInflater inflater) {

    inflater.inflate(R.menu.menu_userlist,menu);
    MenuItem item = menu.findItem(R.id.menuSearch);

    SearchView searchView = (SearchView)item.getActionView();

    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            Log.i(TAG,newText);
            adapter.getFilter().filter(newText);
            return true;
        }
    });

    super.onCreateOptionsMenu(menu,inflater);
}


private void logoutUser(){
    Intent I = new Intent(getActivity(), LoginActivity.class);
    startActivity(I);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {
        case R.id.menuSearch :
            return true;

        case R.id.menuLogout :
            logoutUser();
            return true;

        default:
            return super.onOptionsItemSelected(item);
    }

}

menu_userlist.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/menuSearch"
    android:title="@string/search"
    android:icon="@drawable/ic_search"
    app:actionViewClass="android.widget.SearchView"
    app:showAsAction="always">
</item>

<item android:id="@+id/menuLogout"
    android:title="@string/logout"
    android:icon="@drawable/ic_logout"
    app:showAsAction="always">
</item>

CustomAdapter.java

@Override
public Filter getFilter() {
    Filter filter = new Filter() {

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint,FilterResults results) {

            users = (List<UserData>) results.values; // has the filtered values
            notifyDataSetChanged();  // notifies the data with new filtered values
        }

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new Filter.FilterResults();       

            List<String> FilteredArrList = new ArrayList<String>();

                if (mOriginalValues != null) {

                if (constraint == null || constraint.length() == 0) {

                    // set the Original result to return
                    results.count = mOriginalValues.size();
                    results.values = mOriginalValues;
                } else {
                    constraint = constraint.toString().toLowerCase();
                    for (int i = 0; i < mOriginalValues.size(); i++) {
                        String data = mOriginalValues.get(i).toString();
                        if (data.toLowerCase().contains(constraint.toString())) {
                            FilteredArrList.add(data);
                        }
                    }
                    // set the Filtered result to return
                    results.count = FilteredArrList.size();
                    results.values = FilteredArrList;
                }
            }

            return results;
        }
    };
    return filter;
}
}

【问题讨论】:

  • 你的过滤方法有效吗?你检查了results返回变量的值
  • @Dibzmania 我的 results 变量包含这个值 android.widget.Filter$FilterResults@5a9dec 每次我输入一些字母时,都会为它生成一些值我在搜索中输入的每个字母如上所述。我不知道它是什么。
  • @Dibzmania 我想我得到的是空值。当我尝试打印 results.values 时出现空异常错误。我该如何解决?
  • 您的过滤方法看起来不错。它可能会返回一个空结果,看看搜索字符串是否与任何数据不匹配。问题是您没有在适配器上设置过滤数据。调用 `adapter.getFilter().filter(newText);` 后,需要调用设置适配器数据与上一个方法的返回
  • @Dibzmania 你能提供代码吗?顺便说一句,感谢您的帮助。 :)

标签: android listview android-fragments android-fragmentactivity searchview


【解决方案1】:

更改以下代码段 -

@SuppressWarnings("unchecked")
    @Override
    protected void publishResults(CharSequence constraint,FilterResults results) {
        clear();
        addAll((List<UserData>) results.values)
        users = (List<UserData>) results.values; // has the filtered values

        notifyDataSetChanged();  // notifies the data with new filtered values
    }

这主要可以解决问题。但是您的源代码中有很多不一致之处。您正在扩展 ArrayAdpater,它已经实现了 Filterable 接口。

还要查看为什么需要以下状态变量 -

private List<UserData> messages;
private List<UserData> users;
private List<UserData> mOriginalValues;

请注意,您正在扩展ArrayAdapter,并且您在构造函数中传递了初始数据集。此后数据集的任何更改,您需要在父 ArrayAdapter 上重置它。仅更改子类中的状态变量是没有帮助的。

【讨论】:

  • 您建议的编辑代码导致应用崩溃。 private List&lt;UserData&gt; messages; private List&lt;UserData&gt; users; private List&lt;UserData&gt; mOriginalValues; users 和 mOrigninalValues 我用于过滤方法。我是 android 新手,因此使用了某些来源的代码。我用于未读消息计数的消息,我需要在用户名旁边显示。如果您可以为我提供一些更改并指导我,我应该更改什么。这对我真的很有帮助。非常感谢。 :)
  • 什么是崩溃堆栈跟踪?我实际上并没有运行代码,所以它很有可能。但想法是清除底层数据并添加新数据。
  • java.lang.NullPointerException:尝试在此行的空对象引用上调用接口方法“java.lang.Object[] java.util.Collection.toArray()”。 addAll((List) results.values);
  • 过滤器方法的返回值为 NULL。您需要添加 NULL 检查。
  • 好的。现在我没有收到任何错误。但是当我搜索时,列表变为空,没有搜索建议,关闭搜索菜单后,以前的列表也没有恢复。
【解决方案2】:

我自己解决了我的问题。它可能会帮助其他人。 :)

CustomAdapter.java

@Override
public Filter getFilter() {
    Filter filter = new Filter() {

        @SuppressWarnings("unchecked")
        @Override
        protected void publishResults(CharSequence constraint,
                                      FilterResults results) {
            clear();
            addAll((List<UserData>) results.values);
            arrayList = (List<UserData>)results.values;
            notifyDataSetChanged();
        }


        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();        // Holds the results of a filtering operation in values
            List<UserData> FilteredArrList = new ArrayList<UserData>();

            if (mOriginalValues == null) {
                mOriginalValues = new ArrayList<UserData>(arrayList); 
            }


            if (constraint == null || constraint.length() == 0) {
                results.count = mOriginalValues.size();
                results.values = mOriginalValues;
            } else {
                constraint = constraint.toString().toLowerCase();


                for (int i = 0; i < mOriginalValues.size(); i++) {
                    String data = mOriginalValues.get(i).getName();

                    if (data.toLowerCase().contains(constraint.toString())) {
                        FilteredArrList.add(mOriginalValues.get(i));
                    }
                }
                // set the Filtered result to return
                results.count = FilteredArrList.size();
                results.values = FilteredArrList;
            }

            return results;
        }

    };
    return filter;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-17
    • 2023-03-16
    • 2016-11-05
    • 2015-01-31
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    相关资源
    最近更新 更多