#android #listview #android-arrayadapter #android-listadapter
#Android #listview #android-arrayadapter #android-listadapter
Вопрос:
Я пытаюсь реализовать пользовательский счетчик с возможностью поиска в своей деятельности, но что-то не так в коде, и я не могу его найти. Посмотрите на скриншоты ниже, чтобы понять мою проблему.
snap1 Вот исходное представление списка с тремя элементами, и фильтр поиска еще не добавлен
snap2 Вот список после фильтра поиска
snap3 Вот список после удаления поиска.
Итак, как вы можете видеть на третьем снимке экрана, в listview не отображаются все три элемента после очистки фильтра поиска. Можете ли вы увидеть, какую ошибку я допускаю в своем коде?
ListAdapter.java
public class ListAdapter extends ArrayAdapter<SpinnerItem> {
private List<SpinnerItem> items;
private Context context;
private Filter filter;
public ListAdapter(@NonNull Context context, int resource, List<SpinnerItem> items) {
super(context, resource);
this.context = context;
this.items = items;
this.filter = new CustomItemsFilter();
}
@Nullable
@Override
public SpinnerItem getItem(int position) {
return items.get(position);
}
@Override
public int getCount() {
return items.size();
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rootView = inflater.inflate(R.layout.list_item,parent,false);
TextView textView = rootView.findViewById(R.id.itemTitle);
TextView textView1 = rootView.findViewById(R.id.itemSubTitle);
TextView textView2 = rootView.findViewById(R.id.itemSign);
textView.setText(items.get(position).getTitle());
textView1.setText(items.get(position).getSubTitle());
textView2.setText(items.get(position).getSign());
return rootView;
}
@NonNull
@Override
public Filter getFilter() {
if(filter == null) {
filter = new CustomItemsFilter();
}
return filter;
}
private class CustomItemsFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if(constraint != null amp;amp; constraint.toString().length() > 0) {
constraint = constraint.toString().toLowerCase();
List<SpinnerItem> allItems = new ArrayList<SpinnerItem>();
List<SpinnerItem> filterItems = new ArrayList<SpinnerItem>();
synchronized (this) {
allItems.addAll(items);
}
for (int i = 0; i < allItems.size(); i) {
SpinnerItem item = allItems.get(i);
if(item.getTitle().contains(constraint) || item.getSubTitle().contains(constraint) || item.getSign().contains(constraint)) {
filterItems.add(item);
}
}
filterResults.count = filterItems.size();
filterResults.values = filterItems;
}
else {
synchronized (this) {
filterResults.values = items;
filterResults.count = items.size();
}
}
return filterResults;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if(results.count > 0) {
items = (List<SpinnerItem>) results.values;
notifyDataSetChanged();
}
}
}
}
SpinnerDialog.java
public class SpinnerDiaglog implements SearchView.OnCloseListener, SearchView.OnQueryTextListener{
private List<SpinnerItem> items;
private OnSpinnerItemClick onSpinnerItemClick;
private Activity context;
private SearchView searchView;
private DialogInterface.OnClickListener onClickListener;
private ListAdapter adapter;
private OnSearchTextChanged onSearchTextChanged;
private ListView listView;
private AlertDialog dialog;
public SpinnerDiaglog() {
}
public SpinnerDiaglog(Activity context, List<SpinnerItem> items) {
this.context = context;
this.items = items;
}
public void onCreateDialog() {
View rootView = context.getLayoutInflater().inflate(R.layout.spinner_dialog,null);
//setData(rootView);
AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
alertDialog.setView(rootView);
alertDialog.setPositiveButton("CLOSE",onClickListener);
alertDialog.setTitle("Select Item");
SearchManager searchManager = (SearchManager) context.getSystemService(Context
.SEARCH_SERVICE);
searchView = rootView.findViewById(R.id.search);
searchView.setSearchableInfo(searchManager.getSearchableInfo(context.getComponentName()));
searchView.setOnQueryTextListener(this);
searchView.setOnCloseListener(this);
searchView.setIconifiedByDefault(false);
searchView.clearFocus();
listView = rootView.findViewById(R.id.listItems);
adapter = new ListAdapter(context,R.layout.list_item,items);
listView.setAdapter(adapter);
dialog = alertDialog.create();
dialog.show();
listView.setOnItemClickListener((parent, view, position, id) -> {
onSpinnerItemClick.onClick(adapter.getItem(position),position);
dialog.dismiss();
});
}
public void setOnSpinnerItemClickListener(OnSpinnerItemClick onSpinnerItemClick) {
this.onSpinnerItemClick = onSpinnerItemClick;
}
public void setOnSearchTextChangedListener(OnSearchTextChanged onSearchTextChanged) {
this.onSearchTextChanged = onSearchTextChanged;
}
@Override
public boolean onQueryTextSubmit(String query) {
searchView.clearFocus();
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
if(TextUtils.isEmpty(newText)) {
((ListAdapter) listView.getAdapter()).getFilter().filter(null);
}
else {
((ListAdapter) listView.getAdapter()).getFilter().filter(newText);
}
if (null != onSearchTextChanged) {
onSearchTextChanged.onSearchTextChanged(newText);
}
return true;
}
public interface OnSpinnerItemClick {
void onClick(SpinnerItem item, int position);
}
public interface OnSearchTextChanged {
void onSearchTextChanged(String strText);
}
@Override
public boolean onClose() {
return false;
}
}
MainActivity.java
public class MainActivity2 extends AppCompatActivity {
private SpinnerDiaglog spinnerDiaglog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Button button = findViewById(R.id.show);
List<SpinnerItem> items = new ArrayList<>();
items.add(new SpinnerItemImp("Title","subTitle","sign"));
items.add(new SpinnerItemImp("aitle","subTitle","sign"));
items.add(new SpinnerItemImp("Tiastle","subTitle","sign"));
button.setOnClickListener(v -> {
spinnerDiaglog = new SpinnerDiaglog(MainActivity2.this,items);
spinnerDiaglog.onCreateDialog();
});
}
}
SpinnerItemImp.java
public class SpinnerItemImp implements SpinnerItem {
private String title;
private String subTitle;
private String sign;
public SpinnerItemImp(String title, String subTitle, String sign) {
this.title = title;
this.subTitle = subTitle;
this.sign = sign;
}
@Override
public String getTitle() {
return title;
}
@Override
public String getSubTitle() {
return subTitle;
}
@Override
public String getSign() {
return sign;
}
}
Ответ №1:
Вы сохраняете единый список, items
который изменяется при первом применении фильтра. Итак, при следующем фильтре вы фактически фильтруете из отфильтрованного списка, а не из фактического списка.
Вам необходимо вести полный список отдельно и применять к нему фильтр, а не в отфильтрованном списке. Ниже приведен пример:
public class ListAdapter extends ArrayAdapter<SpinnerItem> {
private List<SpinnerItem> items;
private List<SpinnerItem> allItems;
private Context context;
private Filter filter;
public ListAdapter(@NonNull Context context, int resource, List<SpinnerItem> items) {
super(context, resource);
this.context = context;
this.items = items;
this.filter = new CustomItemsFilter();
allItems=new ArrayList<>(items);
}
@Override
public SpinnerItem getItem(int position) {
return items.get(position);
}
@Override
public int getCount() {
return items.size();
}
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rootView = inflater.inflate(R.layout.list_item,parent,false);
return rootView;
}
@NonNull
@Override
public Filter getFilter() {
if(filter == null) {
filter = new CustomItemsFilter();
}
return filter;
}
private class CustomItemsFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
items.clear();
FilterResults filterResults = new FilterResults();
constraint = constraint.toString().trim().toLowerCase();
if (constraint.length() > 0) {
for (int i = 0; i < allItems.size(); i) {
SpinnerItem item = allItems.get(i);
if (item.getTitle().contains(constraint) || item.getSubTitle().contains(constraint) || item.getSign().contains(constraint)) {
items.add(item);
}
}
} else {
items.addAll(allItems);
}
filterResults.values = items;
filterResults.count = items.size();
return filterResults;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
items = (List<SpinnerItem>) results.values;
notifyDataSetChanged();
}
}
}