AutoCompleteTextView onItemClick 使用 HashMap 的项目位置或 id

发布于 2024-08-29 10:33:46 字数 656 浏览 3 评论 0原文

我是 Android 开发新手,遇到了一个很难解决的问题。我试图弄清楚如何正确使用 AutoCompleteTextView 小部件。我想使用来自 Web 服务的 XML 数据创建一个 AutoCompleteTextView。我设法让它工作,但我对输出肯定不满意。

我想放置一个 id => 的 HashMap名称对放入 AutoCompleteTextView 中并获取单击项目的 id。当我单击自动完成过滤集输出时,我想在自动完成框下方填充一个列表,我也设法开始工作。

到目前为止完成:

  • 自动完成对于简单的 ArrayList 效果很好,所有数据过滤正确的
  • 触发
  • onItemClick 事件在单击后正确

。 )的行为不符合我的意愿。如何找出单击的项目的未过滤数组位置?过滤后的位置是我不感兴趣的。

进一步的问题:

  • 如何在 AutoCompleteTextView 中处理 HashMaps 或 Collections
  • 如何在 onItemClick 事件中获取正确的 itemId

我对这个问题做了非常广泛的研究,但没有找到任何有价值的信息可以回答我的问题。

I am new to Android development and I ran into a problem which I find difficult to solve. I am trying to figure out how to use an AutoCompleteTextView widget properly. I want to create a AutoCompleteTextView, using XML data from a web service. I managed to get it to work, but I am defenitely not pleased with the output.

I would like to put a HashMap with id => name pairs into the AutoCompleteTextView and get the id of the clicked item. When I click on the autocomplete filtered set output, I want to populate a list underneath the autocompletion box, which I also managed to get to work.

Done so far:

  • autocomplete works well for simple ArrayList, all data filtered correct
  • onItemClick event fires properly after click
  • parent.getItemAtPosition(position) returns correct String representation of the clicked item

The event onItemClick(AdapterView parent, View v, int position, long id) does not behave as I would like. How can I figure out the unfiltered array position of the clicked item? The position of the filtered one is the one I am not interested in.

Further questions:

  • How to handle HashMaps or Collections in AutoCompleteTextView
  • How to get the right itemId in the onItemClick event

I did very extensive research on this issue, but did not find any valuable information which would answer my questions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

任谁 2024-09-05 10:33:46

如何在 AutoCompleteTextView 中处理 HashMap 或 Collections

您可以设置自己的自定义适配器。在适配器中,由您决定将数据获取到给定位置的位置。

如何在onItemClick事件中获取正确的itemId

在自定义适配器中,您定义一个过滤器,并且该过滤器设置建议的项目。您有两个不同的列表,一个包含原始值,另一个包含过滤后的项目。我的意思是这样的。

private class AutoCompleteItemAdapter extends ArrayAdapter<YourItemClass> implements Filterable {

    private NameFilter      mFilter;
    List<YourItemClass> suggestions;
    List<YourItemClass> mOriginalValues;

    public AutoCompleteItemAdapter(Context context, int resource, List<YourItemClass> suggestions) {
        super(context, resource, suggestions);
        this.suggestions = suggestions;
        this.mOriginalValues = suggestions;
    }

    public void updateData(List<YourItemClass> suggestions) {
               mLock.lock();
               try{
                   this.suggestions = suggestions;
                       this.mOriginalValues = suggestions;
            finally{
                mLock.unlock();
            }
        }

    @Override
    public int getCount() {
        mLock.lock();
        try {
            return suggestions.size();
        } finally {
            mLock.unlock();
        }
    }

    @Override
    public YourItemClass getItem(int position) {
        return mOriginalValues.get(position);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // draw your item here...
    }

    @Override
    public Filter getFilter() {
        if (mFilter == null) {
            mFilter = new NameFilter();
        }
        return mFilter;
    }

    private class NameFilter extends Filter {
        @Override
        protected FilterResults performFiltering(CharSequence prefix) {
            FilterResults results = new FilterResults();

            if (mOriginalValues == null) {
                mLock.lock();
                try {
                    mOriginalValues = new ArrayList<YourItemClass>(suggestions);
                } finally {
                    mLock.unlock();
                }
            }

            if (prefix == null || prefix.length() == 0) {
                mLock.lock();
                try {
                    ArrayList<YourItemClass> list = new ArrayList<YourItemClass>(mOriginalValues);
                    results.values = list;
                    results.count = list.size();
                } finally {
                    mLock.unlock();
                }
            } else {
                String prefixString = prefix.toString().toLowerCase();

                final List<YourItemClass> values = mOriginalValues;
                final int count = values.size();

                final ArrayList<YourItemClass> newValues = new ArrayList<YourItemClass>(count);

                //              FILTERING
                //
                    // add your hits to the newValues collection
                //
                //
                results.values = newValues;
                results.count = newValues.size();
            }
            return results;
        }


        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            mLock.lock();
            try {
                if (results == null || results.values == null) return; 
                suggestions = new ArrayList<YourItemClass>();
                suggestions = (List<YourItemClass>) results.values;
                if (results.count > 0) {
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            } finally {
                mLock.unlock();
            }
        }
    }
}

现在这可能会引发一些并发问题,当我们引用时,适配器可能会要求列表的大小,并且输出更大的值,这可能会导致 getView 函数出现问题。 (图:尝试用基础数据绘制 5 个元素,但只有 4 个元素,因为我们进行了另一次过滤)这就是我们使用 AutoCompleteTextView 的方式,到目前为止,效果很好,没有问题。我刚才提到我仍然很担心,而且我隐约感觉有更好的解决方案。

在 onClick 侦听器中,您使用返回的值(来自过滤列表)作为地图中的键,并获取关联的值。您可以认为您的列表使用了 HashMap 的索引。之后,您可以使用Map来绘制您的项目,或获取您自己的数据。

How to handle HashMaps or Collections in AutoCompleteTextView

You can set your own custom adapter. In your adapter it's up to you where you get your data to a given position.

How to get the right itemId in the onItemClick event

In your custom adapter, you define a filter, and that filter sets the suggested items. You have two different list, one with the original values, and another one with the filtered items. I mean something like this.

private class AutoCompleteItemAdapter extends ArrayAdapter<YourItemClass> implements Filterable {

    private NameFilter      mFilter;
    List<YourItemClass> suggestions;
    List<YourItemClass> mOriginalValues;

    public AutoCompleteItemAdapter(Context context, int resource, List<YourItemClass> suggestions) {
        super(context, resource, suggestions);
        this.suggestions = suggestions;
        this.mOriginalValues = suggestions;
    }

    public void updateData(List<YourItemClass> suggestions) {
               mLock.lock();
               try{
                   this.suggestions = suggestions;
                       this.mOriginalValues = suggestions;
            finally{
                mLock.unlock();
            }
        }

    @Override
    public int getCount() {
        mLock.lock();
        try {
            return suggestions.size();
        } finally {
            mLock.unlock();
        }
    }

    @Override
    public YourItemClass getItem(int position) {
        return mOriginalValues.get(position);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // draw your item here...
    }

    @Override
    public Filter getFilter() {
        if (mFilter == null) {
            mFilter = new NameFilter();
        }
        return mFilter;
    }

    private class NameFilter extends Filter {
        @Override
        protected FilterResults performFiltering(CharSequence prefix) {
            FilterResults results = new FilterResults();

            if (mOriginalValues == null) {
                mLock.lock();
                try {
                    mOriginalValues = new ArrayList<YourItemClass>(suggestions);
                } finally {
                    mLock.unlock();
                }
            }

            if (prefix == null || prefix.length() == 0) {
                mLock.lock();
                try {
                    ArrayList<YourItemClass> list = new ArrayList<YourItemClass>(mOriginalValues);
                    results.values = list;
                    results.count = list.size();
                } finally {
                    mLock.unlock();
                }
            } else {
                String prefixString = prefix.toString().toLowerCase();

                final List<YourItemClass> values = mOriginalValues;
                final int count = values.size();

                final ArrayList<YourItemClass> newValues = new ArrayList<YourItemClass>(count);

                //              FILTERING
                //
                    // add your hits to the newValues collection
                //
                //
                results.values = newValues;
                results.count = newValues.size();
            }
            return results;
        }


        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            mLock.lock();
            try {
                if (results == null || results.values == null) return; 
                suggestions = new ArrayList<YourItemClass>();
                suggestions = (List<YourItemClass>) results.values;
                if (results.count > 0) {
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            } finally {
                mLock.unlock();
            }
        }
    }
}

Now this might raise some concurrency issue, as we the reference, the adapter might ask for the size of the list, and a bigger value goes out, which might cause problem in the getView function. (fi.: Attempting to draw 5 element with the underlying data has only 4, because we did another filtering) This the way we used our AutoCompleteTextView, and so far it works great, no problem. I just mentioned that I'm still concerned, and I have this vague feeling that there is a better solution for this.

In your onClick listener, you use the returned value(from the filtered list) as the key in your map, and get the associated value. You can think your list you use an index for the HashMap. After that, you can use your Map to draw your item, or to get your own data.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文