Android Studio开发实战:从零基础到App上线 (移动开发丛书)
上QQ阅读APP看书,第一时间看更新

3.4 编辑框

本节介绍Android的两种编辑框,分别是文本编辑框EditText与自动完成编辑框AutoCompleteTextView。在介绍EditText控件时,除了基本属性和方法,还另外阐述了常见的4种编辑处理:更换光标、更换边框、自动隐藏输入法和输入回车符自动换行。

3.4.1 文本编辑框EditText

EditText是文本编辑框,用户可在此输入文本等信息。EditText的常用属性说明如下。

●inputType:指定输入的文本类型,代码中对应的方法是setInputType。输入类型的取值说明见表3-3,若同时使用多种文本类型,则可使用竖线“”把多种文本类型拼接起来。

表3-3 输入类型的取值说明

● maxLength:指定文本允许输入的最大长度。该属性无法通过代码设置。

● hint:指定提示文本的内容,代码中对应的方法是setHint。

● textColorHint:指定提示文本的颜色,代码中对应的方法是setHintTextColor。

编辑框除了上述文本与提示文本的基本操作外,实际开发中还常常关注4个方面:更换编辑框的光标、更换编辑框的边框、自动隐藏输入法、输入回车符自动跳转。

1.更换编辑框的光标

EditText与光标处理有关的属性主要有两个,分别是:

● cursorVisible,指定光标是否可见。代码中对应的方法是setCursorVisible。

● textCursorDrawable,指定光标的图像。该属性无法通过代码设置。

如果要隐藏光标,就要把cursorVisible设置为false。如果要变更光标的样式,就要修改textCursorDrawable设置新图像。如图3-13所示,光标被换成自定义的红色竖线光标。

图3-13 给EditText更换图标样式

2.更换编辑框的边框

EditText的边框通过background属性控制,如果要隐藏边框,就要把background设置为@null;如果要修改边框的样式,就要将background设置为其他边框图形。

下面是一个边框定义XML的例子,一旦编辑框获得焦点(例如用户点击了该编辑框),边框就会显示图形shape_edit_focus;否则默认显示shape_edit_normal。

        <selector xmlns:android="http://schemas.android.com/apk/res/android">
            <item android:state_focused="true" android:drawable="@drawable/shape_edit_focus"/>
            <item android:drawable="@drawable/shape_edit_normal"/>
        </selector>

上述自定义边框的效果如图3-14所示,未点击时显示灰色的圆角边框,点击后显示蓝色的圆角边框。

图3-14 给EditText更换边框样式

3.自动隐藏输入法

如果页面上有EditText控件,开发者又没做其他处理,那么用户打开该页面时往往会自动弹出输入法。这是因为编辑框会默认获得焦点,即默认模拟用户的点击操作,于是输入法的软键盘就弹出了。要想避免这种情况,就得阻止编辑框默认获得焦点。比较常见的做法是给该页面的根节点设置focusable和focusableInTouchMode属性,通过将这两个属性设置为true可强制让根节点获得焦点,从而避免输入法自动弹出的尴尬。

由于软键盘通常会遮盖“登录”“确认”“下一步”等按钮,造成用户输入完毕得再点一次返回键才能关闭软键盘。大家都希望省事点,比如手机号输入满11位软键盘自动关闭,这样就会极大改善用户体验。一个好用的App就是在这一点一滴中体现出来的。

想让编辑框文本达到指定长度时自动关闭输入法,开发者需要获得两个参数,第一个是该编辑框允许输入的最大长度,第二个是当前已经输入的文本长度。当已输入的文本长度等于最大长度时,即可触发关闭软键盘。自动隐藏输入法可分解为3个功能点,分别是获取编辑框的最大长度、监控当前已输入的文本长度和关闭软键盘。

(1)获取编辑框的最大长度

前面我们了解到maxLength属性可设置最大长度,但是EditText并没有提供获取最大长度的方法,不过我们可以通过反射方式曲线获得最大长度,具体代码如下:

            public static int getMaxLength(EditText et) {
                int length = 0;
                try {
                    InputFilter[] inputFilters = et.getFilters();
                    for(InputFilter filter :inputFilters){
                        Class<? > c = filter.getClass();
                        if (c.getName().equals("android.text.InputFilter$LengthFilter")) {
                            Field[] f = c.getDeclaredFields();
                            for(Field field :f){
                                if (field.getName().equals("mMax")) {
                                    field.setAccessible(true);
                                    length=(Integer)field.get(filter);
                                }
                            }
                        }
                    }
                }catch(Exception e){
                    e.printStackTrace();
                }
                return length;
            }

(2)监控当前已输入的文本长度

这个监控操作用到一个文本监听器接口TextWatcher,该接口提供了3个监控方法,具体说明如下。

● beforeTextChanged:在文本改变之前触发。

● onTextChanged:在文本改变过程中触发。

● afterTextChanged:在文本改变之后触发。

这里用到的是afterTextChanged方法,开发者需要自己写个监听器实现TextWatcher接口,另外再给EditText对象调用addTextChangedListener方法注册该监听器。下面是一个具体实现该监听器的例子:

            private class HideTextWatcher implements TextWatcher {
                private EditText mView;
                private int mMaxLength;
                private CharSequence mStr;


                public HideTextWatcher(EditText v) {
                    super();
                    mView = v;
                    mMaxLength = ViewUtil.getMaxLength(v);
                }


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


                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    mStr = s;
                }


                @Override
                public void afterTextChanged(Editable s) {
                    if (mStr == null || mStr.length() == 0)
                        return;
                    if (mStr.length() == 11 && mMaxLength == 11) {
                        ViewUtil.hideAllInputMethod(EditHideActivity.this);
                    } else if (mStr.length() == 6 && mMaxLength == 6) {
                        ViewUtil.hideOneInputMethod(EditHideActivity.this, mView);
                    }
                }
            }

(3)关闭软键盘

输入法通过系统服务INPUT_METHOD_SERVICE管理,所以隐藏输入法也要通过该服务实现。下面是关闭软键盘的两种方式及其代码:

① 调用toggleSoftInput方法:

            public static void hideAllInputMethod(Activity act) {
                InputMethodManager imm = (InputMethodManager)
    act.getSystemService(Context.INPUT_METHOD_SERVICE);
                if(imm.isActive()==true){  //软键盘如果已经打开就要关闭
                    imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
                }
            }

② 调用hideSoftInputFromWindow方法:

            public static void hideOneInputMethod(Activity act, View v) {
                InputMethodManager imm = (InputMethodManager)
    act.getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
            }

完成隐藏输入法的编码后,可在页面上观察效果,如图3-15所示。此时手机号码输入了10位,还没达到11位的最大长度,故而输入法依然显示。手机号再输入一位数字,总长度11位达到最大长度的限制,于是输入法自动隐藏,如图3-16所示。

图3-15 输入10位手机号码

图3-16 输入11位手机号码

4.输入回车符自动跳转

在录入用户信息时(比如输入姓名、密码等),往EditText控件输入回车键,常常不是换行而是让光标直接跳到下一个编辑框。该功能用到了文本监听器接口TextWatcher,主要监听用户是否输入回车符,如果监控到已输入回车符,就自动将焦点移到下一个控件,从而实现回车符自动跳转的要求。

下面是回车符监听器的代码,注意注释部分的文字说明:

              private class JumpTextWatcher implements TextWatcher{
                    private EditText mThisView=null;
                    private View mNextView=null;


                    public JumpTextWatcher(EditText vThis, View vNext){
                       super();
                       mThisView=vThis;
                       if(vNext! =null){
                        mNextView=vNext;
                   }
                }


                @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 s){
                        String str=s.toString();
                        if(str.indexOf("\r")>=0||str.indexOf("\n")>=0){  //发现输入回车符或换行符
                        mThisView.setText(str.replace("\r", "").replace("\n", ""));  //去掉回车符和换行符
                        if (mNextView ! = null) {
                            mNextView.requestFocus();  //让下一个视图获得焦点,即将光标移到下个视图
                            if (mNextView instanceof EditText) {
                                EditText et = (EditText)mNextView;
                                //让光标自动移到编辑框内部的文本末尾
                                //方式一 :直接调用EditText的setSelection方法
                                et.setSelection(et.getText().length());
                                //方式二 :调用Selection类的setSelection方法
                                //Editable edit = et.getText();
                                //Selection.setSelection(edit, edit.length());
                            }
                        }
                    }
                }
            }

下面演示一下输入回车符自动跳转的效果图,文本输入完毕后还没输入回车符,此时焦点仍然停留在编辑框,如图3-17所示。输入回车符,此时焦点离开编辑框,并自动移动到“登录”按钮(编辑框的光标消失,按钮背景变深),如图3-18所示。

图3-17 未按回车符

图3-18 已按回车符

3.4.2 自动完成编辑框AutoCompleteTextView

自动完成编辑框一般用于搜索文本框,如在电商App的搜索框输入商品文字时,下方会自动弹出提示词列表,方便用户快速选择具体商品。AutoCompleteTextView的实现原理是:EditText结合监听器TextWatcher与下拉列表Spinner,一旦监控到EditText的文本发生变化,就自动弹出适配好的文字下拉列表,选中具体的下拉项向EditText填入相应文字。

AutoCompleteTextView新增的几个属性都与下拉列表有关,详细说明见表3-4。

表3-4 自动完成编辑框的属性和设置方法说明

下面是使用AutoCompleteTextView的代码:

                String[] hintArray = {"第一", "第一次", "第一次写代码", "第一次领工资", "第二", "第二个"};
                ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                        this, R.layout.item_dropdown, hintArray);
                AutoCompleteTextView ac_text= (AutoCompleteTextView) findViewById(R.id.ac_text);
                ac_text.setAdapter(adapter);

自动完成编辑框的具体效果如图3-19所示,下拉列表的内容会自动与编辑框的文本进行匹配。

图3-19 自动完成编辑框的自动匹配下拉列表