这在当前的实现中似乎是不可能的TextInputLayout
。但是你可以通过使用TextInputEditText
.
假设您有这样的 aTextInputLayout
和 a TextInputEditText
:
<android.support.design.widget.TextInputLayout
android:id="@+id/text_input_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FAA"
android:hint="Text hint">
<android.support.design.widget.TextInputEditText
android:id="@+id/text_input_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#AAF" />
</android.support.design.widget.TextInputLayout>
正如您所看到的,TextInputLayout
它由一个用于保存小版本提示的顶部区域和一个用于保存大版本提示(以及输入内容)的底部区域组成。当视图失去焦点并且编辑文本为空时,提示在蓝色空间内移动。另一方面,当视图获得焦点或编辑文本中有一些文本时,提示正在移动到红色区域。
所以我们要做的是:
TextInputEditText
当内部没有焦点和文本时,在底部添加一个额外的填充,这个填充等于红色区域的高度;
TextInputEditText
当内部有焦点或文本时删除此填充。
结果,视图看起来像这样,大提示垂直居中:
假设您检索视图如下:
private lateinit var textInputLayout: TextInputLayout
private lateinit var textInputEditText: TextInputEditText
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
...
textInputLayout = view.findViewById(R.id.text_input_layout)
textInputEditText = view.findViewById(R.id.text_input_edit_text)
...
}
这是一个实现示例,您可以使用它来计算以像素为单位的顶部红色空间。
private fun getTextInputLayoutTopSpace(): Int {
var currentView: View = textInputEditText
var space = 0
do {
space += currentView.top
currentView = currentView.parent as View
} while (currentView.id != textInputLayout.id)
return space
}
然后你可以像这样更新填充:
private fun updateHintPosition(hasFocus: Boolean, hasText: Boolean) {
if (hasFocus || hasText) {
textInputEditText.setPadding(0, 0, 0, 0)
} else {
textInputEditText.setPadding(0, 0, 0, getTextInputLayoutTopSpace())
}
}
现在你必须在两个地方调用这个方法:当视图被创建时(实际上我们需要等待视图被完全测量)和焦点改变时。
textInputLayout.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw(): Boolean {
if (textInputLayout.height > 0) {
textInputLayout.viewTreeObserver.removeOnPreDrawListener(this)
updateHintPosition(textInputEditText.hasFocus(), !textInputEditText.text.isNullOrEmpty())
return false
}
return true
}
})
textInputEditText.setOnFocusChangeListener { _, hasFocus ->
updateHintPosition(hasFocus, !textInputEditText.text.isNullOrEmpty())
}
一个问题是高度在TextInputLayout
变化,因此所有视图都在移动,并且看起来并不真正居中。您可以通过将TextInputLayout
内部 a放置在FrameLayout
固定高度并将其垂直居中来解决此问题。
最后,您可以为所有内容设置动画。更改填充时,您只需要使用TransitionManager
支持库的 。
您可以在此链接中看到最终结果:https ://streamable.com/la9uk
完整的代码将如下所示:
布局:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="60dp"> <-- Adapt the height for your needs -->
<android.support.design.widget.TextInputLayout
android:id="@+id/text_input_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="#FAA"
android:hint="Text hint">
<android.support.design.widget.TextInputEditText
android:id="@+id/text_input_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#AAF" />
</android.support.design.widget.TextInputLayout>
</FrameLayout>
编码:
private lateinit var textInputLayout: TextInputLayout
private lateinit var textInputEditText: TextInputEditText
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
val view = inflater.inflate(R.layout.your_layout, container, false)
textInputLayout = view.findViewById(R.id.text_input_layout)
textInputEditText = view.findViewById(R.id.text_input_edit_text)
textInputLayout.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw(): Boolean {
// Wait for the first draw to be sure the view is completely measured
if (textInputLayout.height > 0) {
textInputLayout.viewTreeObserver.removeOnPreDrawListener(this)
updateHintPosition(textInputEditText.hasFocus(), !textInputEditText.text.isNullOrEmpty(), false)
return false
}
return true
}
})
textInputEditText.setOnFocusChangeListener { _, hasFocus ->
updateHintPosition(hasFocus, !textInputEditText.text.isNullOrEmpty(), true)
}
return view
}
private fun updateHintPosition(hasFocus: Boolean, hasText: Boolean, animate: Boolean) {
if (animate) {
TransitionManager.beginDelayedTransition(textInputLayout)
}
if (hasFocus || hasText) {
textInputEditText.setPadding(0, 0, 0, 0)
} else {
textInputEditText.setPadding(0, 0, 0, getTextInputLayoutTopSpace())
}
}
private fun getTextInputLayoutTopSpace(): Int {
var currentView: View = textInputEditText
var space = 0
do {
space += currentView.top
currentView = currentView.parent as View
} while (currentView.id != textInputLayout.id)
return space
}
我希望这能解决你的问题。