我一直试图解决这个问题,但在这里找不到任何答案。 我正在尝试做的是使用ArrayAdapter为自定义arrayList创建EditText搜索。
一切顺利,直到我实际搜索一个Object(在这个项目中命名为Product)。 当我搜索一个,意味着我将字符输入EditText时,列表变为空白,我看不到任何项目。
这是我的代码:
SearchActivity , receiving the ArrayList from the mainactivity :
public class SearchActivity extends Activity {
EditText editSearch;
ProductArrayAdapter productsAdapter;
ListView products;
static ArrayList<Product> viewList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
viewList = new ArrayList<Product>(MainActivity.listToBeSent);
Toast.makeText(getBaseContext(), viewList.get(1).getName(), Toast.LENGTH_LONG).show();
productsAdapter = new ProductArrayAdapter(this,
R.layout.layout_product, viewList);
products = (ListView) findViewById(R.id.listProducts);
products.setAdapter(productsAdapter);
editSearch = (EditText)findViewById(R.id.searchLine);
editSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String charsToSearch = editSearch.getText().toString().toLowerCase(Locale.getDefault());
productsAdapter.filter(charsToSearch);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s) {
String charsToSearch = editSearch.getText().toString().toLowerCase(Locale.getDefault());
productsAdapter.filter(charsToSearch);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.search, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
ProductArrayAdapter里面有filter()方法。
public class ProductArrayAdapter extends ArrayAdapter<Product> {
ArrayList<Product> products;
Context context;
int resource;
public ProductArrayAdapter(Context context, int resource,
ArrayList<Product> products) {
super(context, resource, products);
this.context=context;
this.resource=resource;
this.products=products;
}
public void filter(String charText) {
charText = charText.toLowerCase(Locale.getDefault());
this.products.clear();
if (charText.length() == 0) {
this.products.addAll(SearchActivity.viewList);
} else {
for (Product singleProduct : SearchActivity.viewList) {
if (singleProduct.getName().toLowerCase(Locale.getDefault())
.contains(charText)) {
products.add(singleProduct);
}
}
}
notifyDataSetChanged();
}
static class ViewContainer {
public TextView txtName;
public TextView txtDescription;
public TextView txtPrice;
public ImageView imgProduct;
public ImageView imgOnSale;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewContainer viewContainer;
View rowView = convertView;
// means that if it is the first time and we didn't yet inflate the
// view, so inflate it now. rowView gets the already built or non-exist
// convertView.
if (rowView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
rowView = inflater.inflate(resource, null);
viewContainer = new ViewContainer();
/*viewContainer.textName = (TextView) rowView
.findViewById(this.textViewResource);*/
viewContainer.txtName = (TextView) rowView
.findViewById(R.id.txtName);
viewContainer.txtDescription = (TextView) rowView
.findViewById(R.id.txtDescription);
viewContainer.txtPrice = (TextView) rowView
.findViewById(R.id.txtPrice);
viewContainer.imgProduct = (ImageView) rowView
.findViewById(R.id.productPic);
viewContainer.imgOnSale = (ImageView) rowView
.findViewById(R.id.onSaleImage);
// adding tag to each rowView , tag can be Object therefore
// viewContainer = Object.
rowView.setTag(viewContainer);
} else {
viewContainer = (ViewContainer) (rowView.getTag());
}
Toast.makeText(getContext(), products.get(1).getCategory(), Toast.LENGTH_LONG).show();
Toast.makeText(getContext(), products.get(2).getCategory(), Toast.LENGTH_LONG).show();
viewContainer.txtName.setText(products.get(position).getName());
viewContainer.txtDescription.setText(products.get(position).getDescription());
viewContainer.txtPrice.setText("Price: " + (products.get(position).getPrice().toString()));
viewContainer.imgProduct.setImageResource(products.get(position).getImage());
viewContainer.imgOnSale.setImageResource(R.drawable.logo_icon);
return rowView;
}
我认为主要问题在于viewContainer部分。
感谢您的帮助!
谢谢杰伊,刚刚编辑了我的代码,现在它确实过滤了一些项目,但似乎没有 通过右边的字符过滤,例如,当我搜索字母'r'时,它确实得到'r'作为charSequence,但它只显示第一个项目,而不是正确的项目。
以下是编辑过的相关行:
我输入的textChangeListener上的:
@Override
public void afterTextChanged(Editable s) {
String charsToSearch = editSearch.getText().toString().toLowerCase();
productsAdapter.getFilter().filter(charsToSearch);
}
并在ProductArrayAdapter上我将getView()方法更改为:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewContainer viewContainer;
//View rowView = convertView;
// means that if it is the first time and we didn't yet inflate the
// view, so inflate it now. rowView gets the already built or non-exist
// convertView.
if (convertView == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
convertView = inflater.inflate(resource, parent, false);
viewContainer = new ViewContainer();
viewContainer.txtName = (TextView) convertView
.findViewById(R.id.txtName);
viewContainer.txtDescription = (TextView) convertView
.findViewById(R.id.txtDescription);
viewContainer.txtPrice = (TextView) convertView
.findViewById(R.id.txtPrice);
viewContainer.imgProduct = (ImageView) convertView
.findViewById(R.id.productPic);
viewContainer.imgOnSale = (ImageView) convertView
.findViewById(R.id.onSaleImage);
// adding tag to each rowView , tag can be Object therefore
// viewContainer = Object.
convertView.setTag(viewContainer);
} else {
viewContainer = (ViewContainer) (convertView.getTag());
}
viewContainer.txtName.setText(products.get(position).getName());
viewContainer.txtDescription.setText(products.get(position).getDescription());
viewContainer.txtPrice.setText("Price: " + (products.get(position).getPrice().toString()));
viewContainer.imgProduct.setImageResource(products.get(position).getImage());
viewContainer.imgOnSale.setImageResource(R.drawable.logo_icon);
return convertView;
}
任何想法?
答案 0 :(得分:0)
删除filter
方法。这不是使用适配器处理过滤的正确方法。 ArrayAdapter
已经支持基本的过滤机制。只需:
productsAdapter.getFilter.filter(charsToSearch);
对于存储在适配器中的每个产品,它都会执行:
singleProduct.toString().toLowerCase().startsWith(charsToSearch);
如果startsWith()
逻辑适用于您,则快速解决方案是覆盖toString()
类的Product
方法并让其返回getName()
。否则,如果您想为过滤逻辑提供更自定义的解决方案,那么实际上只有两种解决方案可用:
BaseAdapter
从头开始编写自己的适配器,并让它实现Filterable
接口。虽然一个非常基本的实现并不是太糟糕,但如果你以前从未这样做过,那可能会非常艰巨。另请注意,使用ArrayAdapter
时,将自己的列表副本保留在超级构建的内容之外是非常危险的。特别是在过滤方面。无法保证用于构造适配器的列表与您在外部引用的列表相同。如需进一步阅读,go here。
对于getView()
方法,请确保使用getItem(position)
而不是直接引用products
。将Toasts
置于其中也不是一个好主意。显示列表时,您最终会看到大量Toasts
弹出。如果您需要debuging语句,请改用Log
。此外,您需要调整以下行:
rowView = inflater.inflate(resource, null);
viewContainer = new ViewContainer();
改为:
viewContainer = inflater.inflate(resouce, parent, false);
根本不需要rowView
变量。只需从方法中完全删除,然后替换为viewContainer
。否则,您的getView()
方法看起来不错。