Android 从5.0版本开始,新增了Android Materia Design库,让开发者高效的实现炫酷的UI效果

推荐:

TextInputLayout(文本输入布局)
TabLaout(选项卡布局)
Snackbar
FloatingActionButton(浮动按钮)
NavigationView(导航视图)
AppBarLayout(程序栏布局)
CoordinatorLayout(协作布局)
CollapsingToolbarLayout(折叠工具栏布局)

本篇文章将介绍Materia Design库的TextInputLayout与TextInputEditText组件

TextInputLayout
TextInputLayout用于辅助EditText,当用户输入文本时,在EditText上方显示浮动标签,这个标签的内容就是我们设置的android:hint属性.

TextInputLayout 属于Android Design Support library,可以直接向下兼容到Android 2.2.

TextInputLayout 继承于Linerlayout,说明它是一个布局,需要配合子控件使用才能显示想要的效果,类似ScrollView的用法
TextInputLayout 属性说明


app:Theme    设置下划线或其他的颜色属性
android.support.design:counterEnabled    是否显示计数器
android.support.design:counterMaxLength    设置计数器的最大值,与counterEnabled同时使用
android.support.design:counterTextAppearance    计数器的字体样式
android.support.design:counterOverflowTextAppearance    输入字符大于我们限定个数字符时的字体样式
android.support.design:errorEnabled    是否显示错误信息
android.support.design:errorTextAppearance    错误信息的字体样式
android.support.design:hintAnimationEnabled    是否显示hint的动画,默认true
android.support.design:hintEnabled    是否使用hint属性,默认true
android.support.design:hintTextAppearance    设置hint的文字样式(指运行动画效果之后的样式)
android.support.design:passwordToggleDrawable    设置密码开关Drawable图片,于passwordToggleEnabled同时使用
android.support.design:passwordToggleEnabled    是否显示密码开关图片,需要EditText设置inputType
android.support.design:passwordToggleTint    设置密码开关图片颜色
android.support.design:passwordToggleTintMode    设置密码开关图片(混合颜色模式),与passwordToggleTint同时使用

 

TextInputLayout使用

一、moudle的bulid.gradle 添加依赖库:

dependencies { compile 'com.android.support:appcompat-v7:25.3.1' compile 'com.android.support:design:26.0.0-alpha1' }

 

二、XML布局文件设置属性

<?xml version="1.0" encoding="utf-8"?>                                                                                                                                                            

三、MainActivity中调用控件
其实做完上面两步就已经有效果了,这里简单的演示下:

EditText.setError()和TextInputLayout.setError()的简单监听

EditText.setCompoundDrawables()和EditText.setCompoundDrawablesWithIntrinsicBounds()的简单使用
 

public class TextInputLayoutActivity extends AppCompatActivity {    private TextInputEditText mEditText_customize;    private TextInputLayout   mTil_customize;    private EditText          mEditText;    private TextInputLayout   mTextInputLayout;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_text_input_layout);        //自定义密码开关输入框        mEditText_customize = (TextInputEditText) findViewById(R.id.editText_customize);        mTil_customize = (TextInputLayout) findViewById(R.id.til_customize);        //系统自带的密码开关输入框        mEditText = (EditText) findViewById(R.id.editText);        mTextInputLayout = (TextInputLayout) findViewById(R.id.til);        testSetCompoundDrawables();        testSetCompoundDrawablesWithIntrinsicBounds();        customizeEditText();        TextInputLyout_EditText();    }    /**     * 测试EditText.setCompoundDrawablesWithIntrinsicBounds()     * 

* 可以在上、下、左、右设置图标,如果不想在某个地方显示,则设置为null。 *

* 图标的宽高将会设置为固有宽高,既自动通过getIntrinsicWidth和getIntrinsicHeight获取。 *

* 即:这种方式只能显示原图 */ private void testSetCompoundDrawablesWithIntrinsicBounds() { Drawable drawable = getResources().getDrawable(R.mipmap.edit_lock); EditText editText_drawable = (EditText) findViewById(R.id.editText_drawable2); editText_drawable.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null); } /** * 测试EditText.setCompoundDrawables() *

* 可以在上、下、左、右设置图标,如果不想在某个地方显示,则设置为null。 *

* 但是Drawable必须要setBounds(Rect)。设置初始位置、宽和高等信息。 *

* 即:使用前要先调用Drawable.setBounds(),可以调整图片的大小和相对位置 */ private void testSetCompoundDrawables() { Drawable drawable = getResources().getDrawable(R.mipmap.edit_lock); drawable.setBounds(0, 0, 40, 40); EditText editText_drawable = (EditText) findViewById(R.id.editText_drawable); editText_drawable.setCompoundDrawables(drawable, null, null, null); } /** * 系统自带的密码开关输入框的错误信息处理 */ private void TextInputLyout_EditText() { mEditText.addTextChangedListener(new TextWatcher() { @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) { if (mEditText.getText().length() > mTextInputLayout.getCounterMaxLength()) { mTextInputLayout.setError("超出限定字数了..."); } } }); } /** * 自定义密码开关输入框的错误信息处理 */ private void customizeEditText() { mEditText_customize.addTextChangedListener(new TextWatcher() { @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) { if (mEditText_customize.getText().length() > mTil_customize.getCounterMaxLength()) { mEditText_customize.setError("超出限定字数了!!"); } } }); }}

注意:

1.添加库的时候注意要加appcompat-v7库,确保可以向后兼容
2.TextInputLayout下的实际视图层次结构不能保证以XML格式编写视图层次结构。 因此,对于TextInputLayout的子对象EditText(或子类TextInputEditText)想调用getParent()可能不会返回TextInputLayout. 如果您需要直接访问视图,建议设置一个android:id并使用findViewById(int).
3.一个TextInputLayout只能套一个EditText(或它的子类TextInputEditText)
4.当使用passwordToggleDrawable密码开关图片的时候,EditText end位置的 图标时会被覆盖的,为了保证EditText end 位置Drawable的正常显示,你需要在设置这些Drawables 的相对位置(start/end)为绝对(left/right).(官方文档说的,没搞懂)
5.使用了TextInputLayout,和它的setError(),布局所占的位置会变多,设计布局注意留适当的空间
6.EditText的setError和passwordToggleDrawable的图片会重叠,建议只用TextInputLatyout的setError或者重写EditText的布局
7.TextInputLayout.setError()注意调用setErrorEnabled(false)清空错误信息,不然会一直显示
8.建议TextInputLayout只套一个EditText,放其他控件会出现焦点抢占的问题(View的事件分发)

9.EditText的imeOptions要与inputType同时使用,不然没有反应

TextInputEditText TextInputEditText是EditText的子类,说白了是为了填EditText的坑的 当我们的界面处于全屏时,点击一个EditText,默认情况下不是在它下面弹出键盘,而是进入到输入法的一个全屏的输入界面(通过配置android:imeOptions=”flagNoExtractUi”可以设为直接在当前界面显示) 如果我们给EditText 套上了一个TextInputLayout时,TextInputLayout会拿到EditText的hint显示出来并把EditText本身的hint设为空.这样我们在全屏的输入界面上,就显示不出来我们设置hint,因此TextInputEditText重写了EditText

四、TextInputLayout几种颜色设置的方式(包括EditText)

1.布局:

<?xml version="1.0" encoding="utf-8"?>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    

设置:android:theme="@style/CustomAppTheme_textinputLayout"

如果你要放在5.0以下的版本你会发现颜色并没有改变,这时候你需要给你当前activity单独指定一个theme

  
                 

长时间放后台运行再次回到界面即使没有使用TextInputLayout的error提示作用会发现线都变红了这时候你需要在代码中设置禁用

TextInputLayout.setErrorEnabled(false);

浮动hint改变size :

 

app:hintTextAppearance="@style/TextLabel"

2.主函数代码:

public class TextInputLayoutActivity extends AppCompatActivity {    private TextInputLayout textinputlayout_email;    private TextInputLayout textinputlayout_name;    private TextInputLayout textinputlayout_password;    private TextInputLayout textinputlayout_code;    private EditText et_email;    private EditText et_name;    private EditText et_password;    private EditText et_code;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_textinputlayout);        ButterKnife.bind(this);        et_name = findViewById(R.id.et_name);        et_email = findViewById(R.id.et_email);        et_password = findViewById(R.id.et_password);        et_code = findViewById(R.id.et_code);        textinputlayout_name = findViewById(R.id.textinputlayout_name);        textinputlayout_email = findViewById(R.id.textinputlayout_email);        textinputlayout_password = findViewById(R.id.textinputlayout_password);        textinputlayout_code = findViewById(R.id.textinputlayout_code);        et_email.addTextChangedListener(new TextWatcher() {            @Override            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {            }            @Override            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {//                if (!RegexUtils.isEmail(charSequence)) {//                    textInputLayout.setError("邮箱格式错误");//                    textInputLayout.setErrorEnabled(true);//                } else {//                    textInputLayout.setErrorEnabled(false);//                }                if (!isValidEmail(et_email.getText())) {//                        edittext2.setError("Email is invalid");//                        textInputLayout2.setError("Email is invalid");                    textinputlayout_email.setError("邮箱格式错误");                    textinputlayout_email.setErrorEnabled(true);                } else {//                        textinputlayout_email.setError(null);                    textinputlayout_email.setErrorEnabled(false);                }                //邮箱输入框清空后,颜色恢复默认                if (TextUtils.isEmpty(et_email.getText().toString().trim())) {                    textinputlayout_email.setErrorEnabled(false);                }                if (charSequence.toString().length() < 1) {                    textinputlayout_email.setErrorEnabled(false);                }            }            @Override            public void afterTextChanged(Editable editable) {            }        });        et_email.setOnFocusChangeListener(new View.OnFocusChangeListener() {            @Override            public void onFocusChange(View v, boolean hasFocus) {                if (!hasFocus) {                    if (!isValidEmail(et_email.getText())) {//                        et_email.setError("Email is invalid");//                        textInputLayout2.setError("Email is invalid");                    } else {//                        textInputLayout2.setError(null);                    }                }            }        });        et_code.addTextChangedListener(new TextWatcher() {            @Override            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {            }            @Override            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {//                if (!RegexUtils.isEmail(charSequence)) {//                    textInputLayout.setError("邮箱格式错误");//                    textInputLayout.setErrorEnabled(true);//                } else {//                    textInputLayout.setErrorEnabled(false);//                }                if (!isValidEmail(et_code.getText())) {//                        edittext2.setError("Email is invalid");                    et_code.setError("Email is invalid");                    textinputlayout_code.setError("邮箱格式错误");                    textinputlayout_code.setErrorEnabled(true);                } else {                    textinputlayout_code.setError(null);                    textinputlayout_code.setErrorEnabled(false);                }                //邮箱输入框清空后,颜色恢复默认                if (TextUtils.isEmpty(et_code.getText().toString().trim())) {                    textinputlayout_code.setErrorEnabled(false);                }                if (charSequence.toString().length() < 1) {                    textinputlayout_code.setErrorEnabled(false);                }            }            @Override            public void afterTextChanged(Editable editable) {            }        });        et_code.setOnFocusChangeListener(new View.OnFocusChangeListener() {            @Override            public void onFocusChange(View v, boolean hasFocus) {                if (!hasFocus) {                    if (!isValidEmail(et_code.getText())) {//                        et_email.setError("Email is invalid");//                        textInputLayout2.setError("Email is invalid");                    } else {//                        textInputLayout2.setError(null);                    }                }            }        });    }    public static boolean isValidEmail(CharSequence target) {        return !TextUtils.isEmpty(target) && android.util.Patterns.EMAIL_ADDRESS.matcher(target).matches();    }//    介绍://    app:counterEnabled="true" //设置为true才能显字符数//    app:counterMaxLength="5" //设置最大字符数为5//    app:counterOverflowTextAppearance="@style/HintError" //设置超出字符数后提示文字的颜色,如果不设置默认为@color/colorAccent的颜色//    android:layout_height="wrap_content">}
                

3.常见写法:

布局:

<?xml version="1.0" encoding="utf-8"?>                


 

package com.per.textinputlayout;import android.app.Activity;import android.os.Bundle;import android.support.design.widget.TextInputLayout;public class MainActivity extends Activity {    private TextInputLayout textinputlayout;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        textinputlayout= (TextInputLayout) findViewById(R.id.text_input_layout);        textinputlayout.setErrorEnabled(true);        textinputlayout.setError("请检查手机号码是否正确");    }}

其中app:errorTextAppearance="@style/MyErrorStyle"表示错误提示的样式,如果想更改错误提示的样式的话,也可以在style.xml文件里面,自定义一个style

 

主函数:

package com.per.textinputlayout;import android.app.Activity;import android.os.Bundle;import android.support.design.widget.TextInputLayout;import android.text.Editable;import android.text.TextUtils;import android.text.TextWatcher;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.Toast;public class OtherActivity extends Activity implements View.OnClickListener {    private TextInputLayout mLayoutPhone, mLayoutPwd, mLayoutEmail;    private EditText mEtPhone, mEtPwd, mEtEmail;    private Button mBtnLogin;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_other);        initView();    }    private void initView() {        mLayoutPhone = (TextInputLayout) findViewById(R.id.layout_phone);        mLayoutPwd = (TextInputLayout) findViewById(R.id.layout_pwd);        mLayoutEmail = (TextInputLayout) findViewById(R.id.layout_email);        mEtPhone = (EditText) findViewById(R.id.et_phone);        mEtPwd = (EditText) findViewById(R.id.et_pwd);        mEtEmail = (EditText) findViewById(R.id.et_email);        mBtnLogin = (Button) findViewById(R.id.login);        //设置监听事件        mBtnLogin.setOnClickListener(this);        mEtPhone.addTextChangedListener(new MyTextWatcher(mEtPhone));        mEtPwd.addTextChangedListener(new MyTextWatcher(mEtPwd));        mEtEmail.addTextChangedListener(new MyTextWatcher(mEtEmail));    }    @Override    public void onClick(View v) {        switch (v.getId()) {            case R.id.login:                Login();                break;            default:                break;        }    }    /**     * 登录     */    private void Login() {        if (!isNameValid()) {            showMessage(getString(R.string.error_phone));            return;        }        if (!isPasswordValid()) {            showMessage(getString(R.string.error_pwd));            return;        }        if (!isEmailValid()) {            showMessage(getString(R.string.error_email));            return;        }        showMessage(getString(R.string.login_success));    }    /**     * 检查输入的手机号码是否为空以及格式是否正确     *     * @return     */    public boolean isNameValid() {        String phone = mEtPhone.getText().toString().trim();        if (TextUtils.isEmpty(phone) || !RegularUtils.isPhone(phone)) {            mLayoutPhone.setErrorEnabled(true);            mLayoutPhone.setError(getString(R.string.error_phone));            mEtPhone.requestFocus();            return false;        }        mLayoutPhone.setErrorEnabled(false);        return true;    }    /**     * 检查输入的密码是否为空     *     * @return     */    public boolean isPasswordValid() {        String pwd = mEtPwd.getText().toString().trim();        if (TextUtils.isEmpty(pwd)) {            mLayoutPwd.setErrorEnabled(true);            mLayoutPwd.setError(getResources().getString(R.string.error_pwd));            mEtPwd.requestFocus();            return false;        }        mLayoutPwd.setErrorEnabled(false);        return true;    }    /**     * 检查输入的邮箱是否为空以及格式是否正确     *     * @return     */    public boolean isEmailValid() {        String email = mEtEmail.getText().toString().trim();        if (TextUtils.isEmpty(email) || !RegularUtils.isEmail(email)) {            mLayoutEmail.setErrorEnabled(true);            mLayoutEmail.setError(getString(R.string.error_email));            mLayoutEmail.requestFocus();            return false;        }        mLayoutEmail.setErrorEnabled(false);        return true;    }    //动态监听输入过程    private class MyTextWatcher implements TextWatcher {        private View view;        private MyTextWatcher(View view) {            this.view = view;        }        @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) {            switch (view.getId()) {                case R.id.et_phone:                    isNameValid();                    break;                case R.id.et_pwd:                    isPasswordValid();                    break;                case R.id.et_email:                    isEmailValid();                    break;            }        }    }    private void showMessage(String message) {        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();    }}

检测手机号码与邮箱工具类:

package com.per.textinputlayout;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * 检测手机号码,邮箱等是否有效 */public class RegularUtils {    /**     * 要更加准确的匹配手机号码只匹配11位数字是不够的,比如说就没有以144开始的号码段,     * 故先要整清楚现在已经开放了多少个号码段,国家号码段分配如下:     * 移动:134、135、136、137、138、139、150、151、157(TD)、158、159、187、188     * 联通:130、131、132、152、155、156、185、186   电信:133、153、180、189、(1349卫通)     */    public static boolean isPhone(String param) {        Pattern p = Pattern.compile("^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$");        Matcher m = p.matcher(param);        return m.matches();    }    /**     * 判断email格式是否正确     */    public static boolean isEmail(String email) {        String str = "^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$";        Pattern p = Pattern.compile(str);        Matcher m = p.matcher(email);        return m.matches();    }}
<?xml version="1.0" encoding="utf-8"?>                                                                                                

相关案例源码:

https://github.com/student9128/TextInPutDemo

https://blog.csdn.net/shiki60215/article/details/79214060

https://github.com/Carson-Ho/SuperEditText

更多相关文章

  1. 状态栏提示Notification
  2. Android(安卓)沉浸式状态栏归纳
  3. Android(安卓)自定义控件
  4. Android学习笔记7&s3c2440学习系列8
  5. Android(安卓)7.0 Audio :通话中的音频调用接口
  6. Android实用小技巧(持续更新)
  7. eclipse 中设置android emulator 选项
  8. Android(安卓)TextView当中设置超链接、颜色、字体
  9. 无法在Android(安卓)Studio中设置断点

随机推荐

  1. android语音识别和合成第三方
  2. Android shape实现订单卡片制作(shape画半
  3. Android(安卓)事件分发源码分析
  4. Xamarin开发Android时Visual Studio 2012
  5. Android UI测量、布局、绘制过程探究
  6. 【Android】自定义dialog的布局样式
  7. android源码导入
  8. Android Studio默认创建的view学习笔记
  9. 【Android】adapter has changed解决方法
  10. Native C applications for Android