Все Editexts должны быть заменены на одно и то же значение после добавления фрагмента - PullRequest
0 голосов
/ 11 сентября 2018

У меня странная проблема, у меня есть 2 фрагмента, в первом фрагменте у меня есть несколько пользовательских EditText, и кнопка, чтобы заменить это вторым фрагментом (addToBackStack = true), затем во втором фрагменте я попробуйте использовать popBackStack() для возврата к первому фрагменту, проблема возникает, все пользовательские EditText имеют одинаковое значение.

error

Ниже весь мой код

FirstFragment

class FirstFragment : BaseFragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_first, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        btn_next.setOnClickListener {
            val transaction = requireActivity().supportFragmentManager!!.beginTransaction()
                .replace(R.id.contentFrame, SecondFragment(), "")
            commitTransaction(transaction, true, -1)
        }
    }
}

SecondFragment

class SecondFragment : BaseFragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_second, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        btn_back.setOnClickListener {
            requireActivity().supportFragmentManager.popBackStack()
        }
    }
}

fragment_first.xml

<?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"
    android:orientation="vertical"
    >
    <com.sogia.replacefragmentdemo.CustomView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

    <com.sogia.replacefragmentdemo.CustomView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
    <Button
        android:id="@+id/btn_next"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="next"
        />
</LinearLayout>

fragment_second.xml

<?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>

CustomView

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)
    }
}

layout_custom_view.xml

<?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>

Любой ответ приветствуется.

Ответы [ 4 ]

0 голосов
/ 17 сентября 2018

Наконец, я выясняю причину и решение, спасибо @abhradeep ghosh, @Eselfar, @MadScientist и еще одному человеку, который ответит на этот пост.

Причина: идентификаторы представлений должны быть уникальными!В противном случае ваше состояние будет перезаписано другим представлением с тем же идентификатором.В моем случае у меня есть 2 представления с идентификатором @id/edt, поэтому в моем контейнере состояний хранится только 1 его экземпляр - в зависимости от того, что наступит последним в процессе сохранения состояния.

Вот мое решение (из этого поста ),

Сначала создайте новый класс для сохранения состояния просмотра

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)
        }
    }
}

И вмой CustomView

@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)
    }
0 голосов
/ 14 сентября 2018

Я бы попробовал добавить разные идентификаторы для каждого из ваших пользовательских представлений в макете.Нравится:

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"
    />
0 голосов
/ 16 сентября 2018

Наличие одного и того же идентификатора может быть проблемой, так как управление состоянием может стать беспорядочным.Проверьте это для решения: Восстановить фрагмент с двумя представлениями, имеющими одинаковый идентификатор

0 голосов
/ 13 сентября 2018

Вы не добавляете в задний стек, вы заменяете, попробуйте это, чтобы открыть второй фрагмент, это сохранит состояние FirstFragment в целости и сохранности в стеке

btn_next.setOnClickListener {
            val transaction = requireActivity().supportFragmentManager!!.beginTransaction()
                .add(R.id.contentFrame, SecondFragment(), "")
            commitTransaction(transaction, true, -1)
        }

Также оба ваших EditText имеют одинаковые идентификаторы android:id="@+id/edt", поэтому функция синтезатора, которая запускает findViewById, будет указывать на один и тот же объект EditText

...