使用异步建议的AutocompleteTextView无法显示下拉菜单

9

我在AutocompleteTextView上添加了TextChangedListener。在TextChangedListenerafterTextChanged()中,我调用AsyncTask从网络加载数据(因为列表可能很大,所以在活动启动时加载所有数据不是一个好选择,这只会浪费流量)。 AsyncTaskonPostExecute()代码如下(我使用ArrayAdapter):

    @Override
    protected void onPostExecute(ArrayList<Subregion> result)
    {
        super.onPostExecute(result);
        if (result != null)
        {
            adapter.clear();
            for (Iterator<Subregion> iterator = result.iterator(); iterator.hasNext();)
            {
                Subregion subregion = iterator.next();
                adapter.add(subregion);
            }
            adapter.notifyDataSetChanged();
            autocompleteTextView.showDropDown();
        }
    }

Subregion 是我的自定义对象,已经重写了 toString() 方法。我希望当用户开始输入时,程序可以开始加载数据,并在接收和解析后立即显示结果。

我的问题:

autocompleteTextView.showDropDown() 没有效果。虽然 onPostExecute() 接收到了正确的数据列表,并将它们添加到适配器中,但是 showDropDown() 不会显示下拉框。这是什么问题?

4个回答

19

我正在做完全相同的事情,我刚刚实现了这个功能。不要清除适配器并单独构建它,而是按以下方式设置适配器(我在onPostExecute中调用一个函数来执行此操作):

//suggestions is a string array of suggestions.
suggestAdapter = new ArrayAdapter<String>(this, R.layout.suggestions, suggestions);
//The autocomplete view 
suggestions.setAdapter(this.suggestAdapter);
suggestAdapter.notifyDataSetChanged();

您无需显式调用showdropdown,当适配器通知自动完成视图已更改数据时,自动完成视图会自动更新。

您也可以调用

adapter.setNotifyOnChange(true)

这使得调用变得不必要。

adapter.notifyDatasetChanged()

请查看setNotifyOnChange方法。


6

我也遇到了这个问题。我的完成阈值是2。当输入两个字符时,我从服务器获取数据并填充数组适配器,但是autoRailwayFrom.showDropDown();没有显示下拉框...

我只需在一行上写就可以解决问题...

autoRailwayFrom.setText(autoRailwayFrom.getText());
adapterFrom.notifyDataSetChanged();
autoRailwayFrom.showDropDown();

1
重写这段代码确实帮了我很多,它让整个过程在我的onResponse中重新启动。非常感谢! - upisdown
1
问题在于它会将光标移动到EditText视图的开头。 - kassim

1
这个问题已经被回答了,但我认为回答得不够好 - 对于所有人来说,关键在于可过滤的用户界面。这里有一个基于BaseAdapter的适配器的工作示例。这里缺少的部分是通信(我使用了Retrofit):
public class UsersAutoAdapter extends BaseAdapter implements Filterable
{
    {
        DaggerGraphManager.INSTANCE.inject(this);
    }

    @Inject
    CommunicationManager mCommunicationManager;

    private FindUserResponse mFindUserResponse;

    @Override
    public int getCount()
    {
        if (mFindUserResponse != null && mFindUserResponse.mUsers != null)
        {
            return mFindUserResponse.mUsers.size();
        }

        return 0;
    }

    @Override
    public Object getItem(int i)
    {
        return mFindUserResponse.mUsers.get(i);
    }

    @Override
    public long getItemId(int i)
    {
        return i;
    }

    @Override
    public View getView(int i, View pView, ViewGroup pViewGroup)
    {
        if (pView == null)
        {
            LayoutInflater inflater = LayoutInflater.from(pViewGroup.getContext());
            pView = inflater.inflate(R.layout.ac_item_user, pViewGroup, false);
        }
        TextView textViewUserName = (TextView) pView.findViewById(R.id.text_view_user_name);
        textViewUserName.setText(mFindUserResponse.mUsers.get(i).mUserName);


        return pView;
    }

    @Override
    public Filter getFilter()
    {
        return new Filter()
        {
            //this method is called async (not from UI thread!) so making network request is possible here
            @Override
            protected FilterResults performFiltering(CharSequence pCharSequence)
            {

                if (pCharSequence != null && pCharSequence.length() >= 3)
                {
                    FindUserResponse users = mCommunicationManager.findUsersSync(pCharSequence.toString());

                    FilterResults results = new FilterResults();

                    results.values = users;
                    results.count = users.mUsers.size();

                    return results;
                }
                return null;
            }

            //this is UI thread called method (just after performFiltering returns it's results
            @Override
            protected void publishResults(CharSequence pCharSequence, FilterResults pFilterResults)
            {
                if (pFilterResults != null)
                {
                    mFindUserResponse = (FindUserResponse) pFilterResults.values;
                    notifyDataSetInvalidated();
                }
            }
        };
    }
}

0
在Retrofit API调用中遇到了这个问题。 通过将以下代码保留在Retrofit的onResponse方法中解决。不需要在onCreate方法中初始化适配器。 我的代码如下:
productListAdapter = new ArrayAdapter<>(getApplicationContext(), 
android.R.layout.simple_dropdown_item_1line, productList);

autoCompleteTextViewProductSearch.setAdapter(productListAdapter);
  productListAdapter.setNotifyOnChange(true);
  productListAdapter.notifyDataSetChanged();
  autoCompleteTextViewProductSearch.showDropDown();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接