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()
我有一个 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()