AutoCompleteTextView下拉内容动态更新

1.绪论
一般来说,使用AutoCompleteTextView这个控件是给用户输入时提供选择提示的,而这个提示的列表是预先设置进去的,后面不在改变。但在现实场景中,这并不能满足需求,大部分需求是这个提示列表需根据输入的关键字通过网络请求查询,然后将查询的结果展示出来,供用户选择。也就是说提示列表是动态变化的。这样的需求使用AutoCompleteTextView控件怎么实现呢?

2.AutoCompleteTextView源码分析
要实现上面的需求就必须要了解AutoCompleteTextView是怎么工作的,它的实现逻辑如下:

1.AutoCompleteTextView 继承 EditText
2.需要ListAdapter并且要继承Filter类
 

public <T extends ListAdapter & Filterable> void setAdapter(T adapter) {
        if (mObserver == null) {
            mObserver = new PopupDataSetObserver(this);
        } else if (mAdapter != null) {
            mAdapter.unregisterDataSetObserver(mObserver);
        }
        mAdapter = adapter;
        if (mAdapter != null) {
            //noinspection unchecked
            mFilter = ((Filterable) mAdapter).getFilter();
            adapter.registerDataSetObserver(mObserver);
        } else {
            mFilter = null;
        }
        mPopup.setAdapter(mAdapter);
    }

3.添加监听addTextChangedListener

addTextChangedListener(new MyWatcher());
//下面MyWatcher类的实现
private class MyWatcher implements TextWatcher {
        public void afterTextChanged(Editable s) {
            doAfterTextChanged();
        }
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            doBeforeTextChanged();
        }
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }
    }
    //此方法是记录下拉框的显示状态
    void doBeforeTextChanged() {
        if (mBlockCompletion) return;
        // when text is changed, inserted or deleted, we attempt to show the drop down
        mOpenBefore = isPopupShowing();
    }
    //此方法是根据输入的内容找到匹配项,通过下拉框展示出来
    void doAfterTextChanged() {
        if (mBlockCompletion) return;
        if (mOpenBefore && !isPopupShowing()) {
            return;
        }
        // the drop down is shown only when a minimum number of characters was typed in the text view
        if (enoughToFilter()) {
            if (mFilter != null) {
                mPopupCanBeUpdated = true;
                performFiltering(getText(), mLastKeyCode);
            }
        } else {
            // drop down is automatically dismissed when enough characters are deleted from the text view
            if (!mPopup.isDropDownAlwaysVisible()) {
                dismissDropDown();
            }
            if (mFilter != null) {
                mFilter.filter(null);
            }
        }
    }

4.通过Filter类来找到匹配项,并通过popwindow展示出来

3.实现思路
从源码来看,当EditText内容改变时,就会立马从提示列表中找出匹配项,并展示出来;根本来不及去网络请求,然后将请求结果更新提示列表,再进行筛选。
或许此时,会有这样的一个想法,将网络请求更新提示列表这个动作放在Filter之前
执行不就好了。这个想法不可行,因为AutoCompleteTextView执行流程是不可控的。
既然流程不可控,那是否可以重新执行一遍此流程呢?当我们请求网络后,将结果更新提示列表,然后让系统重新执行doAfterTextChanged这个方法不就可以了么?很激动!!!

4.解决方案
想法很关键,代码实现不难,所以上面重点将源码分析和思路说了一下,当你认真看懂了源码,看懂系统是怎么实现此功能的,你才能在系统的基础上新增功能来实现自己的需求。下面是实现步骤:

1.监听EditText的addTextChangedListener
2.根据输入的内容请求网络,获取提示列表
3.更新列表,调用AutoCompleteTextView类的doAfterTextChanged方法,筛选并弹框

关键代码如下:
 

//添加兼听
       autoTVCheck.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }
            @Override
            public void afterTextChanged(Editable editable) {
                long time = DateUtil.getCurrentTimeInMills();
                //输入的字符间隔时间 小于700毫秒 移除以前的handler 延时600毫秒执行
                if (autoTVCheck.getTag() != null && time - (Long) autoTVCheck.getTag() < 700) {
                    searchHandler.removeMessages(1);
                }
                searchHandler.sendEmptyMessageDelayed(1, 600);
                autoTVCheck.setTag(time);
            }
        });
        //延时搜索的handler
        private Handler searchHandler = new Handler(Looper.getMainLooper()) {
        public void handleMessage(Message msg) {
            dealSearchHint();
        }
    };
    /**
     * 根据用户输入的字符去调用接口查询符合的订单或桌台名
     */
    private void dealSearchHint(){
        String searchContent = autoTVCheck.getText().toString();
        if(searchContent.isEmpty()){
            return;
        }
        //接口-模糊查询符合的订单或桌台名
        mProcess.getSearchDropList(searchContent,new ResultCallback<GetOrderFromCenterRespone>(){
                @Override
                public void onSuccess(GetOrderFromCenterRespone data) {
                    if(data != null && !ListUtil.isEmpty(data.orderList2)){
                    	//更新提示列表
                        searchAdapter.setOrderListModels(data.orderList2);
                        refreshDropList();
                    }
                }
        });
    }
    //AutoCompleteTextView的doBeforeTextChanged方法
    Method doBeforeTextChanged;
    //AutoCompleteTextView的doAfterTextChanged方法
    Method doAfterTextChanged;

    /**
     * 下拉提示框数据获取到后刷新此框
     * 通过反射调用AutoCompleteTextView的doBeforeTextChanged和doAfterTextChanged方法来实现刷新下拉提示框
     */
    private void refreshDropList(){
        try{
            if(doAfterTextChanged == null){
                Class autoCompleteTextView = Class.forName("android.widget.AutoCompleteTextView");
                doBeforeTextChanged = autoCompleteTextView.getDeclaredMethod("doBeforeTextChanged");
                doBeforeTextChanged.setAccessible(true);
                doAfterTextChanged = autoCompleteTextView.getDeclaredMethod("doAfterTextChanged");
                doAfterTextChanged.setAccessible(true);
            }
            autoTVCheck.showDropDown();
            doBeforeTextChanged.invoke(autoTVCheck);
            doAfterTextChanged.invoke(autoTVCheck);
        }catch (Exception e){}
    }

到此呢,AutoCompleteTextView下拉内容动态更新功能就写完了,从上一篇到现在编写这一篇,中间隔了将近一年,也是换工作以来,写的第一篇。可以看出来 换个环境真的很影响生活,影响工作,因为你要去适应和熟悉新的工作环境,要熟悉新工作的代码和以往的业务。当然,这些都是值得的!!

还是那句老话,如果屏前的你有一定的收获的话,那么请您给笔者点个赞或者留个言吧~

屏前的你,加油!!!
--------------------- 
 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在Android中,可以通过下拉搜索来获取搜索结果。一种常见的方式是使用下拉搜索框。当用户输入关键字时,搜索框将显示与输入内容相关的搜索建议或历史记录。 要实现下拉搜索结果,可以使用AutoCompleteTextView组件。该组件具有自动完成和下拉搜索建议的功能。一般来说,需要以下步骤来实现下拉搜索结果: 1. 添加AutoCompleteTextView到布局文件中: ```xml <AutoCompleteTextView android:id="@+id/autoCompleteTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="搜索" /> ``` 2. 在Activity或Fragment中,为AutoCompleteTextView设置适配器和监听器: ```java AutoCompleteTextView autoCompleteTextView = findViewById(R.id.autoCompleteTextView); ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, suggestions); autoCompleteTextView.setAdapter(adapter); autoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { String selected = (String) parent.getItemAtPosition(position); // 处理用户选择的搜索结果 } }); ``` 3. 为AutoCompleteTextView提供搜索建议数据: ```java String[] suggestions = new String[]{"apple", "banana", "cherry"}; // 搜索建议数据 ``` 通过上述步骤,当用户在AutoCompleteTextView中输入关键字时,它将根据输入内容显示下拉的搜索建议列表。用户可以选择一个建议项,或继续输入以进一步收窄搜索范围。选中的搜索结果可以通过监听器回调进行处理,例如跳转到相关的搜索结果页面。 总之,Android提供了AutoCompleteTextView组件,可以用于实现下拉搜索结果的功能。通过适配器和监听器,我们可以为搜索框提供搜索建议,并获取用户选择的搜索结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值