TextInputLayout TextInputEditTe
默认效果图
image.png布局
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/input_host"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dialog_item_logo_txt_padding"
android:layout_toRightOf="@+id/iv_host_logo"
android:textColorHint="@color/item_divider_dark_gray"
app:boxBackgroundColor="#00000000"
app:hintTextAppearance="@style/OurTextInputHint"
app:boxStrokeColor="@color/blue_gray_state_color">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/et_host"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/ID_BOOK_INFO_HOST"
android:minWidth="@dimen/book_edit_text_width"
android:singleLine="true"
android:text="x"
android:imeOptions="actionDone"
android:textColor="@color/dialog_item_text_color"
android:textSize="20sp" />
</com.google.android.material.textfield.TextInputLayout>
上边那个hint文字的颜色设置textColorHint 这个是state状态的,选中状态可以变个深色
app:hintTextAppearance :hint的文字其他属性,比如大小,只能通过这个设置了
<style name="OurTextInputHint" parent="TextAppearance.Design.Hint">
<item name="android:textSize">16sp</item>
</style>
可以看下源码,Layout的默认属性是这个,点进去看这个style就知道有啥了
private static final int DEF_STYLE_RES = R.style.Widget_Design_TextInputLayout;
<style name="Widget.Design.TextInputLayout" parent="android:Widget">
<item name="materialThemeOverlay">@style/ThemeOverlay.Design.TextInputEditText</item>
<item name="enforceMaterialTheme">false</item>
<item name="enforceTextAppearance">false</item>
<item name="boxBackgroundMode">none</item>
<item name="boxStrokeColor">@color/design_box_stroke_color</item>
<item name="passwordToggleDrawable">@drawable/design_password_eye</item>
<item name="passwordToggleTint">@color/design_icon_tint</item>
<item name="passwordToggleContentDescription">@string/password_toggle_content_description</item>
<item name="endIconTint">@color/design_icon_tint</item>
<item name="startIconTint">@color/design_icon_tint</item>
<item name="counterTextAppearance">@style/TextAppearance.Design.Counter</item>
<item name="counterOverflowTextAppearance">@style/TextAppearance.Design.Counter.Overflow</item>
<item name="errorTextAppearance">@style/TextAppearance.Design.Error</item>
<item name="helperTextTextAppearance">@style/TextAppearance.Design.HelperText</item>
<item name="hintTextAppearance">@style/TextAppearance.Design.Hint</item>
<item name="counterTextColor">@null</item>
<item name="counterOverflowTextColor">@null</item>
<item name="errorTextColor">@null</item>
<item name="helperTextTextColor">@null</item>
<item name="hintTextColor">@null</item>
<item name="shapeAppearance">@null</item>
<item name="shapeAppearanceOverlay">@null</item>
</style>
TextInputEditText
这个其实没太多的东西,就是和TextInputLayout交互下hint的值而已。
如果它自己没有设置hint,那就取容器也就是TextInputLayout的hint值。
@Override
public CharSequence getHint() {
// Certain test frameworks expect the actionable element to expose its hint as a label. When
// TextInputLayout is providing our hint, retrieve it from the parent layout.
TextInputLayout layout = getTextInputLayout();
if ((layout != null) && layout.isProvidingHint()) {
return layout.getHint();
}
return super.getHint();
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
final InputConnection ic = super.onCreateInputConnection(outAttrs);
if (ic != null && outAttrs.hintText == null) {
// If we don't have a hint and our parent is a TextInputLayout, use its hint for the
// EditorInfo. This allows us to display a hint in 'extract mode'.
outAttrs.hintText = getHintFromLayout();
}
return ic;
}
@Nullable
private TextInputLayout getTextInputLayout() {
ViewParent parent = getParent();
while (parent instanceof View) {
if (parent instanceof TextInputLayout) {
return (TextInputLayout) parent;
}
parent = parent.getParent();
}
return null;
}
@Nullable
private CharSequence getHintFromLayout() {
TextInputLayout layout = getTextInputLayout();
return (layout != null) ? layout.getHint() : null;
}
先看一些参数的效果
- app:boxBackgroundColor , boxBackgroundMode
<com.google.android.material.textfield.TextInputLayout
app:boxBackgroundMode="filled">
<com.google.android.material.textfield.TextInputLayout
android:background="@mipmap/adp_logo"
app:boxBackgroundColor="#E91E63"
app:boxBackgroundMode="outline">
boxBackgroundMode:3种,默认的filled,还有outline以及none
为filled,有个灰色背景色,edittext 点击以后,下边是一条线,主题色
而且好像上边2个角是圆角
app:boxBackgroundColor 可以修改背景色。
android:background :会被boxBackgroundColor的颜色挡住,可能看不见
image.png
app:boxBackgroundMode:
为none的时候,背景直接没了,成透明的拉;
为outline的时候,hint是显示在文字顶部的,还带个白色背景。这次不是底部有条线了,而是成了边框,颜色是主题色
image.png
- 背景的圆角
上边说了,默认的顶部2个角是圆角的,可以如下修改4个角
app:boxCornerRadiusBottomEnd="10dp"
app:boxCornerRadiusBottomStart="10dp"
app:boxCornerRadiusTopStart="10dp"
app:boxCornerRadiusTopEnd="10dp"
- 选中以后底部那条线【filled模式】,或者边框的颜色[outline模式]
app:boxStrokeColor="#009688"
strokeColor是支持state的,也就是聚焦和非聚焦不同的颜色,上边那种直接设置个颜色,那么就是foucus的颜色拉。
//boxStrokeColor 如果是单独的色值,非isStateful的情况,就走的else,也就是给了focusColor
//如果有state的话,对应设置下if里的3种state颜色就可以拉。
ColorStateList boxStrokeColorStateList =
MaterialResources.getColorStateList(context, a, R.styleable.TextInputLayout_boxStrokeColor);
if (boxStrokeColorStateList != null && boxStrokeColorStateList.isStateful()) {
defaultStrokeColor = boxStrokeColorStateList.getDefaultColor();
disabledColor =
boxStrokeColorStateList.getColorForState(new int[] {-android.R.attr.state_enabled}, -1);
hoveredStrokeColor =
boxStrokeColorStateList.getColorForState(new int[] {android.R.attr.state_hovered}, -1);
focusedStrokeColor =
boxStrokeColorStateList.getColorForState(new int[] {android.R.attr.state_focused}, -1);
} else {
// If attribute boxStrokeColor is not a color state list but only a single value, its value
// will be applied to the box's focus state.
focusedStrokeColor =
a.getColor(R.styleable.TextInputLayout_boxStrokeColor, Color.TRANSPARENT);
defaultStrokeColor =
ContextCompat.getColor(context, R.color.mtrl_textinput_default_box_stroke_color);
disabledColor = ContextCompat.getColor(context, R.color.mtrl_textinput_disabled_color);
hoveredStrokeColor =
ContextCompat.getColor(context, R.color.mtrl_textinput_hovered_box_stroke_color);
}
app:boxStrokeWidth="5dp" 看到有个属性,设置了下,感觉没效果
- hint文字
正确的合理做法是随便哪个其中一个设置hint就行,
Layout和EditText都设置了,那么就各是各的,如下图,
<com.google.android.material.textfield.TextInputLayout
android:hint="hint layout">
<com.google.android.material.textfield.TextInputEditText
android:textColorHint="#FF5722"
android:hint="hint">
image.png
2个都设置了,非聚焦状态可以看到2个重叠在一起了。
image.png
- hint文字距离顶部的距离
设置太大就没意义了,高度超过Layout的高度就不可见了。
app:boxCollapsedPaddingTop="0dp"
image.png
5.hint 文字style设置
复杂的比如字体大小,需要用TextAppearance来设置
简单的修改颜色就用hintTextColor,这个颜色优先级比上边appearance高
image.png
<style name="hintText" parent="Widget.Design.TextInputLayout">
<item name="android:textSize">16sp</item>
</style>
- helperText 相关
app:helperText="helper text"
app:helperTextTextColor="#009688"
app:helperTextEnabled="true"
app:helperTextTextAppearance="@style/test"
默认的属性,enalbe默认也是true的
<item name="helperTextTextAppearance">@style/TextAppearance.Design.HelperText</item>
<item name="helperTextTextColor">@null</item>
效果图,java代码里也有对应的方法可以处理
image.png
- 字数统计
app:counterEnabled="true"
app:counterMaxLength="20"
app:counterTextColor="@color/colorAccent"
app:counterOverflowTextColor="@color/txt_black_white"
app:counterTextAppearance="@style/test"//字体还可以设置style,其他类似,后边不在说这种
默认是不可用的,2种颜色,
counterMaxLength的值来决定,
比这个大的就是overflow颜色,否则就是正常的app:counterTextColor
注意事项,这2个color都不能直接使用#000000这种,必须是一个color资源也就是@color/xxx
image.png
- endIcon
看名字就猜到末尾有个icon
主要就是看mode区分作用的,
none:默认的,就是不显示icon,你设置了也没用。It will not display an end icon
clear_text :点击一下文字清除
password_toggle: 密码显示明文与否的开关
custom: icon会显示,就是没点击效果而已。
app:endIconDrawable="@mipmap/book_add"
app:endIconMode="clear_text"
注意事项:password_toggle的时候,你里边的EditText的inputType需要是password才行
- error text
布局里可以启用,以及设置颜色,显示的文字就需要代码里写了
调用Layout的setError方法即可,
app:errorEnabled="true"
app:errorTextColor="#ff0000"
可以看到:
errorText会隐藏 helper text,字数太长会把后边的counter也就是字数统计,挤到看不见了。
说下,如果你设置了errorText很长,把counter挤没了,接着你设置errorText为空,counter也不会还原的,你需要设置errorEnable为false,counter才能还原。
image.png
helper text和error text一样的效果,把counter挤到看不见了,
image.png
-
passwordToggle
这个好像弃用了,就是endIcon里的mode为password_toggle的效果,建议用endIcon -
startIcon
上边有图,前边显示的那个加号就是
···
app:startIconDrawable="@mipmap/book_add"
···
基本相关的属性都看完了,然后看下源码,了解下布局结构,也就方便理解上边的一些效果咋来的了
源码解析
先打印下结构,没找到那个hint,难道不是个view?等待看完源码再说
至少发现,EditText被取出来放到一个FrameLayout里了.
helper text和error text这两个文本是在一个FrameLayout里的
public class TextInputLayout extends LinearLayout{
public TextInputLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
setOrientation(VERTICAL);//垂直方向的线性布局
inputFrame = new FrameLayout(context);
inputFrame.setAddStatesFromChildren(true);
addView(inputFrame);//先加了一个帧布局进来
collapsingTextHelper.setCollapsedTextGravity(Gravity.TOP | GravityCompat.START);
//就是那个动画的hint文字,位置,collapsed时候的重心,左上角
endIconView =
(CheckableImageButton)
LayoutInflater.from(getContext())
.inflate(R.layout.design_text_input_end_icon, inputFrame, false);
inputFrame.addView(endIconView);
endIconView.setVisibility(GONE);
}