【问题标题】:Autocompletetextview with custom adapter and filter带有自定义适配器和过滤器的 Autocompletetextview
【发布时间】:2013-05-28 00:43:55
【问题描述】:

我正在尝试像这样为我的AutoCompleteTextView 设置一个自定义ArrayAdapter

public class AutoCompleteContactArrayAdapter extends
    ArrayAdapter<Map<String, String>> implements Filterable {
private Context mContext;
private List<Map<String, String>> mContactList;

public AutoCompleteContactArrayAdapter(Context context,
        List<Map<String, String>> objects) {
    super(context, R.layout.auto_contact_list, objects);
    mContext = context;
    mContactList = objects;
    // TODO Auto-generated constructor stub
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) mContext
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View rowView = inflater.inflate(R.layout.auto_contact_list, parent,
            false);
    TextView nameView = (TextView) rowView.findViewById(R.id.ccontName);
    TextView phoneView = (TextView) rowView.findViewById(R.id.ccontNo);
    TextView typeView = (TextView) rowView.findViewById(R.id.ccontType);
    Map<String, String> contactMap = mContactList.get(position);

    nameView.setText(contactMap.get("name"));
    phoneView.setText(contactMap.get("phone"));
    typeView.setText(contactMap.get("type"));

    return rowView;
}
@Override
public Filter getFilter() {
    return new Filter() {
        @Override
        protected void publishResults(CharSequence constraint,
                FilterResults results) {

            if (results.count > 0) {
                notifyDataSetChanged();
            } else {
                notifyDataSetInvalidated();
            }
        }

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            ArrayList<String> result = new ArrayList<String>();
            result.add("test");
            result.add("another");
            result.add("last");
            FilterResults r = new FilterResults();
            r.values = result;
            r.count = result.size();
            return r;
        }
    };
}
}

在调试中,应用程序正在输入 filter 方法 publishResults()performFiltering() 但显示的结果集不是我的测试 array [test,another,last] 而它只是显示所有结果忽略了我的过滤器。

【问题讨论】:

    标签: android


    【解决方案1】:

    这是我的代码的当前实现:

    xml

    <AutoCompleteTextView
        android:id="@+id/searchAutoComplete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginRight="10dp"
        android:layout_toRightOf="@+id/linearLayout1"
        android:background="@drawable/abs__textfield_search_default_holo_light"
        android:drawableLeft="@drawable/abs__ic_search_api_holo_light"
        android:drawableRight="@drawable/abs__ic_clear_holo_light"
        android:hint="@string/search"
        android:imeOptions="actionSearch"
        android:inputType="textAutoComplete|textAutoCorrect" >
    

    适配器:

    import java.util.ArrayList;
    import java.util.List;
    
    import android.content.Context;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.Filter;
    import android.widget.Filterable;
    
    public class AutoCompleteAdapter extends ArrayAdapter<String> implements Filterable {
    
        private ArrayList<String> fullList;
        private ArrayList<String> mOriginalValues;
        private ArrayFilter mFilter;
    
        public AutoCompleteAdapter(Context context, int resource, int textViewResourceId, List<String> objects) {
    
            super(context, resource, textViewResourceId, objects);
            fullList = (ArrayList<String>) objects;
            mOriginalValues = new ArrayList<String>(fullList);
    
        }
    
        @Override
        public int getCount() {
            return fullList.size();
        }
    
        @Override
        public String getItem(int position) {
            return fullList.get(position);
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            return super.getView(position, convertView, parent);
        }
    
        @Override
        public Filter getFilter() {
            if (mFilter == null) {
                mFilter = new ArrayFilter();
            }
            return mFilter;
        }
    
    
        private class ArrayFilter extends Filter {
            private Object lock;
    
            @Override
            protected FilterResults performFiltering(CharSequence prefix) {
                FilterResults results = new FilterResults();
    
                if (mOriginalValues == null) {
                    synchronized (lock) {
                        mOriginalValues = new ArrayList<String>(fullList);
                    }
                }
    
                if (prefix == null || prefix.length() == 0) {
                    synchronized (lock) {
                        ArrayList<String> list = new ArrayList<String>(mOriginalValues);
                        results.values = list;
                        results.count = list.size();
                    }
                } else {
                    final String prefixString = prefix.toString().toLowerCase();
    
                    ArrayList<String> values = mOriginalValues;
                    int count = values.size();
    
                    ArrayList<String> newValues = new ArrayList<String>(count);
    
                    for (int i = 0; i < count; i++) {
                        String item = values.get(i);
                        if (item.toLowerCase().contains(prefixString)) {
                            newValues.add(item);
                        }
    
                    }
    
                    results.values = newValues;
                    results.count = newValues.size();
                }
    
                return results;
            }
    
            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
    
            if(results.values!=null){
            fullList = (ArrayList<String>) results.values;
            }else{
                fullList = new ArrayList<String>();
            }
                if (results.count > 0) {
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            }
        }
    }
    

    最后在代码中像这样初始化......

           ArrayList<String> searchArrayList= new ArrayList<String>();
    //initilaze this array with your data
            AutoCompleteAdapter adapter = new AutoCompleteAdapter(this, android.R.layout.simple_dropdown_item_1line, android.R.id.text1, searchArrayList);
            autoCompleteTextView = (AutoCompleteTextView) customNav.findViewById(R.id.searchAutoComplete);
            autoCompleteTextView.setAdapter(adapter);
    

    完成:)

    【讨论】:

    • 嗨,除了mOriginalValues,我几乎都懂。我不明白我们需要它。请给我解释一下好吗?
    • 这不是一个优化的代码,您可以根据需要更改:)
    • +1 非常好的解决方案。感谢你的分享。你拯救了我的一天。非常感谢你;)
    • 是的,sooper good SOLUTION 它的作品 100% :) 非常感谢 Ali Imran
    • 为什么您使用synchronized (lock) 仅用于清除列表而不用于分配新值? @AliImran
    【解决方案2】:

    好的,我想我明白 Luksprog 说的是什么,这段代码现在可以工作了,关键是这个

    mContactList = (ArrayList<Map<String, String>>) results.values;
    

    @Override
    public int getCount(){
        return mContactList.size();
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = (LayoutInflater) mContext
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View rowView = inflater.inflate(R.layout.auto_contact_list, parent,
                false);
        TextView nameView = (TextView) rowView.findViewById(R.id.ccontName);
        TextView phoneView = (TextView) rowView.findViewById(R.id.ccontNo);
        TextView typeView = (TextView) rowView.findViewById(R.id.ccontType);
        Map<String, String> contactMap = mContactList.get(position);
    
        nameView.setText(contactMap.get("name"));
        phoneView.setText(contactMap.get("phone"));
        typeView.setText(contactMap.get("type"));
    
        return rowView;
    }
    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected void publishResults(CharSequence constraint,
                    FilterResults results) {
    
                if (results.count > 0) {
                    mContactList = (ArrayList<Map<String, String>>) results.values;
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            }
    
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                ArrayList<Map<String, String>> result = new ArrayList<Map<String, String>>();
                HashMap<String,String> myMap = new HashMap<String,String>();
                myMap.put("name", "key");
                result.add(myMap);
                HashMap<String,String> myMap2 = new HashMap<String,String>();
                myMap2.put("name", "is");
                result.add(myMap2);
                HashMap<String,String> myMap3 = new HashMap<String,String>();
                myMap3.put("name", "another");
                result.add(myMap3);
                FilterResults r = new FilterResults();
                r.values = result;
                r.count = result.size();
                return r;
            }
        };
    }
    

    【讨论】:

      【解决方案3】:

      Autocompletetextview 使用 Adapter 显示自动完成建议下拉菜单。

      适配器应该是可过滤的,并且应该为数据列表中的每个项目提供视图填充数据。 Autocompletetextview 使用适配器中定义的过滤器来获取结果并显示它们。

      所以,如果你需要创建自定义适配器,你需要提供getView的实现,并提供一个过滤器类。

      完整的工作示例 autocompletetextview 自定义布局和自定义适配器

      http://www.zoftino.com/android-autocompletetextview-custom-layout-and-adapter

      【讨论】:

        【解决方案4】:

        如果你想添加数据

        String[] arr=new String[100];

        那就错了。 您可以执行与 ArrayList 形式相同的工作,但请记住,您永远不会在此处放置 Getter/Setter 类。只需简单地声明它。请参阅此示例。

        在主分区中声明:

           ArrayList<String>arr=new ArrayList<>();
        

        然后以这种方式初始化它:

        for (int i = 0; i < jsonArray.length(); i++) {
                        JSONObject jsonObject1 = (JSONObject) jsonArray.get(i);
                        String imei = jsonObject1.getString("imei");
                        String name = jsonObject1.getString("name");
                        String my_pic = jsonObject1.getString("my_pic");
                        String email = jsonObject1.getString("email");
        
                        arr.add(name);
                    }
        
        
                    adapter= new ArrayAdapter<>
                            (this, android.R.layout.select_dialog_item, arr);
                    autoCompleteText.setThreshold(1);//will start working from first character
                    autoCompleteText.setAdapter(adapter);//setting the adapter data into the AutoCompleteTextView
                    autoCompleteText.setTextColor(Color.RED);
        
        
                }
        

        我希望这对你有用。祝你好运

        【讨论】:

          【解决方案5】:

          任何对 Kotlin 版本感兴趣的人都可以在下面找到。

          val ac = findViewById<AutoCompleteTextView>(R.id.searchAutoComplete)
          var dataList = listOf("argument", "aid", "appear", "air", "advertise", "appendix", "apathy", "absence", "analysis",
              "bind", "bathroom", "broadcast", "bomb", "build", "bark", "beef", "brain", "bend",
              "conviction", "coincide", "castle", "cafe", "chemistry", "clean", "closed", "composer", "care", "crude")
          ac.setAdapter(object : ArrayAdapter<String>(
              context, android.R.layout.simple_dropdown_item_1line, android.R.id.text1, dataList,
          ), Filterable {
              private var oriValue = dataList.toList()
              override fun getCount() = dataList.size
              override fun getItem(position: Int) = dataList[position]
              override fun getFilter() = object : Filter() {
                  override fun performFiltering(prefix: CharSequence?) =
                      FilterResults().apply {
                          mutableListOf<String>().apply {
                              if (prefix == null || prefix.isEmpty()) addAll(oriValue)
                              else oriValue.map {
                                  if (it.contains(prefix.toString(), true)) // ignore case
                                  // if (it.contains(prefix.toString())) // match case
                                  // if (it.startsWith(prefix.toString(), true)) // start with
                                      add(it)
                              }
                              values = this
                              count = this.size
                          }
                      }
                  override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
                      @Suppress("UNCHECKED_CAST")
                      dataList = results?.values as List<String>? ?: listOf()
                      if (results?.count ?: -1 > 0) notifyDataSetChanged() 
                      else notifyDataSetInvalidated()
                  }
              }
          })
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-03-19
            • 1970-01-01
            • 2013-10-07
            • 1970-01-01
            • 2014-09-06
            • 2021-01-03
            • 1970-01-01
            相关资源
            最近更新 更多