我正在使用Android Design Library中的TextInputLayout在EditText上显示标签。
问题是当我开始活动时,EditText提示(标签)文本与实际文本重叠(一秒钟),然后返回到它自己的位置(在EditText的顶部)。
为了说明这个问题,我录制了一个简短的示例视频:https://youtu.be/gy0CzcYggxU
这是我的activity.xml:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:id="@+id/firstNameTextInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp">
<EditText
android:id="@+id/firstNameEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/first_name"
android:inputType="textCapWords"
android:textColor="@color/textPrimary"
android:textColorHint="@color/textSecondary"
android:textSize="16sp"
android:theme="@style/CustomEditText"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp">
<EditText
android:id="@+id/lastNameEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/last_name"
android:inputType="textCapWords"
android:textColor="@color/textPrimary"
android:textColorHint="@color/textSecondary"
android:textSize="16sp"
android:theme="@style/CustomEditText"/>
</android.support.design.widget.TextInputLayout>
我为此提出了一个廉价的解决方法和另一个bug。
对TextInputLayout进行子类化 查看addView()的代码 如果在文本视图中对文本进行充气时设置了文本,则会将提示设置为折叠并阻止动画。此代码执行一种解决方法,将临时设置文本,直到在安装过程中设置状态。作为奖励,有代码可以确保在只有一个布局传递的情况下绘制提示。
public class TextInputLayout extends android.support.design.widget.TextInputLayout {
public TextInputLayout(Context context) {
super(context);
}
public TextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@SuppressLint("DrawAllocation")
@Override
protected void onLayout(final boolean changed, final int left, final int top, final int right, final int bottom) {
if (ViewCompat.isLaidOut(this)) {
super.onLayout(changed, left, top, right, bottom);
} else {
// Workaround for this terrible logic where onLayout gets called before the view is flagged as laid out.
// The normal TextInputLayout is depending on isLaidOut when onLayout is called and failing the check which prevents initial drawing
// If there are multiple layout passes this doesn't get broken
post(new Runnable() {
@SuppressLint("WrongCall")
@Override
public void run() {
TextInputLayout.super.onLayout(changed, left, top, right, bottom);
}
});
}
}
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
if (child instanceof EditText) {
EditText editText = (EditText) child;
if (StringUtils.isEmpty(editText.getText().toString())) {
editText.setText(" "); // Set filler text so the initial state of the floating title is to be collapsed
super.addView(child, index, params);
editText.setText(""); // Set back to blank to cause the hint to animate in just in case the user sets text
// This prevents the hint from being drawn over text that is set programmatically before the state is determined
return;
}
}
super.addView(child, index, params);
}
}
您可以通过一个小延迟以编程方式设置提示。这不是一个理想的解决方案,但至少它看起来比重叠提示更好。
new Handler().postDelayed(
new Runnable() {
@Override
public void run () {
textInputLayout.setHint("My hint");
}
}, 100
);
对我有用的解决方法是更新这样的活动:
@Override
protected void onCreate(Bundle savedInstanceState) {
...
textInputLayout.setHintAnimationEnabled(false);
textInput.setText("sample");
textInputLayout.setHintAnimationEnabled(true);
...
}
终于找到了问题的充分解释:
事实证明,Android 4.0中的框架中添加了一个性能优化,它允许在启动Activity动画之前,您的视图层次结构只有一个绘制通道。活动动画结束后,您的视图层次结构将按照您的预期每隔~16毫秒绘制一次。
阅读更多:https://medium.com/@chrisbanes
TLDR:它是平台限制,旧版本(Marshmallow和更低版本)会出现此行为。
在Nougat动画将按预期运行没有滞后。
我认为这可以修复为编译'com.android.support:design:23.0.1'
Daniel Ochoa注意到评论中的一个解决方法对我有用 - 为EditText设置一些文本内容的初始状态(空字符串应该这样做)。这将迫使提示的初始状态上升。
<android.support.design.widget.TextInputLayout
android:id="@+id/firstNameTextInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp">
<EditText
android:id="@+id/firstNameEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/first_name"
android:inputType="textCapWords"
android:textColor="@color/textPrimary"
android:textColorHint="@color/textSecondary"
android:textSize="16sp"
android:theme="@style/CustomEditText"
android:text=" "/>
</android.support.design.widget.TextInputLayout>