listview的当前实现显示不同类别/部分的数据,具体取决于要显示的对象的变量。仅举例说明,如果数据集是例如{cat,one,red,five,orange,dog},结果列表视图将是{animals:cat,dog},{colors:red,orange},{numbers:one,five}。为此,我使用了我在网上找到的'SectionerAdapter'的变体,在我的例子中使用了自定义的ArrayAdapter<>对于每个部分。此代码提供的部分与任何Android设备的“设置”应用中的部分类似。
现在,我正在尝试过滤这些结果。如果输入“O”,列表将最终为:{animals:empty},{colors:orange},{numbers:one}。问题是我没有让它与整个列表一起工作,但仅限于其中一个部分。这就是为什么我试图在整个列表中使用另一种方法:ExpandableListView。
有人知道在ExpandableListView中过滤是否可行/容易?你们有什么例子我可以用来了解如何去做吗?
谢谢!
答案 0 :(得分:1)
我为我的一个项目做过类似的事情。我不在家,所以不幸的是我没有代码示例句柄。这是我如何完成这个 -
我使用自定义ArrayAdapter< T>作为我的SectionArrayAdapter< SectionedListItem>的基础。 SectionedListItem用作我可能想要在SectionedList中显示的每个项目的基类。 SectionedListItem定义了几个属性:
boolean isNewSection;
String sectionLabel;
这也可以是一个界面,不需要是一个类。将它作为一个类只对我的实现有意义。
然后,我将要显示的项目列表放在一个分段列表中,并在将它们应用到适配器之前对它们进行一些自定义排序。当我对列表进行排序时,我将空的SectionedListItems添加到应该开始新分段的索引中,将isNewSection属性设置为true。当SectionedArrayAdapter执行渲染时,它会查看isNewSection属性是否为true。如果确实如此,我会渲染节标题而不是默认列表项。
这将为您提供在过滤期间使用的单个列表,而不是一堆不同的列表。然而,它确实构成了它自己的挑战 - 您需要在过滤后重新排序列表和/或您需要忽略仅用于在过滤期间定义新节的SectionedListItems。
我并不是说这是最好的方法,只是我提出的方法:)
答案 1 :(得分:0)
请注意,此代码是作为原型的一部分编写的,所以它不是很干净或光滑:)但是,它应该让你朝着正确的方向前进。我还应该注意到InventoryListItem扩展了我的SectionedListItem类,它包含上面列出的属性。
/* -------------------------
* Class: InventoryAdapter
* ------------------------- */
private final class InventoryAdapter extends ArrayAdapter<InventoryListItem> implements Filterable {
/* -------------------------
* Fields
* ------------------------- */
private ArrayList<InventoryListItem> items;
private ArrayList<InventoryListItem> staticItems;
private int resource;
private InventoryFilter filter = null;
/* -------------------------
* Constructor
* ------------------------- */
public InventoryAdapter(Context context, int textViewResourceId, ArrayList<InventoryListItem> objects) {
super(context, textViewResourceId, objects);
items = objects;
resource = textViewResourceId;
staticItems = items;
}
/* -------------------------
* Private Methods
* ------------------------- */
private void addCategorySpan(SpannableString span, int startIndex, int endIndex, final String category) {
span.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
String categoryFilter = "cat://" + category;
filterList(categoryFilter, true);
}
}, startIndex, endIndex, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
}
/* -------------------------
* Public Methods
* ------------------------- */
// Properties
@Override
public int getCount() {
return items.size();
}
@Override
public InventoryListItem getItem(int position) {
return items.get(position);
}
@Override
public int getPosition(InventoryListItem item) {
return items.indexOf(item);
}
@Override
public long getItemId(int position) {
return items.get(position).id;
}
@Override
public boolean isEnabled(int position) {
return true;
}
// Methods
public Filter getFilter() {
if ( filter == null ) {
filter = new InventoryFilter();
}
return filter;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = null;
InventoryListItem item = items.get(position);
if ( item.startNewSection ) {
v = inflater.inflate(R.layout.sectioned_list_header, null);
TextView sectionText = (TextView)v.findViewById(R.id.list_header_title);
sectionText.setText(item.sectionName);
} else {
v = inflater.inflate(resource, null);
TextView nameText = (TextView)v.findViewById(R.id.inventory_list_item_name_text);
TextView qtyText = (TextView)v.findViewById(R.id.inventory_list_item_qty_text);
TextView brandText = (TextView)v.findViewById(R.id.inventory_list_item_brand_text);
final TextView categoryText = (TextView)v.findViewById(R.id.inventory_list_item_category_text);
nameText.setText(item.name);
String qty = Float.toString(item.remainingAmount) + " " + item.measurementAbbv;
qtyText.setText(qty);
brandText.setText(item.brand);
// Create our list of categories and patterns
String categories = "";
for ( int i = 0; i <= item.categories.size() - 1; i++ ) {
if ( categories.length() == 0 ) {
categories = item.categories.get(i);
} else {
categories += ", " + item.categories.get(i);
}
}
categoryText.setMovementMethod(LinkMovementMethod.getInstance());
categoryText.setText(categories, BufferType.SPANNABLE);
// Now creat our spannable text
SpannableString span = (SpannableString)categoryText.getText();
// Create our links and set our text
int startIndex = 0;
boolean stillLooking = true;
while ( stillLooking ) {
int commaIndex = categories.indexOf(", ", startIndex);
if ( commaIndex >= 0 ) {
final String spanText = categoryText.getText().toString().substring(startIndex, commaIndex);
addCategorySpan(span, startIndex, commaIndex, spanText);
startIndex = commaIndex + 2;
} else {
final String spanText = categoryText.getText().toString().substring(startIndex, categoryText.getText().toString().length());
addCategorySpan(span, startIndex, categoryText.getText().toString().length(), spanText);
stillLooking = false;
}
}
v.setTag(item.id);
}
return v;
}
/* -------------------------
* Class: InventoryFilter
* ------------------------- */
private class InventoryFilter extends Filter {
private Object lock = new Object();
/* -------------------------
* Protected Methods
* ------------------------- */
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if ( constraint == null || constraint.length() == 0 ) {
synchronized(lock) {
items = staticItems;
results.values = items;
results.count = items.size();
}
} else {
String searchString = constraint.toString();
// Do our category search
if ( searchString.startsWith("cat:") ) {
String trimmedSearch = searchString.substring(searchString.indexOf("://") + 3);
// Do our search
ArrayList<InventoryListItem> newItems = new ArrayList<InventoryListItem>();
for ( int i = 0; i <= items.size() - 1; i++ ) {
InventoryListItem item = items.get(i);
// See if we're a section, and if we have an item under us
if ( item.startNewSection && i < items.size() - 1 ) {
InventoryListItem next = items.get(i + 1);
if ( next.sectionName == item.sectionName ) {
if ( !next.startNewSection && next.categories.contains(trimmedSearch) ) {
newItems.add(item);
}
}
}
else if ( !item.startNewSection && item.categories.contains(trimmedSearch) ) {
newItems.add(item);
}
}
results.values = newItems;
results.count = newItems.size();
}
}
return results;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
//noinspection unchecked
items = (ArrayList<InventoryListItem>)results.values;
// Let the adapter know about the updated list
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
}