关于AppCompatAutoCompleteTextView使用总结

简介: Android 的 AppCompatAutoCompleteTextView 控件使用解析

今天抽出时间写一写关于这个控件我的理解,文笔不好,但是可以解决问题哈。

一、公司定下来的需求是这样的:

1、某两个界面都有右侧侧滑;
2、侧滑上有四个文本框;
3、每个文本框点击时候即出现提示下拉;
4、每个文本框输入的时候也会出现提示下拉;
6、当点击下拉内的item时,item文字显示在文本框内;
7、巴拉巴拉...就这么一堆。

二、想法

1、EditText+ListView;
2、AutoCompleteTextView或AppCompatAutoCompleteTextView或MultiAutoCompleteTextView
3、EditText+ListView;
4、去gihub大海捞针去;
...
为了保证程序性的简洁性、易用性、低维护成本....(其实就是懒),选择了第二个方案;实施之后,第二个虽然代码少了,但是这个逻辑啊,一张图表示(此处省略一万字)。既然是自己选择的方案,哭着也得写完。
*疼*紧

三、实施

1、在xml文件内写布局

   <android.support.v7.widget.AppCompatAutoCompleteTextView
        android:id="@+id/act_hidden_danger_pro_name"
        android:layout_width="match_parent"
        android:layout_height="35dp"
        android:layout_below="@+id/tv_nv_hidden_danger_name"
        android:layout_marginEnd="20dp"
        android:layout_marginStart="20dp"
        android:layout_marginTop="20dp"
        android:background="@mipmap/bg_text_all"
        android:completionThreshold="1"
        android:hint="项目名称"
        android:lines="1"
        android:paddingEnd="@dimen/widget_margin_5"
        android:paddingStart="@dimen/widget_margin_5"
        android:singleLine="true"
        android:textColor="@color/contents_text"
        android:textSize="16sp" />

这样的控件写了四个,其实可以写到values/style.xml文件内,但是为了只管展现,我就这么写了(说到底第还是懒)。下面放完整的侧滑代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <TextView
        android:id="@+id/tv_nv_hidden_danger_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="40dp"
        android:gravity="center"
        android:text="@string/filtrate"
        android:textColor="@color/contents_text"
        android:textSize="20sp" />

    <android.support.v7.widget.AppCompatAutoCompleteTextView
        android:id="@+id/act_hidden_danger_pro_name"
        android:layout_width="match_parent"
        android:layout_height="35dp"
        android:layout_below="@+id/tv_nv_hidden_danger_name"
        android:layout_marginEnd="20dp"
        android:layout_marginStart="20dp"
        android:layout_marginTop="20dp"
        android:background="@mipmap/bg_text_all"
        android:completionThreshold="1"
        android:hint="项目名称"
        android:lines="1"
        android:paddingEnd="@dimen/widget_margin_5"
        android:paddingStart="@dimen/widget_margin_5"
        android:singleLine="true"
        android:textColor="@color/contents_text"
        android:textSize="16sp" />

    <android.support.v7.widget.AppCompatAutoCompleteTextView
        android:id="@+id/act_hidden_danger_sys_name"
        android:layout_width="match_parent"
        android:layout_height="35dp"
        android:layout_below="@+id/act_hidden_danger_pro_name"
        android:layout_marginEnd="20dp"
        android:layout_marginStart="20dp"
        android:layout_marginTop="20dp"
        android:background="@mipmap/bg_text_all"
        android:completionThreshold="1"
        android:hint="系统名称"
        android:lines="1"
        android:paddingEnd="@dimen/widget_margin_5"
        android:paddingStart="@dimen/widget_margin_5"
        android:singleLine="true"
        android:textColor="@color/contents_text"
        android:textSize="16sp" />

    <android.support.v7.widget.AppCompatAutoCompleteTextView
        android:id="@+id/act_hidden_danger_firm_name"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:layout_below="@+id/act_hidden_danger_sys_name"
        android:layout_marginEnd="20dp"
        android:layout_marginStart="20dp"
        android:layout_marginTop="20dp"
        android:background="@mipmap/bg_text_all"
        android:completionThreshold="1"
        android:hint="厂商名称"
        android:lines="1"
        android:paddingEnd="@dimen/widget_margin_5"
        android:paddingStart="@dimen/widget_margin_5"
        android:singleLine="true"
        android:textColor="@color/contents_text"
        android:textSize="14sp" />

    <android.support.v7.widget.AppCompatAutoCompleteTextView
        android:id="@+id/act_hidden_danger_type"
        android:layout_width="match_parent"
        android:layout_height="35dp"
        android:layout_below="@+id/act_hidden_danger_firm_name"
        android:layout_marginEnd="20dp"
        android:layout_marginStart="20dp"
        android:layout_marginTop="20dp"
        android:background="@mipmap/bg_text_all"
        android:completionThreshold="1"
        android:hint="报警类型"
        android:lines="1"
        android:paddingEnd="@dimen/widget_margin_5"
        android:paddingStart="@dimen/widget_margin_5"
        android:singleLine="true"
        android:textColor="@color/contents_text"
        android:textSize="16sp" />

    <LinearLayout
        android:id="@+id/act_service"
        android:layout_width="match_parent"
        android:layout_height="35dp"
        android:layout_below="@+id/act_hidden_danger_type"
        android:layout_marginEnd="20dp"
        android:layout_marginStart="20dp"
        android:layout_marginTop="20dp"
        android:background="@drawable/shape_dialog_et"
        android:orientation="vertical"
        android:paddingEnd="@dimen/widget_margin_5"
        android:paddingStart="@dimen/widget_margin_5">

        <android.support.v7.widget.AppCompatSpinner
            android:id="@+id/as_service_type"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:dropDownWidth="wrap_content"
            android:paddingEnd="0dp"
            android:paddingStart="0dp"
            android:spinnerMode="dropdown"
            android:textColor="#666666"
            android:textSize="12sp" />
    </LinearLayout>

    <TextView
        android:id="@+id/btn_hidden_danger_y"
        android:layout_width="100dp"
        android:layout_height="30dp"
        android:layout_below="@+id/act_service"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="60dp"
        android:background="@drawable/bg_group_delete_shape"
        android:gravity="center"
        android:text="确  定"
        android:textColor="#ffffffff" />
    
</RelativeLayout>

然后进入咱们的熟悉的Activity内开始装x大业;

2、满足点击文本框就出现下拉菜单

初始化后的 AppCompatAutoCompleteTextView 对象实现 onFocusChangeListener() 接口
在 onFocusChangeListener() 接口内判断点击的是哪个控件,并且这个控件是否真的活得了焦点;
我当时没有用 switch、case 的形式,而是采用了 if、 else 的形式进行的判断,代码如下:

  @Override
    public void onFocusChange(View v, boolean hasFocus) {

        if (TextUtils.isEmpty(etProName.getText().toString())) {
            projectId = 0;
        }
        if (TextUtils.isEmpty(etSysName.getText().toString().trim())) {
            systemId = 0;
        }
        if (TextUtils.isEmpty(etSysName.getText().toString().trim())) {
            firmId = 0;
        }
        if (v.getId() == etProName.getId() && etProName.hasFocus()) {
            HttpRequest.getProject(etProName.getText().toString().trim(), HiddenDangerActivity.this);
        } else if (v.getId() == etSysName.getId() && etSysName.hasFocus()) {
            if (TextUtils.isEmpty(etProName.getText().toString().trim())) {
                if (TextUtils.isEmpty(etFirmName.getText().toString().trim()))
                    firmId = 0;
                HttpRequest.getSystems(etSysName.getText().toString().trim(), firmId, 0, HiddenDangerActivity.this);
            } else {
                HttpRequest.getSystemData(projectId, HiddenDangerActivity.this);
            }
        } else if (v.getId() == etFirmName.getId() && etFirmName.hasFocus()) {
            if (TextUtils.isEmpty(etSysName.getText().toString().trim()))
                systemId = 0;
            HttpRequest.getFirms(etFirmName.getText().toString().trim(), 0, systemId, HiddenDangerActivity.this);
        } else if (v.getId() == etTypeName.getId() && etTypeName.hasFocus()) {
            HttpRequest.getDanger(etTypeName.getText().toString().trim(), HiddenDangerActivity.this);
        }
    }

当点击的控件为当前控件并且该控件获取了焦点,则进行相关的网络请求,此时返回数据展示在文本框的下拉的菜单当中

3、展示下拉菜单

  /**
     * 展示搜索框下拉列表
     *
     * @param i 标志位
     */
    private void setAdapter(int i) {
        if (isShow) {
            switch (i) {
                case 1:
                    ArrayAdapter projectAdapter = new ArrayAdapter<>(HiddenDangerActivity.this,
                            R.layout.item_h_f_iact, projects);
                    projectAdapter.notifyDataSetChanged();
                    etProName.setAdapter(projectAdapter);
                    removeViewFocus(etProName);
                   
                        etProName.showDropDown();
                    
                    break;
                case 2:
                    ArrayAdapter systemAdapter = new ArrayAdapter<>(HiddenDangerActivity.this,
                            R.layout.item_h_f_iact, systems);
                    systemAdapter.notifyDataSetChanged();
                    etSysName.setAdapter(systemAdapter);
                    removeViewFocus(etSysName);
                 
                        etSysName.showDropDown();
                    
                    break;
                case 3:
                    ArrayAdapter firmAdapter = new ArrayAdapter<>(HiddenDangerActivity.this,
                            R.layout.item_h_f_iact, firms);
                    firmAdapter.notifyDataSetChanged();
                    etFirmName.setAdapter(firmAdapter);

                    removeViewFocus(etFirmName);
                
                        etFirmName.showDropDown();
                    
                    break;
                case 4:
                    ArrayAdapter warnTypeAdapter = new ArrayAdapter<>(HiddenDangerActivity.this,
                            R.layout.item_h_f_iact, dangerTypes);
                    warnTypeAdapter.notifyDataSetChanged();
                    etTypeName.setAdapter(warnTypeAdapter);
                    removeViewFocus(etTypeName);
                  
                        etTypeName.showDropDown();
                    
                    break;
                default:
            }
        }

    }

这里比较非常重要的代码是: etTypeName.showDropDown() 这句话丢了就会导致,输入两个字(默认情况下)才会出现下拉菜单,或者是你设置了 android:completionThreshold="1" 属性,也得输入一个字之后才会出息下拉菜单的尴尬局面;所以 .showDropDown() 方法绝对不能懒。

对了 removeViewFocus();方法内代码为:

 private void removeViewFocus(AppCompatAutoCompleteTextView view) {

        ArrayList<AppCompatAutoCompleteTextView> views = new ArrayList<>();
        views.add(etFirmName);
        views.add(etSysName);
        views.add(etProName);
        views.add(etTypeName);
        for (int i = 0; i < views.size(); i++) {
            if (views.get(i).equals(view)) {
                views.remove(i);
            }
        }
        for (AppCompatAutoCompleteTextView v : views) {
            v.clearFocus();
            v.dismissDropDown();
        }

    }

这个方法很简单了,就不多解释了(还是有点懒),如果你要是不明白了,留言给我,我告诉你哈(手动滑稽);

4、进行输入文本展示下拉

当用户不喜欢选择item的时候也可以一个字一个字的的进行输入(一般来说客户都很勤快,别我勤快),我们也得提示一下,放置用户打错了啥的,于是也得展现下拉菜单,导致这4个控件得实现 TextWatcher 这个接口;
在接口回调内斜下如下代码:
对了,我是用内部类的形式实现了这个接口哈,毕竟是四个控件,好区分:

class MyTextWatcher implements TextWatcher {
        private int tag;

        MyTextWatcher(int tag) {
            this.tag = tag;
        }

        @Override
        public void afterTextChanged(Editable s) {
            if (isShow) {
                switch (tag) {
                    case 1:
                        if (TextUtils.isEmpty(etProName.getText().toString().trim())) {
                            projectId = 0;
                        }
                        HttpRequest.getProject(s.toString(), HiddenDangerActivity.this);
                        break;
                    case 2:
                        if (projectId == 0) {
                            HttpRequest.getSystems(s.toString(), firmId, 0, HiddenDangerActivity.this);
                        } else {
                            HttpRequest.getSystemData(projectId, HiddenDangerActivity.this);
                        }
                        break;
                    case 3:
                        if (TextUtils.isEmpty(s.toString())) {
                            firmId = 0;
                        }
                        HttpRequest.getFirms(s.toString(), 0, systemId, HiddenDangerActivity.this);
                        break;
                    case 4:
                        HttpRequest.getDanger(s.toString(), HiddenDangerActivity.this);
                        break;
                }
            }
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {


        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

    }

每次输入的时候都会出现下拉菜单,完美(沾沾自喜中)。以后一测试,傻眼了。。。。

这样写产生的结果是:每次从下拉内点击item之后,数据进入文本框触发 TextWatcher 的回调 ,然后你懂得,可能你也有可能不懂,文本框下面出现一个网络请求来的 item 。

这次我终于不懒了,百度、谷歌了好几天,翻来覆去就是那么两篇文章,而且我感觉那群楼主都是相互抄来抄去的,一个能解决问题的都没有。 不过看见一个回答问题的博主,他说可以使用一个 boolean 的标志位,我感觉也可以,但是赎晚辈愚笨,我是不知道加到哪里可以实现。如果哪位兄台可以弄出来,跪求传授修仙打法。楼主跪下了哈:跪求修仙大法

5、解决小尾巴问题

经过反复沉思,想到了一个比较靠谱的方法:
.showDropDown();方法处加个if 判断,即将网络请求来的 “数据第一个”与“控件内取出的数据”进行对比,如果不同则展示下拉列表,相同则不展示下拉列表;
修改之后的下拉数据展示代码为:

 /**
     * 展示搜索框下拉列表
     *
     * @param i 标志位
     */
    private void setAdapter(int i) {
        if (isShow) {
            switch (i) {
                case 1:
                    ArrayAdapter projectAdapter = new ArrayAdapter<>(HiddenDangerActivity.this,
                            R.layout.item_h_f_iact, projects);
                    projectAdapter.notifyDataSetChanged();
                    etProName.setAdapter(projectAdapter);
                    removeViewFocus(etProName);
                    if (!etProName.getText().toString().trim().equals(projects.get(0).getProjName())) {
                        etProName.showDropDown();
                    }
                    break;
                case 2:
                    ArrayAdapter systemAdapter = new ArrayAdapter<>(HiddenDangerActivity.this,
                            R.layout.item_h_f_iact, systems);
                    systemAdapter.notifyDataSetChanged();
                    etSysName.setAdapter(systemAdapter);
                    removeViewFocus(etSysName);
                    if (!etSysName.getText().toString().trim().equals(systems.get(0).getDevSysName())) {
                        etSysName.showDropDown();
                    }
                    break;
                case 3:
                    ArrayAdapter firmAdapter = new ArrayAdapter<>(HiddenDangerActivity.this,
                            R.layout.item_h_f_iact, firms);
                    firmAdapter.notifyDataSetChanged();
                    etFirmName.setAdapter(firmAdapter);

                    removeViewFocus(etFirmName);
                    if (!etFirmName.getText().toString().trim().equals(firms.get(0).getFirmName())) {
                        etFirmName.showDropDown();
                    }
                    break;
                case 4:
                    ArrayAdapter warnTypeAdapter = new ArrayAdapter<>(HiddenDangerActivity.this,
                            R.layout.item_h_f_iact, dangerTypes);
                    warnTypeAdapter.notifyDataSetChanged();
                    etTypeName.setAdapter(warnTypeAdapter);
                    removeViewFocus(etTypeName);
                    if (!etTypeName.getText().toString().trim().equals(dangerTypes.get(0).getWarnTyDesc())) {
                        etTypeName.showDropDown();
                    }
                    break;
                default:
            }
        }

    }

到此为止,完美的实现了需求,文本框点击数显下拉、输入输入出现下拉的需求。

文笔不好,代码水平不太高。有大佬指点,小弟感激涕零。当然有问题,大家留言区留言,一起探讨哈。关于探讨问题,楼主还是不太懒得哈。

相关文章
|
开发工具 Android开发
细说 AppCompat 主题引发的坑:You need to use a Theme.AppCompat theme with this activity!
细说 AppCompat 主题引发的坑:You need to use a Theme.AppCompat theme with this activity!
细说 AppCompat 主题引发的坑:You need to use a Theme.AppCompat theme with this activity!
|
API Android开发
深入剖析Android四大组件(九)——Activity之AppCompatActivity与toolbar的结合(一)
深入剖析Android四大组件(九)——Activity之AppCompatActivity与toolbar的结合(一)
143 0
深入剖析Android四大组件(九)——Activity之AppCompatActivity与toolbar的结合(一)
|
Android开发
深入剖析Android四大组件(九)——Activity之AppCompatActivity与toolbar的结合(二)
深入剖析Android四大组件(九)——Activity之AppCompatActivity与toolbar的结合(二)
166 0
深入剖析Android四大组件(九)——Activity之AppCompatActivity与toolbar的结合(二)
|
Android开发
关于AppCompatAutoCompleteTextView使用总结
今天抽出时间写一写关于这个控件我的理解,文笔不好,但是可以解决问题哈。 一、公司定下来的需求是这样的: 1、某两个界面都有右侧侧滑; 2、侧滑上有四个文本框; 3、每个文本框点击时候即出现提示下拉; 4、每个文本框输入的时候也会出现提示下拉; 6、当点击下拉内的item时,item文字显示在文本框内; 7、巴拉巴拉...就这么一堆。
1445 0
|
XML Android开发 数据格式
Android ExpandableListView使用
activity_main.xml layout_parent.xml layout_child.xml MainActivity.
866 0
|
Android开发
AppCompatActivity实现全屏的问题
前言:我的 Activity 是继承 BaseActivity , 而 BaseActivity 继承 AppCompatActivity 。   BaseActivity 的继承 /** * 应用程序的基类 * */ public class BaseActivity ...
1197 0
FragmentPagerAdapter和FragmentStatePagerAdapter区别?
FragmentPagerAdapter:对于不再需要的fragment,选择调用detach方法,仅销毁视图,并不会销毁fragment实例。FragmentStatePagerAdapter:会销毁不再需要的fragment,当当前事务提交以后,会彻底的将fragmeng从当前Activity的...
886 0