如何使用工具栏搜索在片段的可扩展列表视图中进行搜索

How to use toolbar search to search in a fragment's expandable list view

我在片段中有一个可扩展列表视图,我想使用工具栏的搜索菜单在该片段中执行搜索。当我使用当前代码时,出现这样的错误。

java.lang.NullPointerException: Attempt to invoke virtual method 'void com.saikariapps.localforvocal.adapters.ListViewAdapter.fiterData(java.lang.String)' on a null object reference

我认为问题是我的工具栏搜索无法访问我的片段来搜索内容,但我是编程新手,所以我不确定。即使我必须改变一切,任何建议或其他事情都可能非常有帮助,所以请指出正确的方向。

这是我的代码。 HomeActitvity.java

package com.saikariapps.localforvocal.activities;

import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.core.view.MenuItemCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;

import android.app.SearchManager;
import android.content.Context;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ExpandableListAdapter;
import android.widget.SearchView;

import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.navigation.NavigationView;
import com.saikariapps.localforvocal.R;
import com.saikariapps.localforvocal.adapters.ListViewAdapter;
import com.saikariapps.localforvocal.fragments.HomeFragment;
import com.saikariapps.localforvocal.fragments.InfoFragment;
import com.saikariapps.localforvocal.fragments.ShareFragment;

public class HomeActivity extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener,
        NavigationView.OnNavigationItemSelectedListener, SearchView.OnQueryTextListener, SearchView.OnCloseListener {

    private SearchManager searchManager;
    private SearchView searchView;
    private MenuItem searchItem;
    BottomNavigationView bottomNavigationView;
    private DrawerLayout drawer;
    private ListViewAdapter mListAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);

        bottomNavigationView = findViewById(R.id.bottom_navigation);
        bottomNavigationView.setOnNavigationItemSelectedListener(this);

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


        drawer = findViewById(R.id.drawer_layout);

        NavigationView navigationView = findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);

        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar,
                R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        if (savedInstanceState == null) {
            displayFragment(new HomeFragment());
            navigationView.setCheckedItem(R.id.drawer_nav_home);
        }
    }

    private void displayFragment(Fragment fragment) {
        getSupportFragmentManager().beginTransaction().replace(R.id.content_area, fragment).commit();
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {

        Fragment fragment;

        switch (item.getItemId()) {
            case R.id.nav_home:
                fragment = new HomeFragment();
                break;
            case R.id.nav_why:
                fragment = new InfoFragment();
                break;
            case R.id.nav_share:
                fragment = new ShareFragment();
                break;
            case R.id.drawer_nav_home:
                fragment = new HomeFragment();
                break;
            case R.id.drawer_nav_info:
                fragment = new InfoFragment();
                break;
            case R.id.drawer_nav_share:
                fragment = new ShareFragment();
                break;
            default:
                fragment = new HomeFragment();
                break;
        }
        displayFragment(fragment);
        return true;
    }

    @Override
    public void onBackPressed() {
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.isDrawerOpen(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.toolbar_menu, menu);
        searchItem = menu.findItem(R.id.action_search);
        searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
        searchView.setIconifiedByDefault(false);
        searchView.setOnQueryTextListener(this);
        searchView.setOnCloseListener(this);
        searchView.requestFocus();
        return true;
    }

    @Override
    public boolean onClose() {
        mListAdapter.fiterData("");
        return false;
    }

    @Override
    public boolean onQueryTextSubmit(String query) {
        mListAdapter.fiterData(query);
        return false;
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        mListAdapter.fiterData(newText);
        return false;
    }
}

这是我的可扩展 ListView 适配器。

package com.saikariapps.localforvocal.adapters;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.TextView;


import com.saikariapps.localforvocal.R;
import com.saikariapps.localforvocal.models.Categories;
import com.saikariapps.localforvocal.models.Products;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class ListViewAdapter extends BaseExpandableListAdapter {

    private Context context;
    private ArrayList<Categories> lstGroups;
    private ArrayList<Categories> lstItemsGroups;

    public ListViewAdapter(Context context,ArrayList<Categories> data) {
        this.context = context;
        this.lstGroups = new ArrayList<Categories>();
        this.lstGroups.addAll(data);

        this.lstItemsGroups = new ArrayList<Categories>();
        this.lstItemsGroups.addAll(data);
    }

    @Override
    public int getGroupCount() {
        // returns groups count
        return lstGroups.size();
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        // returns items count of a group
        return lstGroups.get(groupPosition).getProducts().size();
    }

    @Override
    public Object getGroup(int groupPosition) {
        // returns a group
        return lstGroups.get(groupPosition);
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        // returns a group item
        return this.lstItemsGroups.get(groupPosition).getProducts().get(childPosition);
    }

    @Override
    public long getGroupId(int groupPosition) {
        // return the group id
        return groupPosition;
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        // returns the item id of group
        return childPosition;
    }

    @Override
    public boolean hasStableIds() {
        // returns if the ids are specific ( unique for each group or item)
        // or relatives
        return false;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
        // create main items (groups)
        if (convertView == null) {
            LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = layoutInflater.inflate(R.layout.list_group, null);
        }

        Categories categories = (Categories) getGroup(groupPosition);

        TextView headText = convertView.findViewById(R.id.headText);
        ImageView imageView = convertView.findViewById(R.id.headImg);
        headText.setText(categories.getCatName());
        imageView.setImageResource(categories.getCatThumb());

        return convertView;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        // create the subitems (items of groups)

        if (convertView == null) {
            LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = layoutInflater.inflate(R.layout.list_item, null);
        }

        TextView itemText = convertView.findViewById(R.id.itemText);
        TextView itemText2 = convertView.findViewById(R.id.itemText2);

        Products products = (Products) getChild(groupPosition, childPosition);
        itemText.setText(products.getName());
        itemText2.setText(products.getAmount());

        return convertView;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }

    public void fiterData(String query){
        query = query.toLowerCase();
        lstGroups.clear();

        if (query.isEmpty()){
            lstGroups.addAll(lstItemsGroups);
        }else {
            for (Categories categories: lstItemsGroups) {
                ArrayList<Products> list = categories.getProducts();
                ArrayList<Products> newList = new ArrayList<>();

                for (Products products: list){
                    if (products.getName().toLowerCase().contains(query)){
                        newList.add(products);
                    }
                }
                if (newList.size() > 0){
                    Categories mCategories = new Categories(categories.getCatName(),0, newList);
                    lstGroups.add(mCategories);
                }
            }
        }
        notifyDataSetChanged();
    }
}

这是我的主页片段。

package com.saikariapps.localforvocal.fragments;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.saikariapps.localforvocal.R;
import com.saikariapps.localforvocal.adapters.ListViewAdapter;
import com.saikariapps.localforvocal.models.Categories;
import com.saikariapps.localforvocal.models.Products;

import java.util.ArrayList;
public class HomeFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_home, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        ExpandableListView elvInvestments = view.findViewById(R.id.elvProducts);
        ArrayList<Categories> categories = new ArrayList<>();
        categories = populateCategoriesData(categories);
        ListViewAdapter adapter = new ListViewAdapter(getActivity(), categories);
        elvInvestments.setAdapter(adapter);

    }

    private ArrayList<Categories> populateCategoriesData(ArrayList<Categories> categories){
        Categories lstCat1 = new Categories("category1", R.drawable.ic_home,null);
        ArrayList<Products> catPro1 = new ArrayList<>();
        catPro1.add(new Products("indPro1", "forPro1"));
        catPro1.add(new Products("indPro2", "forPro2"));
        catPro1.add(new Products("indPro3", "forPro3"));
        catPro1.add(new Products("indPro4", "forPro4"));
        lstCat1.setProducts(catPro1);
        categories.add(lstCat1);

        Categories lstCat2 = new Categories("category2", R.drawable.ic_info,null);
        ArrayList<Products> catPro2 = new ArrayList<>();
        catPro2.add(new Products("indPro1.1", "forPro1.1"));
        catPro2.add(new Products("indPro2", "forPro2"));
        catPro2.add(new Products("indPro3", "forPro3"));
        catPro2.add(new Products("indPro4", "forPro4"));
        lstCat2.setProducts(catPro2);
        categories.add(lstCat2);

        Categories lstCat3 = new Categories("category3", R.drawable.ic_share,null);
        ArrayList<Products> catPro3 = new ArrayList<>();
        catPro3.add(new Products("indPro1.3", "forPro1.3"));
        catPro3.add(new Products("indPro2", "forPro2"));
        catPro3.add(new Products("indPro3", "forPro3"));
        catPro3.add(new Products("indPro4", "forPro4"));
        lstCat3.setProducts(catPro3);
        categories.add(lstCat3);
        return categories;
    }


}

HomeActivity 中,您尚未初始化 mListAdapter,但您正在通过以下方法访问它:onClose()onQueryTextSubmit(String query)onQueryTextChange(String newText),例如 mListAdapter.filterData() 等等,但是你的 mListAdapternull,这就是它抛出 NullPointerException 的原因。

在您的 HomeActivityonCreate() 方法中执行如下操作:

ListViewAdapter mListAdapter = new ListViewAdapter(this , categories);

当然,您应该有 categories 列表。 (像在您的 HomeFragment 中创建它)