Android 弹出片段后,所有EditExt都将替换为相同的值
我有一个奇怪的问题,我有2个片段,在第一个片段中,我有一些自定义的Android 弹出片段后,所有EditExt都将替换为相同的值,android,android-fragments,fragment-backstack,Android,Android Fragments,Fragment Backstack,我有一个奇怪的问题,我有2个片段,在第一个片段中,我有一些自定义的EditText,还有一个按钮用第二个片段替换它(addToBackStack=true),然后在第二个片段中,我尝试使用popBackStack()返回到第一个片段,问题发生了,所有自定义EditText都具有相同的值 下面是我所有的代码 第一片段 第二片段 fragment_first.xml layout_custom_view.xml 任何响应都将不胜感激。您不是在添加后堆栈,而是在替换,尝试打开第二个片段,这将保持
EditText
,还有一个按钮用第二个片段替换它(addToBackStack
=true),然后在第二个片段中,我尝试使用popBackStack()
返回到第一个片段,问题发生了,所有自定义EditText
都具有相同的值
下面是我所有的代码
第一片段
第二片段
fragment_first.xml
layout_custom_view.xml
任何响应都将不胜感激。您不是在添加后堆栈,而是在替换,尝试打开第二个片段,这将保持第一个片段的完整状态并在堆栈中
btn_next.setOnClickListener {
val transaction = requireActivity().supportFragmentManager!!.beginTransaction()
.add(R.id.contentFrame, SecondFragment(), "")
commitTransaction(transaction, true, -1)
}
另外,您的两个
EditText
都有相同的idandroid:id=“@+id/edt”
,因此运行findViewById
的合成器函数将指向EditText的相同对象。我将尝试在布局中为每个自定义视图添加不同的id。比如:
com.sogia.replacefragmentdemo.CustomView
android:id="@+id/custom1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
com.sogia.replacefragmentdemo.CustomView
android:id="@+id/custom2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
拥有相同的id可能是一个问题,因为管理状态可能会变得混乱。
检查此项以获得解决方案:
最后我找到了根本原因和解决方案,
感谢@abhradeep ghosh、@Eselfar、@madscitector和其他回复此帖子的人
原因:视图ID应该是唯一的!否则,您的状态将被具有相同ID的另一个视图覆盖。在我的情况下,我有两个ID为@ID/edt
的视图,因此我的状态容器仅包含它的一个实例—以状态存储过程中最后出现的为准
这是我的解决方案,(来自)
首先,为保存视图状态创建新类
class SavedState(superState: Parcelable) : View.BaseSavedState(superState) {
var childrenStates: SparseArray<Any>? = null
override fun writeToParcel(out: Parcel, flags: Int) {
super.writeToParcel(out, flags)
childrenStates?.let {
out.writeSparseArray(it)
}
}
}
为什么您使用自定义的EditText(com.sogia.replacefragmentdemo.CustomView)而不是默认的EditText?@sebasira只是为了演示这个问题,在实际代码中,我使用了更多的视图如果您使用默认的EditText,您有相同的行为还是问题已经解决了?如果它消失了,那么问题可能在您的自定义视图中。如果错误仅出现在使用自定义视图时,您可以发布它吗?@sebasira是的,问题仅出现在我使用自定义视图时,但您可以看到我的CustomView
,它非常清楚,我看不到任何问题我也有类似的问题,请查看我已在“commitTransaction”行的后堆栈中添加片段的答案(交易,正确,-1)’,我也认为“kotlinx.android.synthetic”是根本原因,但正如您所看到的,我的代码很清楚,我将关注这一点,并在回来时告诉您结果我有这个问题的答案,很遗憾我不能接受您的答案,因为它没有解决方案,但是,嗯,非常感谢(+1)别担心,为了知识的缘故,请把你的答案发出来。谢谢。我发了:)请看下面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:id="@+id/btn_back"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="back"
/>
</LinearLayout>
class CustomView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
init {
inflate(context, R.layout.layout_custom_view, this)
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<EditText
android:id="@+id/edt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="input something"
/>
</LinearLayout>
btn_next.setOnClickListener {
val transaction = requireActivity().supportFragmentManager!!.beginTransaction()
.add(R.id.contentFrame, SecondFragment(), "")
commitTransaction(transaction, true, -1)
}
com.sogia.replacefragmentdemo.CustomView
android:id="@+id/custom1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
com.sogia.replacefragmentdemo.CustomView
android:id="@+id/custom2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
class SavedState(superState: Parcelable) : View.BaseSavedState(superState) {
var childrenStates: SparseArray<Any>? = null
override fun writeToParcel(out: Parcel, flags: Int) {
super.writeToParcel(out, flags)
childrenStates?.let {
out.writeSparseArray(it)
}
}
}
@Suppress("UNCHECKED_CAST")
public override fun onSaveInstanceState(): Parcelable? {
val superState = super.onSaveInstanceState()
val ss = SavedState(superState)
ss.childrenStates = SparseArray()
for (i in 0 until childCount) {
getChildAt(i).saveHierarchyState(ss.childrenStates as SparseArray<Parcelable>)
}
return ss
}
@Suppress("UNCHECKED_CAST")
public override fun onRestoreInstanceState(state: Parcelable) {
val ss = state as SavedState
super.onRestoreInstanceState(ss.superState)
for (i in 0 until childCount) {
getChildAt(i).restoreHierarchyState(ss.childrenStates as SparseArray<Parcelable>)
}
}
override fun dispatchSaveInstanceState(container: SparseArray<Parcelable>) {
dispatchFreezeSelfOnly(container)
}
override fun dispatchRestoreInstanceState(container: SparseArray<Parcelable>) {
dispatchThawSelfOnly(container)
}