AutoCompleteTextView适配器,"隐藏"适配器?

时间:2012-03-11 19:47:27

标签: android android-adapter

我有3个AutoCompleteTextViews,我想在它们上注册2个String []适配器。目前,我这样做:

atw_from.setAdapter(new ArrayAdapter(ctx, android.r.layout.simple_dropdown_item_1line, stages_adapter));

假设我的用户想要输入“Középmező”,他开始输入“Közé”,他将会选择Középmező,直到这个,它非常简单。但是如果用户懒得键入重音(并且很多都是懒惰的),那么他只会输入Kozepmezo,然后他就不会得到任何报价,因为我的String []中没有Kozepmezo。我想要的是,如果他输入“Koze”,他应该被提供给Középmező,所以即使他不使用口音,他也会一直提供带有重音的实际单词。

目前,我有一个非常愚蠢的解决方案,我有一个String [],其大小是原始[]的两倍,前半部分包含带重音的单词,第二个包含deaccented版本。所以现在,如果他打字Közé,他将被提供Középmező,如果他输入Koze,他将被提供Kozepmezo。它的工作原理是因为服务器可以处理这两个版本,但它看起来很愚蠢,我想解决它。

根据我的理解,我应该制作一个完整的自定义适配器。这是最好的方法,还是SDK中包含任何解决方案?如果我应该制作自定义适配器,有人能指出我正确的方向,如何做到这一点? :)

编辑:添加了我自己的答案,应该为每个人工作,为其他答案欢呼,这导致我朝着好方向前进!

3 个答案:

答案 0 :(得分:1)

我确实会选择自定义适配器,您可以在其中提供自己的过滤功能,以匹配重音和重音符号。

可以找到here的示例实现。基本上你需要在performFiltering中实现实际过滤 - 我假设你已经有办法去除查询,因为你目前正在使用deaccented版本填充你的String[]。您将需要将带有和不带重音符号的查询与数组中的条目进行比较(您将要使用和不使用重音符号)。最后,您应该至少进行以下四项测试:

accented(query) -> accented(entry)
accented(query) -> deaccented(entry)
deaccented(query) -> accented(entry)
deaccented(query) -> deaccented(entry)

通过即时解除单词,您只需要为String[]提供带重音的单词,而过滤逻辑(在您的适配器中)将处理与(de)重音单词的匹配。 / p> 如上所述

编辑,在我正在进行的一个项目中的示例实施下面。

一些指示:

  1. CustomArrayAdapter主要是一个简化常见任务的包装类;例如与行包装/视图持有者的交互。基本上它需要的是updateRow的构造函数和实现(显然将从超类'getView方法调用)。
  2. CustomRowWrapper应该非常简单。
  3. ArrayUtilArrayUtil.FilterFuction负责实际过滤。简单地说,这些作为for循环的替代,构建了符合某些标准的所有项目的新列表。

  4. public class CARMedicationSuggestionAdapter extends CustomArrayAdapter<CARMedicationInfo, RowWrapper> {
    
        private List<CARMedicationInfo> mMedications;
        private Filter mFilter;
    
        /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
         * constructor
         * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    
        public CARMedicationSuggestionAdapter(Context context, List<CARMedicationInfo> objects) {
            super(RowWrapper.class, context, R.layout.medication_suggestion_item_layout, objects);
            // keep copy of all items for lookups 
            mMedications = new ArrayList<CARMedicationInfo>(objects);
        }
    
        /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
         * update row
         * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    
        @Override protected void updateRow(RowWrapper wrapper, CARMedicationInfo item) {
            wrapper.getNameTextView().setText(item.toString());
        }
    
        /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
         * get filter
         * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    
        @Override public Filter getFilter() {
            // return if already created
            if (mFilter != null) return mFilter;
            mFilter = new Filter() {
                @Override protected void publishResults(CharSequence constraint, FilterResults results) {
                    @SuppressWarnings("unchecked") List<CARMedicationInfo> filtered = (List<CARMedicationInfo>) results.values;
                    if (results == null || results.count == 0) return;
                    // clear out current suggestions and add all new ones
                    clear(); 
                    addAll(filtered);
                }
    
                @Override protected FilterResults performFiltering(final CharSequence constraint) {
                    // return empty results for 'null' constraint
                    if (constraint == null) return new FilterResults();
                    // get all medications that contain the constraint in drug name, trade name or whose string representation start with the constraint
                    List<CARMedicationInfo> suggestions = ArrayUtil.filter(mMedications, new ArrayUtil.FilterFunction<CARMedicationInfo>() {
                        @Override public boolean filter(CARMedicationInfo item) {
                            String query = constraint.toString().toLowerCase().trim();
                            return  item.mMedicationDrugName.toLowerCase().contains(query) || 
                                    item.mMedicationTradeName.toLowerCase().contains(query) ||
                                    item.toString().toLowerCase().startsWith(query); 
                        }
                    });
                    // set results and size
                    FilterResults filterResults = new FilterResults();
                    filterResults.values = suggestions;
                    filterResults.count = suggestions.size();
                    return filterResults;
                }
            };
            return mFilter;
        }
    
        /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
         * row wrapper
         * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    
        static class RowWrapper extends CustomRowWrapper {
    
            private ImageView mIconImageView;
            private TextView mNameTextView;
    
            public RowWrapper(View row) {
                super(row);
            }
    
            public ImageView getIconImageView() {
                if (mIconImageView == null) mIconImageView = (ImageView) mRow.findViewById(R.id.icon_imageview);
                return mIconImageView;
            }
    
            public TextView getNameTextView() {
                if (mNameTextView == null) mNameTextView = (TextView) mRow.findViewById(R.id.name_textview);
                return mNameTextView;
            }
    
        }
    
    }
    

答案 1 :(得分:1)

Okey,在经历了很多关于这个问题的痛苦之后,这就是我最后做的事情。这根本不是一个好习惯,我可能做错了,但至少它现在工作得很好。

只需按ctrl + c,ctrl + v BaseAdapter的源代码,然后按ctrl + c,ctrl + v ArrayAdapter的源代码。现在看一下私有内部类ArrayFilter,尤其是performFiltering方法。修改(不要覆盖!)它,根据你的需要,在我的情况下,我添加了很多.replace(“x”,“y”)东西,用于去除部分。

无论我尝试了什么,要么产生不可预测的力量关闭(很多,完全随机的),或者我无法做到,因为太多的方法/变量是私有的,而不是受保护的。我必须说,谷歌应该重新审视这些代码...

注意:你真的不需要ctrl + c ctrl + v BaseAdapter代码,因为它是一个公共抽象类,但是,它不是那么多的代码,这样一切都在那里,显然你可以看到。

欢呼声

答案 2 :(得分:0)

看看这个帖子remove-accents-from-string和android Normalizer

[编辑] 或者您可以尝试使用两个数组merge-adapter