Android <include> navigateUp() 后的布局变化

Android <include> layout change after navigateUp()

我有一个 activity 有两个片段。我创建了一个可重复使用的布局,如下所示:

这里是自定义布局xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<androidx.appcompat.widget.AppCompatTextView
    android:id="@+id/tvFormTitle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="@color/black1"
    android:textSize="@dimen/ssp_10"
    android:visibility="visible"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:text="Email" />

<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/clForm"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/sdp_4"
    android:background="@drawable/sh_all_round_form"
    android:paddingStart="@dimen/sdp_12"
    android:paddingEnd="@dimen/sdp_12"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/tvFormTitle">

    <androidx.appcompat.widget.AppCompatEditText
        android:id="@+id/etForm"
        style="@style/et_form"
        android:layout_width="0dp"
        android:layout_weight="1"
        app:layout_constraintEnd_toStartOf="@+id/ivSwitchPassword"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/ivSwitchPassword"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:paddingStart="@dimen/sdp_8"
        android:paddingTop="@dimen/sdp_8"
        android:paddingEnd="@dimen/sdp_2"
        android:paddingBottom="@dimen/sdp_8"
        android:src="@drawable/ic_eye"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="@+id/etForm"
        app:layout_constraintEnd_toStartOf="@+id/ivCancel"
        app:layout_constraintTop_toTopOf="@+id/etForm" />

    <androidx.appcompat.widget.AppCompatImageView
        android:id="@+id/ivCancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:paddingStart="@dimen/sdp_12"
        android:paddingTop="@dimen/sdp_12"
        android:paddingBottom="@dimen/sdp_12"
        android:src="@drawable/white_close"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="@+id/etForm"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@+id/etForm"
        app:tint="@color/grey_shade5" />
</androidx.constraintlayout.widget.ConstraintLayout>

<androidx.appcompat.widget.AppCompatTextView
    android:id="@+id/tvMessage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/sdp_5"
    android:textColor="@color/colorError"
    android:textSize="@dimen/ssp_10"
    android:visibility="visible"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/clForm"
    tools:text="This field is required" />

</androidx.constraintlayout.widget.ConstraintLayout>

我在片段 A 中使用这个自定义 la,如下所示:

                <include
                    android:id="@+id/email"
                    layout="@layout/layout_form_edittext"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/sdp_36"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@+id/tvDescription" />

                <include
                    android:id="@+id/password"
                    layout="@layout/layout_form_edittext"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/sdp_12"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toBottomOf="@+id/email" />

我正在使用片段导航从片段 A 移动到片段 B。在电子邮件和密码中输入值并移动到片段 B,然后通过按返回或 navigateUp() 返回片段 A。电子邮件字段包含密码字段的值。

编辑:

它在 Custom Compound class 中使用的布局与以下问题相同。

class FormView @JvmOverloads
constructor(
private val ctx: Context,
private val attributeSet: AttributeSet? = null,
private val defStyleAttr: Int = 0
) : ConstraintLayout(ctx, attributeSet, defStyleAttr) {

private var formTitle = ""
private var passwordType = false
private var showMessage = false

init {
    val inflater = ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
    val attributes = ctx.obtainStyledAttributes(attributeSet, R.styleable.FormView)
    attributes.getString(R.styleable.FormView_formTitle)?.let { formTitle = it }
    passwordType = attributes.getBoolean(R.styleable.FormView_passwordType, passwordType)
    showMessage = attributes.getBoolean(R.styleable.FormView_showErrorMessage, false)
    attributes.recycle()

    inflater.inflate(R.layout.layout_form_edittext, this)

    setTitle(formTitle)
    setPasswordType(passwordType)
    errorMessageVisibility(showMessage)
    borderVisibility(false)


    ivSwitchPassword.setOnClickListener {
        updatePasswordVisibility()
    }

    ivCancel.setOnClickListener {
        etForm.text?.clear()
        clearError()
    }
}

fun showError(msg: String) {
    msg?.let {
        tvMessage.text = it
        cancelBtnVisibility(true)
        errorMessageVisibility(true)
        borderVisibility(true)
    }
}

fun clearError() {
    tvMessage.text = ""
    cancelBtnVisibility(false)
    errorMessageVisibility(false)
    borderVisibility(false)
}

private fun errorMessageVisibility(flag: Boolean) {
    if (flag) tvMessage.visible() else tvMessage.gone()
}

private fun cancelBtnVisibility(flag: Boolean) {
    if (flag) ivCancel.visible() else ivCancel.gone()
}

private fun borderVisibility(flag: Boolean) {
    val drawable = clForm.background as GradientDrawable
    if(flag) drawable.setStroke(1, Color.parseColor("#c32329"))
    else drawable.setStroke(0, Color.TRANSPARENT)
}

fun setPasswordType(passwordType: Boolean) {
    if(!passwordType) ivSwitchPassword.gone()
    else {
        ivSwitchPassword.visible()
        etForm.inputType = InputTypeUtils.getInputTypeByProperty("textPassword")
    }
}

fun setTitle(title: String) {
    tvFormTitle.text = title
}

private fun updatePasswordVisibility() {
    if (etForm.transformationMethod is PasswordTransformationMethod) {
        etForm.transformationMethod = null
    } else {
        etForm.transformationMethod = PasswordTransformationMethod()
    }
    etForm.setSelection(etForm.length())
}
}

这是因为 include edit text 对两个字段都有一个 id,解决方案是生成新的 id,在 onViewCreated 方法中添加此代码:

email.etForm.id = View.generateViewId()
password.etForm.id = View.generateViewId()