07.04 控件-EditText

2021/9/19 Android 开发基础

EditText (opens new window)(输入框),是一个可以接受用户输入的文本内容的控件。输入框控件在日常软件中是很常见的,如登录界面的用户名和密码输入场景,搜索界面的搜索框场景等等。

基本属性:

  • android:hint 默认提示文本
  • android:textColorHint 提示文本的颜色
  • android:selectAllOnFocus 控件获得焦点后将全选组件内所有文本内容
  • android:inputType 指定输入的类型
  • android:minLines 设置最小行数显示
  • android:maxLines 设置最大行数显示
  • android:singleLine 限制单行显示
  • android:textScaleX 设置文字的水平间隔
  • android:textScaleY 设置文字的垂直间隔
  • android:capitalize 字母的大写类型

# 基本使用

先来看一个输入框的基本使用,带有“文字提示”和“指定的提示颜色”的一个基本的输入框。

示例:

xml布局:

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

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入内容"
        android:textColorHint="#03A9F4" />
</LinearLayout>

效果:

EditText 基本使用

# 输入的类型

可以通过指定inputType属性进行输入类型的指定,详细属性可以参考R.styleable.TextView_inputType (opens new window)

文本类型

  • 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" URI格式
  • 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" 时间键盘
  • android:inputType="numberPassword" 数字密码格式

示例:

xml布局:

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

    <!-- 电话号码(拨号键盘)类型 -->
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="电话号码"
        android:inputType="phone"
        android:textColorHint="#03A9F4" />

    <!-- 带小数的数字类型 -->
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="带小数的数字"
        android:inputType="numberDecimal"
        android:textColorHint="#03A9F4" />

    <!-- 文本密码类型 -->
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="文本密码"
        android:inputType="textPassword"
        android:textColorHint="#03A9F4" />

    <!-- 单词首字母大小类型 -->
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="单词首字母大小"
        android:inputType="textCapWords"
        android:textColorHint="#03A9F4" />
</LinearLayout>

效果:

EditText 输入类型效果图1

EditText 输入类型效果图2

# 行数显示

EditText 默认是可以多行显示的,当输入一行显示不完会自动换行显示。这个时候可以通过一些属性限制其行数的显示(当超过最大行数时,文字将会向上滚动显示,控件可以上下滑动内容),类似于 TextView 控件。

属性:

  • android:minLines 最小行数
  • android:maxLines 最大行数
  • android:singleLine 单行显示

示例:

xml布局:

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

    <!-- 默认换行显示 -->
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp" />

    <!-- 限制最大3行显示 -->
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:maxLines="3"
        android:textSize="20sp" />

    <!-- 限制单行显示 -->
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:singleLine="true"
        android:textSize="20sp" />

</LinearLayout>

效果:

EditText 行数显示效果

# Action类型

我们经常可以在一些软件上看到,输入搜索框中输入文字后输入法显示“搜索”字样,聊天窗口输入文字后输入法显示“发送”字样,信息填写框中输入文字后输入法显示“完成”字样,输入法是怎么知道你输入文字后的动作类型的呢?那就是可以设置 android:imeOptions 属性来告诉输入法输入文本后的动作类型,然后可以通过设置 setOnEditorActionListener 方式来监听输入法相关类型按钮的操作。

常用属性:

  • android:actionUnspecified 未指定,对应常量EditorInfo.IME_ACTION_UNSPECIFIED.
  • android:actionNone 没有动作,对应常量EditorInfo.IME_ACTION_NONE
  • android:actionGo 去往,对应常量EditorInfo.IME_ACTION_GO
  • android:actionSearch 搜索,对应常量EditorInfo.IME_ACTION_SEARCH
  • android:actionSend 发送,对应常量EditorInfo.IME_ACTION_SEND
  • android:actionNext 下一个,对应常量EditorInfo.IME_ACTION_NEXT
  • android:actionDone 完成,对应常量EditorInfo.IME_ACTION_DONE
  • 更多请参考:imeOptions (opens new window)

提示:

  1. 设置动作类型,需要指定 android:inputType="text",如果不指定可能属性不生效。
  2. 如果布局是多个 EditText,为每个 EditText 控件设置 android:singleLine=”true”,弹出的软盘输入法中回车键为 next,直到最后一个获取焦点后显示为 Done,点击 Done 后,软盘输入键盘便隐藏。或者将 EditText 的 imeOptions 属性设置android:imeOptions=”actionDone”,则不管是不是最后一个 EditText,点击回车键即隐藏输入法。
  3. 设置相应的动作属性后,可以通过 setOnEditorActionListener 或者 setOnKeyListener 监听输入法触发这些动作操作。

示例:

xml布局:

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

    <!-- 搜索类型 -->
    <EditText
        android:id="@+id/et_demo_search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="actionSearch"
        android:imeOptions="actionSearch"
        android:inputType="text" />

    <!-- 完成类型 -->
    <EditText
        android:id="@+id/et_demo_done"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="actionDone"
        android:imeOptions="actionDone"
        android:inputType="text" />

</LinearLayout>

示例代码:

mEtSearch = findViewById(R.id.et_demo_search);
mEtDone = findViewById(R.id.et_demo_done);
// 监听actionListener,获取输入法操作完成响应
TextView.OnEditorActionListener actionListener = new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        switch (actionId) {
            case EditorInfo.IME_ACTION_SEARCH:
                Log.i(TAG, "onEditorAction: IME_ACTION_SEARCH");
                break;
            case EditorInfo.IME_ACTION_DONE:
                Log.i(TAG, "onEditorAction: IME_ACTION_DONE");
                break;
            default:
                break;
        }

        return false;
    }
};
mEtSearch.setOnEditorActionListener(actionListener);
mEtDone.setOnEditorActionListener(actionListener);

// 监听keyEvent的KEYCODE_ENTER,获取输入法操作完成响应, 当imeOptions="actionDone"后没有此回调
// 注意:点击动作按钮和输入法退出都会有enter事件回调
View.OnKeyListener keyListener = new View.OnKeyListener() {
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_ENTER) {
            Log.i(TAG, "onKey: KEYCODE_ENTER");
        }
        return false;
    }
};
mEtSearch.setOnKeyListener(keyListener);
mEtDone.setOnKeyListener(keyListener);

执行结果:

DemoActivity: onEditorAction: IME_ACTION_SEARCH
DemoActivity: onKey: KEYCODE_ENTER
DemoActivity: onKey: KEYCODE_ENTER
DemoActivity: onEditorAction: IME_ACTION_DONE

效果:

EditText Action类型效果图

# 输入监听

在输入框输入文字的时候,实时监听输入的文字,可以通过 addTextChangedListener (opens new window) 添加监听器来实时监听输入文本变化,用于实时输入文本处理的功能。比较常见的场景就是搜索框根据输入实时的模糊搜索功能。

示例代码:

mEtSearch = findViewById(R.id.et_demo_search);
mEtSearch.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        // 变化前的文本
        Log.i(TAG, "beforeTextChanged: s = " + s.toString()
                + ", start = " + start
                + ", count = " + count
                + ", after = " + after);
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        // 变化的文本
        Log.i(TAG, "onTextChanged: s = " + s.toString()
        + ", start = " + start
        + ", before = " + before
        + ", count = " + count);
    }

    @Override
    public void afterTextChanged(Editable s) {
        // 变化后文本
        Log.i(TAG, "afterTextChanged: s = " + s.toString());
    }
});

执行结果:输入hello文字

DemoActivity: beforeTextChanged: s = , start = 0, count = 0, after = 1
DemoActivity: onTextChanged: s = h, start = 0, before = 0, count = 1
DemoActivity: afterTextChanged: s = h
DemoActivity: beforeTextChanged: s = h, start = 0, count = 1, after = 2
DemoActivity: onTextChanged: s = he, start = 0, before = 1, count = 2
DemoActivity: afterTextChanged: s = he
DemoActivity: beforeTextChanged: s = he, start = 0, count = 2, after = 3
DemoActivity: onTextChanged: s = hel, start = 0, before = 2, count = 3
DemoActivity: afterTextChanged: s = hel
DemoActivity: beforeTextChanged: s = hel, start = 0, count = 3, after = 4
DemoActivity: onTextChanged: s = hell, start = 0, before = 3, count = 4
DemoActivity: afterTextChanged: s = hell
DemoActivity: beforeTextChanged: s = hell, start = 0, count = 4, after = 5
DemoActivity: onTextChanged: s = hello, start = 0, before = 4, count = 5
DemoActivity: afterTextChanged: s = hello

# 光标和文本选中

控制 EditText 中的光标移动到指定位置或者选中某些文本,有以下方式可以实现:

  • setSelection(int index) 设置获取焦点后,光标的位置。
  • setSelection(int start, int stop) 设置获取焦点后,选中起始位置的文本。
  • setSelectAllOnFocus(boolean selectAllOnFocus) 设置获取焦点后,是否全选文本。
  • setCursorVisible(boolean visible) 设置光标是否显示。
  • getSelectionStart() 获取选中文本的开始位置。
  • getSelectionEnd() 获取选中文本的结束位置。

注意:

一般控制光标的移动或者文件的选中,需要 EditText 对象的获取到焦点后才能生效,获取焦点可以调用requestFocus()方法。

当操作的参数不合法或者超出范围的情况,会有相应的异常出现,使用的话需要考虑到其异常情况。

# 软键盘交互

Activity 中的 windowSoftInputMode 属性主要是用来设置窗口软键盘的交互模式的,这个属性会有两个影响:

1)当有焦点产生时,软键盘是隐藏还是显示。

2)是否减少活动主窗口大小以便腾出空间放软键盘。

在AndroidManifest.xml为需要弹出小键盘的Activity设置这个属性,调用EditText对象的requestFocus()方法。

有下述值可供选择,可设置多个值,用"|"分开:

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

进入activity,EditText自动弹出输入法可以实现以下的方法:

1)在AndroidManifest的 Activity 节点中添加 android:windowSoftInputMode="stateVisible"

2)调用EditText对象requestFocus()方法请求焦点。

注意:

在低版本系统中,只需要调用 EditText.requestFocus() 方法就可以自动弹出输入法键盘,高版本中必须要配置windowSoftInputMode,调用请求焦点才有效。

  • EditText.requestFocus() 请求获取焦点
  • EditText.clearFocus() 清除焦点

# 结束

本节主要介绍了 EditText 控件的基本属性和相应的使用方式,大多数开发中都是需要自定义 EditText 来实现各种差异化的需求的,如需了解更多请自行深入研究。