如何使用工具栏搜索在片段的可扩展列表视图中进行搜索
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()
等等,但是你的 mListAdapter
是 null
,这就是它抛出 NullPointerException
的原因。
在您的 HomeActivity
的 onCreate()
方法中执行如下操作:
ListViewAdapter mListAdapter = new ListViewAdapter(this , categories);
当然,您应该有 categories
列表。 (像在您的 HomeFragment
中创建它)
我在片段中有一个可扩展列表视图,我想使用工具栏的搜索菜单在该片段中执行搜索。当我使用当前代码时,出现这样的错误。
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()
等等,但是你的 mListAdapter
是 null
,这就是它抛出 NullPointerException
的原因。
在您的 HomeActivity
的 onCreate()
方法中执行如下操作:
ListViewAdapter mListAdapter = new ListViewAdapter(this , categories);
当然,您应该有 categories
列表。 (像在您的 HomeFragment
中创建它)