自定义ArrayAdapter的搜索行 - Android

时间:2015-01-04 18:06:45

标签: java android android-arrayadapter

我一直试图解决这个问题,但在这里找不到任何答案。 我正在尝试做的是使用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;

    }

任何想法?

1 个答案:

答案 0 :(得分:0)

删除filter方法。这不是使用适配器处理过滤的正确方法。 ArrayAdapter已经支持基本的过滤机制。只需:

productsAdapter.getFilter.filter(charsToSearch);

对于存储在适配器中的每个产品,它都会执行:

singleProduct.toString().toLowerCase().startsWith(charsToSearch);

如果startsWith()逻辑适用于您,则快速解决方案是覆盖toString()类的Product方法并让其返回getName()。否则,如果您想为过滤逻辑提供更自定义的解决方案,那么实际上只有两种解决方案可用:

  1. 使用BaseAdapter从头开始编写自己的适配器,并让它实现Filterable接口。虽然一个非常基本的实现并不是太糟糕,但如果你以前从未这样做过,那可能会非常艰巨。
  2. 利用现有的3rd party library,可以添加自己的过滤逻辑。
  3. 另请注意,使用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()方法看起来不错。