android - 自定义 TextInputLayout 在后按时设置错误的值
问题描述
在我的应用程序中,我使用包含TextInputLayout
以下代码的自定义视图:
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/input_layout"
style="@style/UbiInput2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="-"
android:orientation="horizontal"
app:boxBackgroundColor="@color/white">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/input_value"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="textPersonName" />
</com.google.android.material.textfield.TextInputLayout>
</androidx.appcompat.widget.LinearLayoutCompat>
和科特林
class TextInputView(context: Context, attrs: AttributeSet?) : LinearLayout(context, attrs) {
var errorMessage: String? = ""
init {
inflate(context, R.layout.text_input_view, this)
val attributes = context.obtainStyledAttributes(attrs, R.styleable.TextInputView)
val inputLayout = findViewById<TextInputLayout>(R.id.input_layout)
val inputValue = findViewById<TextInputEditText>(R.id.input_value)
inputLayout.hint = attributes.getString(R.styleable.TextInputView_hint)
inputValue.hint = attributes.getString(R.styleable.TextInputView_placeholderText)
inputLayout.isExpandedHintEnabled =
attributes.getBoolean(R.styleable.TextInputView_expandedHintEnabled, true)
errorMessage = attributes.getString(R.styleable.TextInputView_errorMessage)
inputLayout.isHelperTextEnabled = false
inputValue.inputType =
attributes.getInt(
R.styleable.TextInputView_android_inputType,
InputType.TYPE_CLASS_TEXT
)
if (attributes.hasValue(R.styleable.TextInputView_android_maxLength)) {
inputValue.filters += InputFilter.LengthFilter(
attributes.getInt(
R.styleable.TextInputView_android_maxLength,
100
)
)
}
inputValue.gravity =
attributes.getInt(R.styleable.TextInputView_android_gravity, Gravity.START)
if (attributes.getBoolean(R.styleable.TextInputView_android_gravity, false)) {
inputLayout.helperText = attributes.getString(R.styleable.TextInputView_helperText)
}
if (attributes.getBoolean(R.styleable.TextInputView_helperTextEnabled, false)) {
inputLayout.isHelperTextEnabled = true
inputLayout.helperText = attributes.getString(R.styleable.TextInputView_helperText)
}
inputLayout.startIconDrawable =
attributes.getDrawable(R.styleable.TextInputView_startIconDrawable)
attributes.recycle()
}
}
@BindingAdapter("textValue")
fun TextInputView.setTextValue(value: String?) {
value?.let {
setValue(value)
}
}
@InverseBindingAdapter(attribute = "textValue")
fun TextInputView.getTextValue(): String {
return value()
}
@BindingAdapter("textValueAttrChanged")
fun TextInputView.setListener(textAttrChanged: InverseBindingListener) {
val inputValue = findViewById<TextInputEditText>(R.id.input_value)
inputValue.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
textAttrChanged.onChange()
}
})
}
我有以下屏幕,点击按钮会转到下一个片段。使用导航组件。
但是在下一个屏幕上,当我按下返回按钮返回搜索表单时,和的TextInputLayout
值都是相同的。我设置这些的唯一地方是在自定义视图中。从调试中我可以看到当时设置了所有正确的值。hint
helperText
我有点不知道那里发生了什么。任何提示将不胜感激。
使用的材料库版本:1.3.0-alpha04
所有代码库已根据最新更改迁移到视图绑定
视图使用如下:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewModel"
type="com.ubigo.features.v2.products.taxi.SearchViewModel" />
<variable
name="dateFormat"
type="com.ubigo.ubicore.date.UbiDate" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/rental_search_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/background">
<androidx.cardview.widget.CardView
android:id="@+id/rental_search_form"
style="@style/WhiteCardView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView10">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout3"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.ubigo.ubicore.ui.TextInputView
android:id="@+id/pickup"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
app:hint="@string/product_start"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:startIconDrawable="@drawable/ic_calendar"
app:textValue="@{dateFormat.getPrettyDate(viewModel.pickupDateTime)}" />
<View
android:id="@+id/divider6"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:background="?android:attr/listDivider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/pickup" />
<com.ubigo.ubicore.ui.TextInputView
android:id="@+id/dropoff"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:hint="@string/product_end"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/divider6"
app:startIconDrawable="@drawable/ic_calendar"
app:textValue="@{dateFormat.getPrettyDate(viewModel.destinationDatetime)}" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
<com.ubigo.ubicore.ui.LoaderButton
android:id="@+id/rental_search_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
android:text="@string/product_rental_show_car"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/rental_search_location" />
<androidx.cardview.widget.CardView
android:id="@+id/rental_search_location"
style="@style/WhiteCardView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/rental_search_form">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraintLayout4"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.ubigo.ubicore.ui.TextInputView
android:id="@+id/user_location"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:helperText="@string/product_rental_location"
app:helperTextEnabled="true"
app:hint="@string/product_pickup_location"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:startIconDrawable="@drawable/ic_location_on_black_24dp"
app:textValue="@{viewModel.depAddress}" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/textView10"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="32dp"
android:text="@string/product_rental_weekend"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
以及片段的初始化:
class RentalSearchFragment : Fragment() {
val viewModel: SearchViewModel by viewModel()
private val binding get() = _binding!!
private var _binding: FragmentRentalSearchBinding? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
if (_binding == null) {
_binding = FragmentRentalSearchBinding.inflate(inflater, container, false)
binding.lifecycleOwner = viewLifecycleOwner
binding.viewModel = viewModel
binding.dateFormat = UbiDate()
}
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
解决方案
我能够通过实现 onSaveInstanceState、onRestoreInstanceState、dispatchSaveInstanceState、dispatchRestoreInstanceState 和 setValues 来解决这个确切的问题,如此处所述
http://www.devexchanges.info/2016/03/custom-compound-view-in-android.html
上面的链接介绍了有关如何实现这些功能的所有必要细节。毫无疑问,您还可以找到无数其他有关如何实现此 android 范例的资源。
推荐阅读
- flutter - 用于扩展子的 toJson 方法的父类 - 或如何使用干净的架构模式嵌套 json
- jenkins - git checkouts 多次,尽管在 Jenkins 管道中只签出一次
- laravel - 如何将简单版本的 Vue 3 安装到 Laravel 8 项目中?
- web - 网站托管服务加载问题
- openiddict - OpenIdDict 在不使用降级模式的情况下扩展现有的程序流程,或者改为扩展现有的默认实现
- python-3.x - 如何在 s3 文件夹上搜索正则表达式匹配,并解析文件
- javascript - Angular 12 更新让我的字体看起来不一样了
- wikipedia - 如何使用 dbpedia 在维基百科上获取公司的结构化数据?
- maven - 迁移到 java 9 模块时无法使用 maven-jar-plugin 构建可执行 jar
- azure - Azure:无法从 ARM 部署 FortiGate - 错误“不支持提供‘未知’支付工具...”