美文网首页Android UI 控件相关DevSupport
关于AppCompatAutoCompleteTextView使

关于AppCompatAutoCompleteTextView使

作者: 吾乃韩小呆 | 来源:发表于2018-07-23 17:30 被阅读0次

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

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

    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:
                }
            }
    
        }
    

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

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

    相关文章

      网友评论

        本文标题:关于AppCompatAutoCompleteTextView使

        本文链接:https://www.haomeiwen.com/subject/nrsjmftx.html