精华内容
参与话题
问答
  • Android开发:EditText组件的基本使用

    千次阅读 2018-08-10 10:27:13
    在Android开发过程中,EditText组件是一个常用控件,也是一个比较重要的组件,它的基本属性需要熟练使用才行,接下来就来讲一下在Android开发中EditText组件的基本使用。 一、EditText简介  ED(EditText的简称)...

          在Android开发过程中,EditText组件是一个常用控件,也是一个比较重要的组件,它的基本属性需要熟练使用才行,接下来就来讲一下在Android开发中EditText组件的基本使用。

    一、EditText简介
           ED(EditText的简称)在开发中也是经常使用到而且比较重要的一个控件,它是用户跟应用进行数据传输的窗口,比如实现一个登陆界面, 需要用户输入账号和密码,然后我们开发者获取到用户输入的内容,提交给后台服务器进行判断再做相应的处理。

    二、EditText支持的XML属性以及基础的用法    

    setText(CharSequence text) 设置文本内容

    setTextColor(int color) 设置字体颜色值

    setHint(int resid) 内容为空时候显示的文本

    void setHintTextColor(int color) 内容为空时候显示的文本颜色值

    setInputType(int type)      限制输入类型

    number:整数类型

    numberDecimal:小数点类型

    date:日期类型

    text:文本类型(默认值)

    phone:拨号键盘

    textPassword:密码

    textVisiblePassword:可见密码

    textUri:网址

    setMaxLines(int maxlines) 设置文本的最小行数

    setGravity(int gravity) 设置文本位置,如设置成“center”,文本将居中显示。

    setLines(int lines) 设置文本的行数,设置两行就显示两行,即使第二行没有数据。

    setSingleLine()     true:单行显示 false:可以多行

            EditText示例:开发中常用的登录界面
            首先我们来看布局文件:activity_login.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="@drawable/main_background"
        tools:context="com.teamosa.Teamosa.mvvm.activity.LoginActivity">

        <EditText
            android:id="@+id/login_accout"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_marginTop="100dp"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:drawablePadding="8dp"
            android:drawableLeft="@mipmap/user_account"
            android:hint="请输入手机号码/邮箱地址"
            android:background="@drawable/btn_shape" />

        <EditText
            android:id="@+id/login_password"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_marginTop="20dp"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:drawablePadding="8dp"
            android:drawableLeft="@mipmap/user_password"
            android:hint="请输入密码"
            android:background="@drawable/btn_shape" />

        <Button
            android:id="@+id/login_login"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_marginTop="70dp"
            android:layout_marginLeft="@dimen/dp20"
            android:layout_marginRight="@dimen/dp20"
            android:text=“登录”
            android:textColor="@color/white"
            android:background="@drawable/btn_shape"/>
    </LinearLayout>

           以上这两个输入框的使用了EditText的常用属性,值得借鉴的是EditText组件drawableLeft属性设置的图片和hint设置的文字之间的距离。有的时候,需要在文本框里放置icon图片,并且设置默认提示文字的时候,需要设置两者之间的间距,就是之前的手机icon和”请输入手机号“之间的距离。下面再说一下上面没有用到的属性:
            1、android:background=”@null”     输入框无背景 
           2、android:drawableBottom=”@drawable/shape_bottom_line”   底部引入一个shape布局文件,该布局文件就是输入框的下划线。shape_bottom_line.xml内容如下:
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle" >
        <solid android:color="#1E7EE3" />
        <size android:height="1dp" android:width="500dp"/>
    </shape>

        三、EditText的其他功能
           1、监听用户输入的内容. 
           例如,一个搜索框,只要用户输入了内容就去请求服务器,于是就要在Activity里面监听EditeText文本改变事件,具体实现如下所示:
    EditText etOne= (EditText) findViewById(R.id.phone);
    etOne.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                    Log.i("And","内容改变之前调用:"+s);
                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    Log.i("And","内容改变,可以去告诉服务器:"+s);
                }

                @Override
                public void afterTextChanged(Editable s) {
                    Log.i("And”,”内容改变之后调用:"+s);
                }


        2、EditText 在左边加入图片,代码如下:  
            Bitmap bitmap = mWebView.getFavicon();
            Drawable drawable = new BitmapDrawable(bitmap);
            drawable = this.getResources().getDrawable(R.drawable.history);
            edit.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
            edit.setText(cur_url);
     
              setCompoundDrawablesWithIntrinsicBounds与setCompoundDrawables的区别:
              setCompoundDrawables画的drawable的宽高是按drawable.setBound()设置的宽高,所以才有The Drawables must already have had setBounds(Rect) called.
             而setCompoundDrawablesWithIntrinsicBounds画的drawable的宽高是按drawable固定的宽高,即通过getIntrinsicWidth()与getIntrinsicHeight()获得,所以才有The Drawables' bounds will be set to their intrinsic bounds.
              查看下面的方法:
    public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top,
                Drawable right, Drawable bottom) {
            if (left != null) {
                left.setBounds(0, 0, left.getIntrinsicWidth(), left.getIntrinsicHeight());
            }
            if (right != null) {
                right.setBounds(0, 0, right.getIntrinsicWidth(), right.getIntrinsicHeight());
            }
            if (top != null) {
                top.setBounds(0, 0, top.getIntrinsicWidth(), top.getIntrinsicHeight());
            }
            if (bottom != null) {
                bottom.setBounds(0, 0, bottom.getIntrinsicWidth(), bottom.getIntrinsicHeight());
            }
            setCompoundDrawables(left, top, right, bottom);


        3、获取、设置EditText的文本
             在开发过程中,使用EditText的时候,需要获取到EditText的文本值,其实获得EditText控件的值方法也就是调用EditText的方法,获取文本值,具体步骤如下所示:
             首先,在xml中定义EditText控件editText1;
             然后在activity里面,声明生成一个EditText对象,然后获取文本值即可:
        String str = "";  
        EditText editText1 =(EditText)findViewById(R.id.editText1);  
        str = editText.getText().toString();   //str即为获取的String类型的文本值
        或者用方法  Integer.parseInt(editText.getText().toString());


             
        //将文本框1的文本赋给文本框2          
       

         EditText editText2 =(EditText)findViewById(R.id.editText2);       
       

         editText2.setText(str.toCharArray(), 0, str.length()); 


            以上就是本节全部内容, 欢迎关注三掌柜的微信公众号,欢迎关注!

     

    展开全文
  • EditText属性大全详解

    千次阅读 2017-09-27 09:54:59
    EditText继承关系:View–>TextView–>EditTextEditText的属性很多,这里介绍几个:android:hint="请输入数字!"//设置显示在空间上的提示信息 android:numeric="integer"//设置只能输入...

    EditText继承关系:View–>TextView–>EditText

    EditText的属性很多,这里介绍几个:

    android:hint="请输入数字!"//设置显示在空间上的提示信息
    android:numeric="integer"//设置只能输入整数,如果是小数则是:decimal
    android:singleLine="true"//设置单行输入,一旦设置为true,则文字不会自动换行。
    android:password="true"//设置只能输入密码
    android:textColor = "#ff8c00"//字体颜色
    android:textStyle="bold"//字体,bold, italic, bolditalic
    android:textSize="20dip"//大小
    android:capitalize = "characters"//以大写字母写
    android:textAlign="center"//EditText没有这个属性,但TextView有,居中
    android:textColorHighlight="#cccccc"//被选中文字的底色,默认为蓝色
    android:textColorHint="#ffff00"//设置提示信息文字的颜色,默认为灰色android:textScaleX="1.5"//控制字与字之间的间距
    android:typeface="monospace"//字型,normal, sans, serif, monospace
    android:background="@null"//背景,这里没有,指透明
    android:layout_weight="1"//权重,控制控件之间的地位,在控制控件显示的大小时蛮有用的。
    android:textAppearance="?android:attr/textAppearanceLargeInverse"//文字外观
    android:layout_gravity="center_vertical"//设置控件显示的位置:默认top,这里居中显示,还有bottom
    
    android:gray="top" //多行中指针在第一行第一位置
    
    et.setSelection(et.length());//调整光标到最后一行
    
    android:autoText //自动拼写帮助
    
    android:capitalize //首字母大写
    
    android:digits //设置只接受某些数字
    
    Android:singleLine//是否单行或者多行,回车是离开文本框还是文本框增加新行
    
    android:numeric //只接受数字
    
    android:phoneNumber //输入电话号码
    
    android:editable //是否可编辑
    
    android:autoLink=”all” //设置文本超链接样式当点击网址时,跳向该网址 
    
    android:textAppearance="?android:attr/textAppearanceLargeInverse"//文字外观,这里引用的是系统自带的一个外观,?表示系统是否有这种外观,否则使用默认的外观。不知道这样理解对不对? 
    

    属性名称描述

    android:autoLink
    设置是否当文本为URL链接/email/电话号码/map时,文本显示为可点击的链接。可选值(none/web/email/phone/map/all)

    android:autoText
    如果设置,将自动执行输入值的拼写纠正。此处无效果,在显示输入法并输入的时候起作用。

    android:bufferType
    指定getText()方式取得的文本类别。选项editable 类似于StringBuilder可追加字符,

    也就是说getText后可调用append方法设置文本内容。spannable 则可在给定的字符区域使用样式,参见这里1、这里2。

    android:capitalize
    设置英文字母大写类型。此处无效果,需要弹出输入法才能看得到,参见EditView此属性说明。

    android:cursorVisible
    设定光标为显示/隐藏,默认显示。

    android:digits
    设置允许输入哪些字符。如“1234567890.±*/% ()”

    android:drawableBottom
    在text的下方输出一个drawable,如图片。如果指定一个颜色的话会把text的背景设为该颜色,并且同时和background使用时覆盖后者。

    android:drawableLeft
    在text的左边输出一个drawable,如图片。

    android:drawablePadding
    设置text与drawable(图片)的间隔,与drawableLeft、drawableRight、drawableTop、drawableBottom一起使用,可设置为负数,单独使用没有效果。

    android:drawableRight
    在text的右边输出一个drawable,如图片。

    android:drawableTop
    在text的正上方输出一个drawable,如图片。

    android:editable
    设置是否可编辑。这里无效果,参见EditView。

    android:editorExtras
    设置文本的额外的输入数据。在EditView再讨论。

    android:ellipsize
    设置当文字过长时,该控件该如何显示。有如下值设置:”start”—?省略号显示在开头;”end”——省略号显示在结尾;”middle”—-省略号显示在中间;”marquee” ——以跑马灯的方式显示(动画横向移动)

    android:freezesText
    设置保存文本的内容以及光标的位置。参见:这里。

    android:gravity
    设置文本位置,如设置成“center”,文本将居中显示。

    android:hintText
    为空时显示的文字提示信息,可通过textColorHint设置提示信息的颜色。此属性在EditView中使用,但是这里也可以用。

    android:imeOptions
    附加功能,设置右下角IME动作与编辑框相关的动作,如actionDone右下角将显示一个“完成”,而不设置默认是一个回车符号。这个在EditView中再详细说明,此处无用。

    android:imeActionId
    设置IME动作ID。在EditView再做说明,可以先看这篇帖子:这里。

    android:imeActionLabel
    设置IME动作标签。在EditView再做说明。

    android:includeFontPadding
    设置文本是否包含顶部和底部额外空白,默认为true。

    android:inputMethod
    为文本指定输入法,需要完全限定名(完整的包名)。例如:com.google.android.inputmethod.pinyin,但是这里报错找不到。

    android:inputType
    设置文本的类型,用于帮助输入法显示合适的键盘类型。在EditView中再详细说明,这里无效果。

    android:linksClickable
    设置链接是否点击连接,即使设置了autoLink。

    android:marqueeRepeatLimit
    在ellipsize指定marquee的情况下,设置重复滚动的次数,当设置为marquee_forever时表示无限次。

    android:ems
    设置TextView的宽度为N个字符的宽度。这里测试为一个汉字字符宽度,如图:

    android:maxEms
    设置TextView的宽度为最长为N个字符的宽度。与ems同时使用时覆盖ems选项。

    android:minEms
    设置TextView的宽度为最短为N个字符的宽度。与ems同时使用时覆盖ems选项。

    android:maxLength
    限制显示的文本长度,超出部分不显示。

    android:lines
    设置文本的行数,设置两行就显示两行,即使第二行没有数据。

    android:maxLines
    设置文本的最大显示行数,与width或者layout_width结合使用,超出部分自动换行,超出行数将不显示。

    android:minLines
    设置文本的最小行数,与lines类似。

    android:lineSpacingExtra
    设置行间距。

    android:lineSpacingMultiplier
    设置行间距的倍数。如”1.2”

    android:numeric
    如果被设置,该TextView有一个数字输入法。此处无用,设置后唯一效果是TextView有点击效果,此属性在EdtiView将详细说明。

    android:password
    以小点”.”显示文本

    android:phoneNumber
    设置为电话号码的输入方式。

    android:privateImeOptions
    设置输入法选项,此处无用,在EditText将进一步讨论。

    android:scrollHorizontally
    设置文本超出TextView的宽度的情况下,是否出现横拉条。

    android:selectAllOnFocus
    如果文本是可选择的,让他获取焦点而不是将光标移动为文本的开始位置或者末尾位置。TextView中设置后无效果。

    android:shadowColor
    指定文本阴影的颜色,需要与shadowRadius一起使用。效果:

    android:shadowDx
    设置阴影横向坐标开始位置。

    android:shadowDy
    设置阴影纵向坐标开始位置。

    android:shadowRadius
    设置阴影的半径。设置为0.1就变成字体的颜色了,一般设置为3.0的效果比较好。

    android:singleLine
    设置单行显示。如果和layout_width一起使用,当文本不能全部显示时,后面用“…”来表示。

    如android:text="test_ singleLine " android:singleLine=“true” android:layout_width="20dp"将只显示“t…”。如果不设置singleLine或者设置为false,文本将自动换行

    android:shadowDx
    设置阴影横向坐标开始位置。

    android:shadowDy
    设置阴影纵向坐标开始位置。

    android:shadowRadius
    设置阴影的半径。设置为0.1就变成字体的颜色了,一般设置为3.0的效果比较好。

    android:singleLine
    设置单行显示。如果和layout_width一起使用,当文本不能全部显示时,后面用“…”来表示。

    如android:text="test_ singleLine " android:singleLine=“true” android:layout_width="20dp"将只显示“t…”。

    如果不设置singleLine或者设置为false,文本将自动换行

    android:text
    设置显示文本.

    android:textSize
    设置文字大小,推荐度量单位”sp”,如”15sp”

    android:textStyle
    设置字形[bold(粗体) 0, italic(斜体) 1, bolditalic(又粗又斜) 2] 可以设置一个或多个,用“|”隔开

    android:typeface
    设置文本字体,必须是以下常量值之一:normal 0, sans 1, serif 2, monospace(等宽字体) 3]

    android:height
    设置文本区域的高度,支持度量单位:px(像素)/dp/sp/in/mm(毫米)

    android:maxHeight
    设置文本区域的最大高度

    android:minHeight
    设置文本区域的最小高度

    android:width
    设置文本区域的宽度,支持度量单位:px(像素)/dp/sp/in/mm(毫米),与layout_width的区别看这里。

    android:maxWidth
    设置文本区域的最大宽度

    android:minWidth
    设置文本区域的最小宽度

    android:textAppearance
    设置文字外观。

    如“?android:attr/textAppearanceLargeInverse”这里引用的是系统自带的一个外观,?表示系统是否有这种外观,否则使用默认的外观。

    可设置的值如下:textAppearanceButton/textAppearanceInverse/textAppearanceLarge/textAppearanceLargeInverse/textAppearanceMedium/textAppearanceMediumInverse/textAppearanceSmall/textAppearanceSmallInverse

    android:textAppearance
    设置文字外观。如“?android:attr/textAppearanceLargeInverse

    ”这里引用的是系统自带的一个外观,?表示系统是否有这种外观,否则使用默认的外观。

    可设置的值如下:textAppearanceButton/textAppearanceInverse/textAppearanceLarge/textAppearanceLargeInverse/textAppearanceMedium/textAppearanceMediumInverse

    展开全文
  • Android开发&EditText的使用方式

    万次阅读 2019-03-06 17:27:44
    安卓开发内容编辑不同于H5,即便是编辑多行文本,文本块,也只能使用 EditText,这也是我们使用的最多的控件之一,今天就来分析一下,EditText该怎样使用。 在开始之前,先查看一下这个View的继承方式,通过继承...

    安卓开发内容编辑不同于H5,即便是编辑多行文本,文本块,也只能使用 EditText,这也是我们使用的最多的控件之一,今天就来分析一下,EditText该怎样使用。

    在开始之前,先查看一下这个View的继承方式,通过继承方式我们可以看出很多内容来。

    在这里插入图片描述

    在此先进行一下说明,AppCompatTextView 是迎合 Meterial Design进行一些外观的处理,实际功能并没有任何变化。

    一、基础部分

    就平时而言,EditText 最多的是改一些文字,颜色,大小,通过 xml 几乎可以完成大部分的功能,常用的属性值在此列出:

    <EditText
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:cursorVisible="true"
        android:ellipsize="marquee"
        android:hint="hint文字"
        android:imeOptions="actionNext"
        android:inputType="numberDecimal"
        android:marqueeRepeatLimit="marquee_forever"
        android:maxLength="16"
        android:singleLine="true"
        android:text="文字"
        android:includeFontPadding="false"
        android:digits="0123456789."
        android:textAllCaps="false"
        android:textAppearance="@style/TextAppearance.AppCompat"
        android:textColor="@color/main_color_white"
        android:textColorHint="@color/toolbar_hint_color_primary"
        android:textCursorDrawable="@drawable/shape_cursor_2dp_white"
        android:textIsSelectable="true"
        android:textSize="@dimen/text_size_normal_14sp"
        android:textStyle="bold">
    </EditText>
    

    基本的属性就这些,根据名称就可以看出属性代表的功能,这里就几个不常见的另做说明:

    • cursorVisible 光标显示控制
    • includeFontPadding是否显示上下标,关于文本上下标的问题,可以参考博客:Android开发&TextView设定精确间隔
    • digits显示文本框中只能输入指定的一些字符
    • textIsSelectable文本内容是否可以被选中

    从上面的继承关系中,应该能想到,基本上TextView 有的功能,EditText 也拥有,因此对于一些 drawable***适用于 TextView 的属性,同样可用于 EditText

    二、焦点控制

    EditText 相比 TextView ,最大的改变是可人为输入内容,安卓系统自诞生到现在,几乎使用的都是虚拟键盘,这就引出了焦点的概念。

    简单的理解,焦点就是当前界面中,跟用户做交互的控件,用户要输入内容,EditText 就需要先获取到焦点,然后弹出输入法,键盘中输入内容,EditText 可以动态显示。

    焦点可以丢失,也可以获得,如果我们需要控制某个 EditText 获取焦点让用户输入信息,就需要动态使用代码来控制:

    mEt.findFocus();
    mEt.requestFocus()
    mEt.clearFocus()
    

    更多时候,我们还需要控制键盘主动弹出或者消失,这里推荐一个比较好的工具类:AndroidUtilCode

    然后找到键盘相关的方法进行调用即可:

    在这里插入图片描述

    二、动态切换明文与密文

    在很多场景(比如 显示银行卡余额 ,或者 输入密码 )下,我们需要对输入或者显示的文字动态密文或者明文,是否显示密文需要用户来控制,这时候,就需要使用如下操作来完成:

    //显示
    mEtPassword.setTransformationMethod(new HideReturnsTransformationMethod());
    
    //隐藏
    mEtPassword.setTransformationMethod( new PasswordTransformationMethod());
    

    三、控制输入文本样式

    在最前面,提到了digits属性,可以来规范输入框中输入的内容,如果输入范围较小,当然可以使用这种方式一一列出,如果限定的范围比较大 ,那么列出所有的可能就不太合理了,因此需要使用其他的方式。

    翻阅前面的属性,还有一个我们没做解释:inputType,这个属性用来规范输入的内容类别,官方解释是这样的:

    在这里插入图片描述

    大致意思是说:

    则用来帮助用户规范如何来输入内容;可以选择单个值,也可以选择多个值,中间以| 符号间隔;如果指定了非 none 外的其他值,则暗示这个文本框为:editable

    inputType 可选下列的值:

    Constant Value Description
    date 4 For entering a date. Corresponds to InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_DATE.
    datetime 4 For entering a date and time. Corresponds to InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_NORMAL.
    none 0 There is no content type. The text is not editable.
    number 2 A numeric only field. Corresponds to InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_NORMAL.
    numberDecimal 2 Can be combined with number and its other options to allow a decimal (fractional) number. Corresponds to InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL.
    numberPassword 2 A numeric password field. Corresponds to InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD.
    numberSigned 2 Can be combined with number and its other options to allow a signed number. Corresponds to InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED.
    phone 3 For entering a phone number. Corresponds to InputType.TYPE_CLASS_PHONE.
    text 1 Just plain old text. Corresponds to InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL.
    textAutoComplete 1 Can be combined with text and its variations to specify that this field will be doing its own auto-completion and talking with the input method appropriately. Corresponds to InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE.
    textAutoCorrect 1 Can be combined with text and its variations to request auto-correction of text being input. Corresponds to InputType.TYPE_TEXT_FLAG_AUTO_CORRECT.
    textCapCharacters 1 Can be combined with text and its variations to request capitalization of all characters. Corresponds to InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS.
    textCapSentences 1 Can be combined with text and its variations to request capitalization of the first character of every sentence. Corresponds to InputType.TYPE_TEXT_FLAG_CAP_SENTENCES.
    textCapWords 1 Can be combined with text and its variations to request capitalization of the first character of every word. Corresponds to InputType.TYPE_TEXT_FLAG_CAP_WORDS.
    textEmailAddress 1 Text that will be used as an e-mail address. Corresponds to InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS.
    textEmailSubject 1 Text that is being supplied as the subject of an e-mail. Corresponds to InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_SUBJECT.
    textFilter b 1 Text that is filtering some other data. Corresponds to InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_FILTER.
    textImeMultiLine 1 Can be combined with text and its variations to indicate that though the regular text view should not be multiple lines, the IME should provide multiple lines if it can. Corresponds to InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE.
    textLongMessage 1 Text that is the content of a long message. Corresponds to InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_LONG_MESSAGE.
    textMultiLine 1 Can be combined with text and its variations to allow multiple lines of text in the field. If this flag is not set, the text field will be constrained to a single line. Corresponds to InputType.TYPE_TEXT_FLAG_MULTI_LINE.
    textNoSuggestions 1 Can be combined with text and its variations to indicate that the IME should not show any dictionary-based word suggestions. Corresponds to InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS.
    textPassword 1 Text that is a password. Corresponds to InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD.
    textPersonName 1 Text that is the name of a person. Corresponds to InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PERSON_NAME.
    textPhonetic c 1 Text that is for phonetic pronunciation, such as a phonetic name field in a contact entry. Corresponds to InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PHONETIC.
    textPostalAddress 1 Text that is being supplied as a postal mailing address. Corresponds to InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS.
    textShortMessage 1 Text that is the content of a short message. Corresponds to InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE.
    textUri 1 Text that will be used as a URI. Corresponds to InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI.
    textVisiblePassword 1 Text that is a password that should be visible. Corresponds to InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD.
    textWebEditText a 1 Text that is being supplied as text in a web form. Corresponds to InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT.
    textWebEmailAddress d 1 Text that will be used as an e-mail address on a web form. Corresponds to InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS.
    textWebPassword e 1 Text that will be used as a password on a web form. Corresponds to InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD.
    time 4 For entering a time. Corresponds to InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_TIME.

    根据 inputType 可以规范输入内容类型,实现预期的效果。

    四、添加Drawable或使用Span

    TextView 或者 说 EditText 拥有一个强大的功能:

    • drawableStart
    • drawableEnd
    • drawableTop
    • drawableBottom

    根据设计图(PS效果图)进行开发时,经常会遇到这种情况:

    在这里插入图片描述

    很简单的,我们一般会把左侧的图标当做drawableStart的属性值,然后添加drawablePadding控制间距。自是不必多说,但如果是这种情况呢?

    在这里插入图片描述

    放置两个TextView当然可以,不过若是布局嵌套很深,或者是使用库中的UI进行布局的话,恐怕就不是很方便了。

    通常情况下,可以使用Span来进行处理:

    //设置高亮色为透明
    this.highlightColor = dispatchGetColor(android.R.color.transparent)
    
    //设置部分可点击
    this.movementMethod = LinkMovementMethod()
    
    SpannableString("重新获取").run {
      setSpan(object : ClickableSpan() {
            override fun onClick(widget: View) {
                route(ARouterConst.Activity_ServiceAgreementActivity).empty(comment = "跳转到协议界面")
            }
    
            override fun updateDrawState(ds: TextPaint) {
                ds.color = dispatchGetColor(R.color.red_ff414c)
            }
        }, 0, length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
        SpannableStringBuilder("没有收到邮件?").append(this)
    }
    

    这样一来,在修改颜色的同时,还给颜色部分添加了点击事件。

    通常我们使用的Span只有寥寥数种:详见:Android中各种Span的用法

    BackgroundColorSpan:给部分文字设置背景颜色
    ForegroundColorSpan:给部分文字设置前景色
    ClickableSpan:设置点击事件
    URLSpan:设置链接,相当于Html的标签
    MaskFilterSpan:文字的装饰效果。分为两种:BlurMaskFilter(模糊效果) 和 EmbossMaskFilter (浮雕效果)
    AbsoluteSizeSpan:设置字体大小
    RelativeSizeSpan:设置字体的相对大小
    ImageSpan:设置图片
    ScaleXSpan:横向压缩
    SubscriptSpan:设置脚注
    SuperscriptSpan:上标,相当于数学中的平方样式
    TextAppearanceSpan:使用style来定义文本样式
    TypefaceSpan:设置字体
    RasterizerSpan:设置光栅字样
    StrikethroughSpan:删除线,相当于购物网站上的划掉的原价
    UnderlineSpan:下划线。
    


    再来考虑一种情况,我们使用的Toolbar控件左上角一般为返回图标:

    在这里插入图片描述

    在基类中,都会处理按钮的点击事件,但设计时不可避免的会碰到这种情况:

    在这里插入图片描述

    Toolbar返回键图标设置方式如下:

    public void setNavigationIcon(@Nullable Drawable icon) {
       //...
    }
    

    或者

    public void setNavigationIcon(@DrawableRes int resId) {
       //...
    }
    

    让UI重新切图,当然可以,不过只是为了这一个功能,就需要切多套图片,是在有些麻烦,这时候,就可以使用 TextDrawable 了,代码逻辑类似如下:

    /**
     * 设置toolbar的navigation为text
     */
    protected final void setToolbarNavText(@NotNull Toolbar t, @Nullable String text, @ColorRes int color) {
        t.post(() -> {
            ColorTextDrawable textDrawable = new ColorTextDrawable(getBaseContext())
                    .setText(TextUtils.isEmpty(text) ? getString(R.string.function_close) : text)
                    .setColor(dispatchGetColor(color))
                    .setTextSize(getResources().getDimensionPixelSize(R.dimen.text_size_title_15sp))
                    .setDefaultBounds();
            t.setNavigationIcon(textDrawable);
        });
    }
    

    详细代码可参考:携带 label 的 text 文本 => 使用 ColorTextDrawable 设定label

    五、ClearText

    文本内容较多时,需要添加删除图标,这样比较方便:

    public class ClearEditText extends AppCompatEditText {
        /**
         * 记录 横坐标
         */
        private float touchX;
    
        /**
         * 左侧点击事件重载
         * 右侧点击事件重载
         */
        private BasePresenter.HttpCallback<Editable> clickLeftCallback;
        private BasePresenter.HttpCallback<Editable> clickRightCallback;
    
        {
            //设置默认的清除标识
            int dimen24 = getResources().getDimensionPixelSize(R.dimen.smallest_view_height_24dp);
    
            Drawable[] compoundDrawables = getCompoundDrawables();
            Drawable drawable = getContext().getDrawable(R.drawable.selector_clear_text);
            drawable.setBounds(0, 0, Math.min(drawable.getMinimumWidth(), dimen24), Math.min(drawable.getMinimumHeight(), dimen24));
            setCompoundDrawables(compoundDrawables[0], compoundDrawables[1], compoundDrawables[2] != null ? compoundDrawables[2] : drawable, compoundDrawables[3]);
        }
    
        public ClearEditText(Context context) {
            super(context);
        }
    
        public ClearEditText(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public ClearEditText(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @SuppressLint("ClickableViewAccessibility")
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    touchX = event.getX();
                    break;
                case MotionEvent.ACTION_UP://如果点击的位置在右侧,并且手指抬起时仍在右侧,那么表示点击的clear标志
                    //计算右侧距离
                    Drawable drawableRight = getCompoundDrawables()[2];
                    if (drawableRight != null) {
                        int judgeX = getWidth() - (drawableRight.getBounds().right - drawableRight.getBounds().left + getCompoundDrawablePadding() / 2 + getPaddingEnd());
                        //如果x位置大于判断基准,且down时位置也大于判断基准,则直接删除内容
                        if (event.getX() > judgeX && touchX > judgeX) {
                            if (clickRightCallback == null) {
                                post(() -> setText(null));
                            } else {
                                clickRightCallback.run(getText());
                            }
                        }
                    }
    
                    //计算左侧距离
                    Drawable drawableLeft = getCompoundDrawables()[0];
                    if (drawableLeft != null) {
                        int judgeX = drawableLeft.getBounds().right - drawableLeft.getBounds().left + getCompoundDrawablePadding() / 2 + getPaddingStart();
                        if (event.getX() < judgeX && touchX < judgeX) {
                            if (clickLeftCallback != null) {
                                clickLeftCallback.run(getText());
                            }
                        }
                    }
                    break;
            }
            return super.onTouchEvent(event);
        }
    
        /**
         * 点击左侧时,进行处理
         */
        public void setOnClickLeft(@Nullable BasePresenter.HttpCallback<Editable> callback) {
            this.clickLeftCallback = callback;
        }
    
        /**
         * 点击左侧时,进行处理
         */
        public void setOnClickRight(@Nullable BasePresenter.HttpCallback<Editable> callback) {
            this.clickRightCallback = callback;
        }
    }
    
    

    逻辑比较简单:

    • 判断是否存在DrawableEnd值,若不存在,则放置一个默认的删除图标
    • 添加onTouchEvent 监听,当点击右侧部分时,执行回调,回调对象不存在或者返回false时,自动删除文本内容。

    六、重写键盘确认,自动完成功能

    现在来这样一种情况:

    存在一个界面,两个输入框,一个按钮,分别表示:手机号验证码登录按钮

      <LinearLayout
            android:id="@+id/linear_loginType1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/view_padding_margin_40dp"
            android:orientation="vertical"
            android:paddingStart="@dimen/view_padding_margin_32dp"
            android:paddingEnd="@dimen/view_padding_margin_32dp">
    
            <EditText
                android:id="@+id/et_phone"
                style="@style/TextViewStandard"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/transparent"
                android:hint="@string/activity_login_please_input_phoneNumber"
                android:imeActionLabel="发送验证码"
                android:imeOptions="actionDone" 
                android:inputType="phone"
                android:paddingStart="0dp"
                android:drawablePadding="@dimen/view_padding_margin_16dp"
                android:drawableStart="@drawable/icon_login_phone"
                android:paddingEnd="0dp"
                android:singleLine="true"
                android:textColorHint="@color/black_text_663a4254"
                android:textSize="@dimen/text_size_title_15sp" />
    
            <com.linktech.hrt.view.DividerView
                android:layout_width="match_parent"
                android:layout_height="@dimen/divider_line_width_1dp" />
    
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">
    
                <EditText
                    android:id="@+id/et_random_code"
                    style="@style/TextViewStandard"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:background="@color/transparent"
                    android:hint="@string/activity_login_please_input_code"
                    android:imeActionLabel="@string/activity_login_submit"
                    android:imeOptions="actionGo"
                    android:drawablePadding="@dimen/view_padding_margin_16dp"
                    android:inputType="number"
                    android:maxLength="6"
                    android:drawableStart="@drawable/icon_login_password"
                    android:paddingStart="0dp"
                    android:paddingEnd="0dp"
                    android:singleLine="true"
                    android:textColorHint="@color/black_text_663a4254"
                    android:textSize="@dimen/text_size_title_15sp" />
    
                <com.linktech.hrt.view.RandomCodeTextView
                    android:id="@+id/rctv_random_code"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:paddingStart="@dimen/view_padding_margin_8dp"
                    android:paddingTop="@dimen/view_padding_margin_4dp"
                    android:paddingEnd="@dimen/view_padding_margin_8dp"
                    android:paddingBottom="@dimen/view_padding_margin_4dp" />
    
            </LinearLayout>
    
            <com.linktech.hrt.view.DividerView
                android:layout_width="match_parent"
                android:layout_height="@dimen/divider_line_width_1dp" />
        </LinearLayout>
    

    注意观察输入控件中的这两行:

    • android:imeOptions="actionDone"
    • android:imeOptions="actionGo"

    布局实现的效果大致是这样:

    在这里插入图片描述

    我们现在要实现的功能是:

    • 1、打开该界面(Activity)时,默认聚焦在 手机号 输入控件;
    • 2、当在虚拟键盘上完成手机号的输入后,只需要点击虚拟键盘右下角按键,即可自动触发验证码发送,同时虚拟键盘消息;
    • 3、发送手机号前如果需要,先动态申请权限,手机号发送成功后,自动捕获短信内容;
    • 4、短信验证码自动输入,并触发登录按钮的点击事件;
    • 5、登录完成后,界面可以退出。

    如果以上功能实现,那我们登录时,所需的只是进入界面 -> 输入手机号 -> 点击回车键,像这类功能,可以很大程度减轻用户的负担。

    接下来,我们就分析如何实现以上效果;

    1、打开界面,自动聚焦

    KeyboardUtils.showSoftInput(mEtPhone);
    mEtPhone.setSelection(mEtPhone .getText().length());
    

    KeyboardUtils所属库为:AndroidUtilCode

    • 第一行代码是将输入法弹出
    • 第二行代码将光标移动输入框中内容的最后

    2、重写回车键逻辑,自动发送验证码/自动点击登录按钮

    首先,为输入框添加监听事件:

    et_phone.setOnEditorActionListener(this)
    et_random_code.setOnEditorActionListener(this)
    

    然后处理两个输入框的逻辑:

    override fun onEditorAction(v: TextView, actionId: Int, event: KeyEvent?): Boolean {
        //当actionId不表示无操作时
        if (actionId != EditorInfo.IME_ACTION_UNSPECIFIED) {
            when (v.id) {
                R.id.et_phone -> rctv_random_code.performClick()  //输入手机号完成,则默认去触发一次获取验证码按钮
                R.id.et_random_code, R.id.et_password -> bt_common_function.performClick()   //输入完验证码或者密码后,直接调用一次登录操作
            }
        }
        return false
    }
    

    手机号输入框监听到返回键时,自动去触发一下获取验证码按钮。

    这里就需要去监听广播了:

    /**
     * 注入短信监听
     */
    @NeedsPermission({Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_SMS, Manifest.permission.RECEIVE_MMS})
    void initSMSReceiver() {
        try {
            BCRMachine.registerBroadcastWithoutCheck(this, this, RemoveTime.onDestroy,
                    (HttpCallback<Pair<String, String>>) tag -> {
    	                //填充验证码
                        mEtRandomCode.setText(tag.second);
                        //触发登录操作
                        mBtLogin.performClick();
                    }, MSmsReceiver.class);
        } catch (Exception e) {
            // TODO: 2018/7/7 非需要的短信
        }
    }
    

    这段代码用了两个框架:

    MSmsReceiver类代码如下:可以拦截六位数字的验证码

    open class MSmsReceiver(httpCallback: HttpCallback<Pair<String, String>>) :
            BaseReceiver<Pair<String, String>>(httpCallback, SMS_DELIVER_ACTION, SMS_RECEIVED_ACTION ,"android.intent.action.MOMS_SMS_RECEIVED") {
    
        /**
         * 处理短信结果
         */
        override fun apply(intentPairFunction: Intent): Pair<String, String> {
            val contact: String
    
            val builder = StringBuilder()
            val bundle = intentPairFunction.extras
    
            if (bundle != null) {
                //从Intent中获取bundle对象,此对象包含了所有的信息,短信是以“pdus”字段存储的。得到的是一个object数组,每个object都包含一条短信,(可能会获取到多条信息)。
                val pdus = bundle.get("pdus") as Array<Any?>? ?: throw RuntimeException("短信无内容")
    
                //新建SmsMessage数组对象存储短信,每个SmsMessage对应一条短信类。
                val messages = arrayOfNulls<SmsMessage>(pdus.size)
                for (i in messages.indices) {
                    messages[i] = SmsMessage.createFromPdu(pdus[i] as ByteArray?)
                }
    
                //获取得到的最末端短信的联系人地址,赋值给contact
                contact = messages.getOrNull(pdus.size - 1)?.displayOriginatingAddress ?: ""
    
                //读取短信内容,getDisplayMessageBody()是获取正文消息。
                for (message in messages) {
                    builder.append(message?.displayMessageBody)
                }
    
                Pair.create(contact, builder.toString()).let {
                    if (it != null && !TextUtils.isEmpty(it.second)) {
                        return Pair(it.first,
                        //const val REGEX_VERIFY_CODE_SMS_EMAIL = "^.*?[^\\d]([\\d]{6})[^\\d].*?$"
                                it.second.replace(RegexConst.REGEX_VERIFY_CODE_SMS_EMAIL.toRegex(), "$1").let {
                                    if (it.matches("[\\d]{6}".toRegex())) it else throw RuntimeException("not require verify code")
                                }
                        )
                    }
                }
            }
    
            throw RuntimeException("无法获取短信内容")
        }
    }
    

    当验证码被应用拦截到以后,自动填充到验证码输入区域,然后触发登录操作,至此,逻辑完成。

    七、输入控件空值检测

    现在很多的设计中,如果界面中输入框没有输入完成,则功能按钮将处于不可点击状态,当然简单的我们可以通过一个个添加Watcher来监控:

    et_random_code.addTextChangedListener(this)
    

    然后当监听回调:

       override fun afterTextChanged(s: Editable?) {
        //当内容变化时,检测界面内所有输入框是否有非空值
        }
    

    不过这样做,麻烦不说,还很有可能存在遗漏之处。

    对此,我们可以新建一个EditText,当值变化时,自动回调,完成逻辑:

    public interface EditTextChangedListener {
        /**
         * 当文本发生变化
         */
        void onExistEditTextChanged(@NonNull WatchInputEditText editText, @NonNull Editable s);
    }
    
    
    public class WatchInputEditText extends AppCompatEditText implements TextWatcher {
        /**
         * 是否绑定空值监听器
         */
        public boolean nullMonitorEnable;
        
        /**
         * 唯一监听器
         */
        private WeakReference<EditTextChangedListener> singleTextNullWatcher;
    
        public WatchInputEditText(Context context) {
            this(context, null);
        }
    
        public WatchInputEditText(Context context, AttributeSet attrs) {
            this(context, attrs, R.attr.editTextStyle);
        }
    
        public WatchInputEditText(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
    
            //检测是否需要监听器
            TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.WatchInputEditText);
            nullMonitorEnable = ta.getBoolean(R.styleable.WatchInputEditText_WatchInputEditText_monitoring, true);
            ta.recycle();
    
            //是否设置监听器
            if (nullMonitorEnable) {
                //添加watcher
                addTextChangedListener(this);
    
                //开始前主动触发一次
                post(() -> {
                    if (singleTextNullWatcher != null && singleTextNullWatcher.get() != null) {
                        singleTextNullWatcher.get().onExistEditTextChanged(this, getText());
                    }
                });
            }
        }
    
        @Override
        protected void onDetachedFromWindow() {
            super.onDetachedFromWindow();
            //移除
            if (nullMonitorEnable) {
                removeTextChangedListener(this);
            }
        }
    
        @Override
        protected void onAttachedToWindow() {
            super.onAttachedToWindow();
            if (!isInEditMode()) {
                if (nullMonitorEnable && singleTextNullWatcher == null) {
                    // 如果 context 满足,则设置为 context
                    List<? extends Fragment> fragments = ((BaseActivity) getContext()).getSupportFragmentManager().getFragments();
    
                    //指定应该谁做listener
                    Object target = getContext() instanceof EditTextChangedListener ? getContext() : null;
    
                    //查找是否应该设置为fragment
                    for (Fragment fragment : fragments) {
                        if (isParentChild(fragment.getView(), this) && fragment instanceof EditTextChangedListener) {
                            target = fragment;
                            break;
                        }
                    }
    
                    //如果目标是EditTextChangedListener子类,则设置为监听器
                    if (target != null) {
                        singleTextNullWatcher = new WeakReference<>((EditTextChangedListener) target);
                    }
                }
            }
    
        }
    
        /**
         * 判断两个view是否构成子父节点关系
         */
        private boolean isParentChild(View parent, View child) {
            //如果是同一个对象,也算是有父子关系
            if (parent == child) {
                return true;
            } else if (parent instanceof ViewGroup) {
                //父节点
                ViewParent child_parent = child.getParent();
                while (true) {
                    //找到了父类为parent
                    if (child_parent == parent) {
                        return true;
                    }
    
                    //找不到目标父类
                    if (child_parent == null) {
                        return false;
                    }
    
                    //重置
                    child_parent = child_parent.getParent();
                }
            } else {
                return false;
            }
        }
    
        /**
         * 设置监听事件
         */
        public void setEditTextChangedListener(EditTextChangedListener singleTextNullWatcher) {
            this.singleTextNullWatcher = new WeakReference<>(singleTextNullWatcher);
        }
    
        /**
         * This method is called to notify you that, within <code>s</code>,
         * the <code>count</code> characters beginning at <code>start</code>
         * are about to be replaced by new text with length <code>after</code>.
         * It is an error to attempt to make changes to <code>s</code> from
         * this callback.
         *
         * @param s
         * @param start
         * @param count
         * @param after
         */
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    
        }
    
        /**
         * This method is called to notify you that, within <code>s</code>,
         * the <code>count</code> characters beginning at <code>start</code>
         * have just replaced old text that had length <code>before</code>.
         * It is an error to attempt to make changes to <code>s</code> from
         * this callback.
         *
         * @param s
         * @param start
         * @param before
         * @param count
         */
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
    
        }
    
        /**
         * This method is called to notify you that, somewhere within
         * <code>s</code>, the text has been changed.
         * It is legitimate to make further changes to <code>s</code> from
         * this callback, but be careful not to get yourself into an infinite
         * loop, because any changes you make will cause this method to be
         * called again recursively.
         * (You are not told where the change took place because other
         * afterTextChanged() methods may already have made other changes
         * and invalidated the offsets.  But if you need to know here,
         * you can use {@link android.text.Spannable} in {@link #onTextChanged}
         * to mark your place and then look up from here where the span
         * ended up.
         *
         * @param s
         */
        @Override
        public void afterTextChanged(Editable s) {
            if (nullMonitorEnable && singleTextNullWatcher != null && singleTextNullWatcher.get() != null) {
                post(() -> singleTextNullWatcher.get().onExistEditTextChanged(this, s));
            }
        }
    }
    
    

    该控件有自定义属性,用于控制是否添加空值检测,如果不开启,则跟一个普通的EditText相同:

        <!--WatchInputEditText:检测文本变化-->
        <declare-styleable name="WatchInputEditText">
            <attr name="WatchInputEditText_monitoring" format="boolean" />
        </declare-styleable>
    

    注意一点,对于监听器的添加,是在onAttachedToWindow中完成的,只有界面显示出来以后才会去处理监听器的逻辑。

    • view所在的Activity实现了 EditTextChangedListener 接口时,会将该Activity当做监听器
    • view所在的Fragment实现了 EditTextChangedListener 接口时,会将该Fragment当做监听器
    • Fragment和Activity都实现了接口,则默认Fragment为监听器

    然后修改Activity和Fragment基类,使其都实现EditTextChangedListener 接口

    对于BaseActivity:BaseFragment:(伪代码)

    public abstract class BaseActivity/BaseFragment extends AppCompatActivity/android.support.v4.app.Fragment implements  EditTextChangedListener{
    	// ...
        /**
         * 当文本发生变化
         *
         * @param editText
         * @param s
         */
        @Override
        public void onExistEditTextChanged(@NonNull WatchInputEditText editText, @NonNull Editable s) {
        
        }
    	// ...
    }
    

    到这,基本的框架就搭建完了,加入现在有个需求是这样:

    当用户在三个输入框内输入内容之前,提交按钮为灰色,不可点击:

    在这里插入图片描述

    当文本框内容有内容时不管内容格式是否正确,只要不为空,提交按钮可点击:

    在这里插入图片描述

    所需代码如下:

    首先,搭建布局文件,使用我们刚自定义的控件:

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <!---->
        <include layout="@layout/layout_top_bar"/>
    
        <!--输入密码-->
        <com.linktech.hrt.view.WatchInputEditText
            android:id="@+id/et_old_password"
            style="@style/TextViewStandard"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/view_padding_margin_10dp"
            android:background="@color/main_color_white"
            android:hint="@string/activity_change_password_hint_old_password"
            android:inputType="textPassword"
            android:maxLength="16"
            android:maxLines="1"
            android:paddingEnd="@dimen/view_padding_margin_16dp"
            android:paddingStart="@dimen/view_padding_margin_16dp"
            android:textColorHint="@color/black_text_c7"
            android:textSize="@dimen/text_size_title_15sp"/>
    
        <com.linktech.hrt.view.DividerView
            android:layout_width="match_parent"
            android:layout_height="@dimen/divider_line_width_1dp"/>
    
        <com.linktech.hrt.view.WatchInputEditText
            android:id="@+id/et_password_one"
            style="@style/TextViewStandard"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/main_color_white"
            android:hint="@string/activity_change_password_hint_one"
            android:inputType="textPassword"
            android:maxLength="16"
            android:maxLines="1"
            android:paddingEnd="@dimen/view_padding_margin_16dp"
            android:paddingStart="@dimen/view_padding_margin_16dp"
            android:textColorHint="@color/black_text_c7"
            android:textSize="@dimen/text_size_title_15sp"/>
    
        <com.linktech.hrt.view.DividerView
            android:layout_width="match_parent"
            android:layout_height="@dimen/divider_line_width_1dp"/>
    
        <com.linktech.hrt.view.WatchInputEditText
            android:id="@+id/et_password_two"
            style="@style/TextViewStandard"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/view_padding_margin_40dp"
            android:background="@color/main_color_white"
            android:hint="@string/activity_change_password_hint_two"
            android:inputType="textPassword"
            android:maxLength="16"
            android:maxLines="1"
            android:paddingEnd="@dimen/view_padding_margin_16dp"
            android:paddingStart="@dimen/view_padding_margin_16dp"
            android:textColorHint="@color/black_text_c7"
            android:textSize="@dimen/text_size_title_15sp"/>
    
        <!--提交按钮:id为 bt_common_function-->
        <include layout="@layout/layout_common_function_button"/>
    </LinearLayout>
    

    控制逻辑也很简单:

    @Route(path = ARouterConst.Activity_ChangePasswordActivity, extras = ARouterConst.FLAG_LOGIN)
    @InjectLayoutRes(layoutResId = R.layout.activity_change_password)
    @InjectActivityTitle(titleRes = R.string.label_change_password)
    class ChangePasswordActivity : BaseActivity<BasePresenter<ChangePasswordActivity>>() {
        /**
         * 成员变量
         */
        private var oldPassword: String by viewBind(R.id.et_old_password)
        private var passwordOne: String by viewBind(R.id.et_password_one)
        private var passwordTwo: String by viewBind(R.id.et_password_two)
    
        override fun initData(savedInstanceState: Bundle?) {
            super.initData(savedInstanceState)
    
            bt_common_function.run {
                text = "提交"
                dOnClick(::verify_password) {
                    mPresenter.changepwd(_username, _signature, oldPassword.toMD5(), passwordOne.toMD5(), passwordTwo.toMD5()) {
                    	//初始化一些缓存变量
                    	// ...
                    	
                    	// 跳转到登录界面
                        routeSuccessFinish(ARouterConst.Activity_LoginActivity).toast("密码修改成功,请重新登陆")
                    }
                }
            }
        }
    
        /**
         * @return true if ok
         */
        private fun verify_password(): Boolean {
            return when {
                oldPassword.isEmpty() -> false.toast("请输入原密码")
                oldPassword notMatch RegexConst.REGEX_PASSWORD -> false.toast("旧密码错误")
                passwordOne.isEmpty() -> false.toast("请输入登录密码")
                passwordTwo.isEmpty() -> false.toast("请确认登录密码")
                passwordOne != passwordTwo -> false.toast("两次输入的新密码不同")
                passwordOne notMatch RegexConst.REGEX_PASSWORD -> false.toast("新密码须为8-16位字母数字组合")
                oldPassword == passwordOne -> false.toast("新密码和旧密码不能相同")
                else -> true
            }
        }
    
        override fun onExistEditTextChanged(editText: WatchInputEditText, s: Editable) {
            super.onExistEditTextChanged(editText, s)
    
            bt_common_function.isEnabled = listOf(oldPassword, passwordOne, passwordTwo).all { it.isNotBlank() }
        }
    }
    
    
    • 类上面的注解,用于指出layouttitle的值
    • 整体使用MVP模式,mPresenter相当于P层的表现对象,用于进行网络请求或者其他操作。
    • 使用到的成员变量其实是借用委托模式,其实操作的是对应的是id资源对应的View控件
    • verify_password方法在用户点击bt_common_function按钮时,进行逻辑验证,验证通过则会发起网络请求
    • onExistEditTextChangedWatchInputEditText自定义控件内容对应的回调接口,当输入框有值发生变化时,该方法会被回调。

    可以看到,在搭建完框架后,对于空值检测并没有增加任何复杂度,额外的,我们还不需要在verify_password中去判断和提醒用户哪个值没有输入,一举两得!

    事实上,EditText功能远不止这些,用的越多,了解的越多,越是能发现其魅力!

    展开全文
  • EditText(输入框)详解

    千次阅读 2016-05-02 16:12:02
    1.设置默认提示文本 如下图,相信你对于这种用户登录的界面并不陌生,是吧,我们很多时候都用的这种界面 相比另外这种,下面这种又如何? ...还不赖是吧,当然,不会在这里贴布局,这里只介绍默认提示文本的两个...

    1.设置默认提示文本

    如下图,相信你对于这种用户登录的界面并不陌生,是吧,我们很多时候都用的这种界面

    相比另外这种,下面这种又如何?

    还不赖是吧,当然,不会在这里贴布局,这里只介绍默认提示文本的两个控制属性:

    默认提示文本的两个属性如下:

    android:hint="默认提示文本"
    android:textColorHint="#95A1AA"

    前者设置提示的文本内容,后者设置提示文本的颜色!


    2.获得焦点后全选组件内所有文本内容

    当我们点击想当我们的输入框获得焦点后,不是将光标移动到文本的开始或者结尾;而是 获取到输入框中所有的文本内容的话!这个时候我们可以使用selectAllOnFocus属性

    android:selectAllOnFocus="true"

    比如下面的效果图: 第一个是设置了该属性的,第二个是没设置该属性的,设置为true的EditText获得焦点后 选中的是所有文本!


    3.限制EditText输入类型

    有时我们可能需要对输入的数据进行限制,比如输入电话号码的时候,你输入了一串字母,这 显然是不符合我们预期的,而限制输入类型可以通过inputType属性来实现!

    比如限制只能为电话号码,密码(textPassword):

    <EditText   
            android:layout_width="fill_parent"   
            android:layout_height="wrap_content"   
            android:inputType="phone" />  

    可选参数如下:

    文本类型,多为大写、小写和数字符号

    android:inputType="none"  
    android:inputType="text"  
    android:inputType="textCapCharacters"  
    android:inputType="textCapWords"  
    android:inputType="textCapSentences"  
    android:inputType="textAutoCorrect"  
    android:inputType="textAutoComplete"  
    android:inputType="textMultiLine"  
    android:inputType="textImeMultiLine"  
    android:inputType="textNoSuggestions"  
    android:inputType="textUri"  
    android:inputType="textEmailAddress"  
    android:inputType="textEmailSubject"  
    android:inputType="textShortMessage"  
    android:inputType="textLongMessage"  
    android:inputType="textPersonName"  
    android:inputType="textPostalAddress"  
    android:inputType="textPassword"  
    android:inputType="textVisiblePassword"  
    android:inputType="textWebEditText"  
    android:inputType="textFilter"  
    android:inputType="textPhonetic" 

    数值类型

    android:inputType="number"  
    android:inputType="numberSigned"  
    android:inputType="numberDecimal"  
    android:inputType="phone"//拨号键盘  
    android:inputType="datetime"  
    android:inputType="date"//日期键盘  
    android:inputType="time"//时间键盘

    4.设置最小行,最多行,单行,多行,自动换行

    EditText默认是多行显示的,并且能够自动换行,即当一行显示不完的时候,他会自动换到第二行

    我们可以对其进行限制,比如
    设置最小行的行数:android:minLines="3"
    或者设置EditText最大的行数:android:maxLines="3"
    PS:当输入内容超过maxline,文字会自动向上滚动!!

    另外很多时候我们可能要限制EditText只允许单行输入,而且不会滚动,比如上面的登陆界面的 例子,我们只需要设置

    android:singleLine="true"</p>
    <p>
    即可实现单行输入不换行</p>
    
    <hr />
    
    <h2>5.设置文字间隔,设置英文字母大写类型</h2>
    
    <p>我们可以通过下述两个属性来设置字的间距:
    </p>
    <pre>
    android:textScaleX="1.5"    //设置字与字的水平间隔
    android:textScaleY="1.5"    //设置字与字的垂直间隔

    另外EditText还为我们提供了设置英文字母大写类型的属性:android:capitalize 默认none,提供了三个可选值:

    • sentences:仅第一个字母大写
    • words:每一个单词首字母大小,用空格区分单词
    • characters:每一个英文字母都大写

    6.控制EditText四周的间隔距离与内部文字与边框间的距离

    我们使用margin相关属性增加组件相对其他控件的距离,比如android:marginTop = "5dp" 使用padding增加组件内文字和组件边框的距离,比如android:paddingTop = "5dp"


    7.设置EditText获得焦点,同时弹出小键盘

    关于这个EditText获得焦点,弹出小键盘的问题,前不久的项目中纠结了笔者一段时间 需求是:进入Activity后,让EditText获得焦点,同时弹出小键盘供用户输入! 试了很多网上的方法都不可以,不知道是不是因为笔者用的5.1的系统的问题! 下面小结下:

    首先是让EditText获得焦点与清除焦点的

    edit.requestFocus(); //请求获取焦点
    edit.clearFocus(); //清除焦点

    获得焦点后,弹出小键盘,笔者大部分时间就花在这个上:

    • 低版本的系统直接requestFocus就会自动弹出小键盘了
    • 稍微高一点的版本则需要我们手动地去弹键盘: 第一种:
    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);

    第二种:

    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);     imm.showSoftInput(view,InputMethodManager.SHOW_FORCED);  
    imm.hideSoftInputFromWindow(view.getWindowToken(), 0); //强制隐藏键盘  

    不知道是什么原因,上面这两种方法并没有弹出小键盘,笔者最后使用了:windowSoftInputMode属性解决了弹出小键盘的问题,这里跟大家分享下:

    android:windowSoftInputMode Activity主窗口与软键盘的交互模式,可以用来避免输入法面板遮挡问题,Android1.5后的一个新特性。
    这个属性能影响两件事情:
    【一】当有焦点产生时,软键盘是隐藏还是显示
    【二】是否减少活动主窗口大小以便腾出空间放软键盘

    简单点就是有焦点时的键盘控制以及是否减少Act的窗口大小,用来放小键盘
    有下述值可供选择,可设置多个值,用"|"分开
    stateUnspecified:软键盘的状态并没有指定,系统将选择一个合适的状态或依赖于主题的设置
    stateUnchanged:当这个activity出现时,软键盘将一直保持在上一个activity里的状态,无论是隐藏还是显示
    stateHidden:用户选择activity时,软键盘总是被隐藏
    stateAlwaysHidden:当该Activity主窗口获取焦点时,软键盘也总是被隐藏的
    stateVisible:软键盘通常是可见的
    stateAlwaysVisible:用户选择activity时,软键盘总是显示的状态
    adjustUnspecified:默认设置,通常由系统自行决定是隐藏还是显示
    adjustResize:该Activity总是调整屏幕的大小以便留出软键盘的空间
    adjustPan:当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分

    我们可以在AndroidManifest.xml为需要弹出小键盘的Activity设置这个属性,比如:

    然后在EditText对象requestFocus()就可以了~


    8.EditText光标位置的控制

    有时可能需要我们控制EditText中的光标移动到指定位置或者选中某些文本!
    EditText为我们提供了setSelection()的方法,方法有两种形式:


    一个参数的是设置光标位置的,两个参数的是设置起始位置与结束位置的中间括的部分,即部分选中!
    当然我们也可以调用setSelectAllOnFocus(true);让EditText获得焦点时选中全部文本!
    另外我们还可以调用setCursorVisible(false);设置光标不显示
    还可以调用getSelectionStart()getSelectionEnd获得当前光标的前后位置


    9.带表情的EditText的简单实现

    相信大家对于QQ或者微信很熟悉吧,我们发送文本的时候可以连同表情一起发送,有两种简单的实现方式:

    1.使用SpannableString来实现
    2.使用Html类来实现
    这里笔者用的是第一种,这里只实现一个简单的效果,大家可以把方法抽取出来,自定义一个EditText;
    也可以自己动手写个类似于QQ那样有多个表情选择的输入框!

    看下效果图(点击添加表情即可完成表情添加):

    代码也很简单:

    public class MainActivity extends Activity {
        private Button btn_add;
        private EditText edit_one;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            btn_add = (Button) findViewById(R.id.btn_add);
            edit_one = (EditText) findViewById(R.id.edit_one);
            btn_add.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    SpannableString spanStr = new SpannableString("imge");
                    Drawable drawable = MainActivity.this.getResources().getDrawable(R.drawable.f045);
                    drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());
                    ImageSpan span = new ImageSpan(drawable,ImageSpan.ALIGN_BASELINE);
                    spanStr.setSpan(span,0,4,Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    int cursor = edit_one.getSelectionStart();
                    edit_one.getText().insert(cursor, spanStr);
                }
            });
        }
    }

    PS:对了,别忘了放一个图片哦~


    10.带删除按钮的EditText

    我们常常在App的输入界面上看到:


    当我们输入内容后,右面会出现这样一个小叉叉的图标,我们点击后会清空输入框中的内容!
    实现起来其实也很简单:
    为EditText设置addTextChangedListener,然后重写TextWatcher()里的抽象方法,这个用于监听输入框变化的;然后setCompoundDrawablesWithIntrinsicBounds设置小叉叉的图片;最后,重写onTouchEvent方法,如果点击区域是小叉叉图片的位置,清空文本!

    实现代码如下:

    public class EditTextWithDel extends EditText {
    
        private final static String TAG = "EditTextWithDel";
        private Drawable imgInable;
        private Drawable imgAble;
        private Context mContext;
    
        public EditTextWithDel(Context context) {
            super(context);
            mContext = context;
            init();
        }
    
        public EditTextWithDel(Context context, AttributeSet attrs) {
            super(context, attrs);
            mContext = context;
            init();
        }
    
        public EditTextWithDel(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mContext = context;
            init();
        }
    
        private void init() {
            imgInable = mContext.getResources().getDrawable(R.drawable.delete_gray);
            addTextChangedListener(new TextWatcher() {
                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                }
    
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                }
    
                @Override
                public void afterTextChanged(Editable s) {
                    setDrawable();
                }
            });
            setDrawable();
        }
    
        // 设置删除图片
        private void setDrawable() {
            if (length() < 1)
                setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
            else
                setCompoundDrawablesWithIntrinsicBounds(null, null, imgInable, null);
        }
    
        // 处理删除事件
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (imgInable != null && event.getAction() == MotionEvent.ACTION_UP) {
                int eventX = (int) event.getRawX();
                int eventY = (int) event.getRawY();
                Log.e(TAG, "eventX = " + eventX + "; eventY = " + eventY);
                Rect rect = new Rect();
                getGlobalVisibleRect(rect);
                rect.left = rect.right - 100;
                if (rect.contains(eventX, eventY))
                    setText("");
            }
            return super.onTouchEvent(event);
        }
        @Override
        protected void finalize() throws Throwable {
            super.finalize();
        }
    }
    展开全文
  • 安卓EditText使用总结

    千次阅读 2018-09-11 16:08:15
    本文是在日常开发中所遇到的EditText使用需求的总结。 一、光标移动到文本框末尾。 if (!TextUtils.isEmpty(editText.getText())) { editText.setSelection(editText.getText().length()); } 二、实现搜索功能...
  • EditText

    千次阅读 2020-02-24 21:08:19
    一、EditText的一些常用属性 第一部分 这里是界面的代码粘贴出来,里面有注释来加以说明 **<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=...
  • Android中EditText的常见属性

    万次阅读 2018-03-22 03:00:27
    EditText介绍:EditText 在开发中也是经常用到的控件,也是一个比较必要的组件,可以说...EditText实例:开发中常用的登录界面首先我们来看布局文件:activity_main.xml&lt;?xml version="1.0" encoding...
  • 记得两周前写过关于@功能的简单实现, 那次的实现思路是监听删除字符串, 如果删除一个字符并且该字符是unicode编码为 8197 的字符, 就查找@符号并删除整个@字符串. 刚好上周做到了@的需求, 完全推翻了上篇博客的思路 ...
  • EditText属性及一些常用用法

    万次阅读 2016-12-24 14:21:26
    EditText 属性及一些常用用法
  • EditText可以设置多种输入方式,其中若要设置输入数字和小数点时应注意一下几点: 有两种写法:一、利用安卓自身的语法。二、利用正则表达式。 一、利用安卓自身的语法 1.如果设置只输入数字 edittext....
  • 隐藏android中EditText的下划线

    万次阅读 多人点赞 2016-02-29 15:14:28
    有的时候需要隐藏掉EditText的边框和下划线,代码为: 主要是这一栏:android:background="@null"<EditText style="?android:attr/textViewStyle" android:layout_width="wrap_content" android:layout_heig
  • 前几天一同学项目中的某个功能需要ListView+EditText来实现,希望我给他写个Demo,自己就随手写了一个小的Demo。后来想了想觉得这个功能其实挺常用的,而且期间也踩了几个坑,就整理了一下决定写成博客,希望能够帮...
  • Android 更改EditText下划线的颜色样式

    万次阅读 多人点赞 2017-04-17 00:07:55
    当你使用AppCompatEditText(Edit Text)时,默认的下划线是跟随系统的#FF4081的颜色值的,通过改变这个值可以改变所有的颜色样式,但是有时候你想单独定义某一个界面的颜色样式,则可以这样做。
  • EditText 的 drawableRight

    2013-07-01 02:24:54
    <EditText android:id="@+id/account_et" android:layout_width="match_parent" android:layout_height="fill_parent" android:layout_weight="1" android:drawableRight="@drawable/icon_backall" ...
  • RecyclerView 完美嵌套EditText

    千次阅读 2020-01-06 10:38:08
    RecyclerView中item嵌套EditText,总是会出现,焦点错乱,数据错乱 主要原因在于,EditText焦点发生变化的时候,监听也在变化,数据就会不断变化 解决方法:监听焦点变化,有焦点就添加:addTextChangedListener ;...
  • 关于基本控件EditText属性大全详解

    千次阅读 2016-04-04 21:57:03
     把该EditText设为:android:password="true" // 以”.”形式显示文本 (2)在代码里设置: 通过设置EditText的setTransformationMethod()方法来实现隐藏密码或这显示密码。 editText.setTransformationMet
  • 最近在写些小Demo复习基础,在用到EditText的时候突然发现之前几乎没有注意到它的光标和下划线的颜色,于是花了不少时间,看了不少博客,现在就来总结和分享一下收获。 1、第一印象:原生的EditText 我们要在原生...
  • EditText点击全选

    2016-07-28 15:51:55
    EditText点击全选:touch监听和xml属性
  • 问题是程序中有一个EditText,但是不能填充父类。如果我移除上面的主题,它就能很好地填满。 android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation=...
  • Android中EditText去掉下划线的方法

    万次阅读 2018-07-06 10:35:04
    在XML文件中找到相关EditText的代码, 1:添加如下属性:android:background=“@null” 可能会出现如下图的问题,如果出现这个问题就直接按第二个方法。 2:这个时候另外一种解决办法是:直接android:...

空空如也

1 2 3 4 5 ... 20
收藏数 118,831
精华内容 47,532
关键字:

edittext