androidkotlinandroid-fragmentsandroid-edittextfragment-oncreateview

Android - Restore Programmatically Created Views


I am currently designing an app that helps you manage recipes. When you create a recipe, a series of EditText views are created programmatically when you click an 'add' button. You can make as many steps/EditText lines as you want, so it is not a constant number. When you click 'Create Recipe' I iterate through step by step and add the EditText views to a mutable list called 'stepsList'. I do text parsing to pick out the ingredients and amounts for each step and you are taken to a confirmation screen before the recipe is finalized. When you go back, I am trying to restore all the steps with the text that was entered before. Programmatically created views are not automatically restored, you have to reconstruct them. Here is my onCreateView() function that does the restoration:

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    // Firebase
    auth = Firebase.auth
    db = Firebase.firestore

    utils = Utils(activity as MainActivity)

    // Inflate the layout for this fragment
    val view = inflater.inflate(R.layout.fragment_recipe_setup, container, false)

    // Loop through the list of EditText views
    for (i in 0 until stepsList.size) {
        //println((stepsList[i] as EditText).text)
        if (stepsList[i] is EditText) {
            val stepListEditText = stepsList[i] as EditText

            // Add the EditText view to the fragment's layout
            val stepFieldLayout = inflater.inflate(R.layout.step, container, false)
            val stepsContainer = view.findViewById<LinearLayout>(R.id.recipe_steps_container)
            val stepEditText = stepFieldLayout.findViewById<EditText>(R.id.step_field)
            stepEditText.text = (stepsList[i] as EditText).text
            stepsContainer.addView(stepFieldLayout, i)
            println(stepEditText.text)

        }
    }
    // Inflate the layout for this fragment
    return view
}

From here, I get some strange behavior. The correct number of EditText views are restored, but whatever text was in the last EditText originally is the text for all the restored EditText views. For example, if I originally had 3 steps with the text '1', '2', '3', respectively, when they are restored, all of the will have '3'. What is even more strange, the println(stepEditText.text) prints the correct text, but when I look at the app, the text is wrong. Anyone have any ideas? I'd even take answers in java since it is so similar to kotlin


Solution

  • This is because they all share the same id. The easy way to fix it is to assign all the edit texts random ids, but this will occasionally cause an error. The safest way to fix it is to override onSaveInstanceState and onRestoreInstanceState and to do the serialization yourself.