Save state of Activity that contains Buttons when you press back button android

144 Views Asked by At

I have an activity where the user can choose how many button should be created. If the user types 5 in an EditText that is in an AlertDialog Builder, 5 buttons are created programmatically. If I go back, the created Buttons are gone. How can I save the 5 buttons in the Activity?

This is my code that creates Buttons dynamically:

AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("How many Buttons?");
final EditText input = new EditText(this);
input.setInputType(InputType.TYPE_CLASS_NUMBER);
input.setRawInputType(Configuration.KEYBOARD_12KEY);

alert.setView(input);
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
   public void onClick(DialogInterface dialog, int whichButton) {
      String persons = input.getText().toString();
      try {
         personsnumber = Integer.parseInt(persons);
      } catch (NumberFormatException nfe) {}
      Button[] buttons = new Button[personsnumber];
      for (int l = 0; l < personsnumber; l++) {
         buttons[l] = new Button(HandleTableClick.this);
         buttons[l].setTextSize(20);
         buttons[l].setLayoutParams(lp);
         buttons[l].setId(l);
         buttons[l].setText("Person" + (l + 1) + "bblabla");

         // myLayout.addView(pairs[l]);
         myLayout.addView(buttons[l]);
      }
   }
});
alert.show();

I know that I have to override the OnBackPress Method but I don't know what code I should use to save the state.

1

There are 1 best solutions below

9
On

You will save your buttons states using the default way which is implementing onSaveInstanceState().

You will create a class that will save the state of your buttons. That class would implement Parcelable, in order to pass it as an ArrayList<Parcelable> to the Bundle parameter in onSaveInstanceState().

Here is the source of this answer.

Edit:

I believe this is the main idea behind the implementation, it's simple, yet I am missing something about the button creation and the buttons are weirdly created after rotating. By weirdly I mean that the background was not the default and the font is larger which it should not be because I am setting the same size (am I, right?).

To prove that some state is kept you can see it from the text of the button and also from the background color if you press the button.

The main activity:

public class MainActivity extends AppCompatActivity {

    private static final String EXTRA_BUTTONS = "extra button list";
    private static final int BUTTONS_COUNT = 5;
    private ArrayList<Button> createdButtons = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        LinearLayout root = findViewById(R.id.root);

        if (savedInstanceState == null) {
            createButtonsForTheFirstTime(root);
        } else {
            createButtonsFromState(savedInstanceState, root);
        }

    }


    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        ArrayList<ButtonViewState> states = new ArrayList<>();
        for (int i = 0; i < BUTTONS_COUNT; i++) {
            states.add(ButtonViewState.create(createdButtons.get(i)));
        }
        outState.putParcelableArrayList(EXTRA_BUTTONS, states);
    }

    private void createButtonsForTheFirstTime(LinearLayout root) {
        for (int i = 0; i < BUTTONS_COUNT; i++) {
            Button button = createButton(i);
            // Save the button so we can retrieve them when we want to save their state
            createdButtons.add(button);
            // I added the listener which changes the color onClick to prove that state remains
            button.setOnClickListener((view) -> view.setBackgroundColor(Color.GREEN));
            root.addView(button);
        }
    }

    private void createButtonsFromState(Bundle savedInstanceState, LinearLayout root) {
        ArrayList<ButtonViewState> states = savedInstanceState.getParcelableArrayList(EXTRA_BUTTONS);
        for (ButtonViewState state : states) {
            Button button = createButtonFrom(state);
            button.setOnClickListener((view) -> view.setBackgroundColor(Color.GREEN));
            root.addView(button);
            createdButtons.add(button);
        }
    }

    @NonNull
    private Button createButton(int id) {
        Button button = new Button(this);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        button.setLayoutParams(params);
        button.setText("Button " + id);
        button.setId(id);
        button.setTextSize(TypedValue.COMPLEX_UNIT_SP, 25);
        return button;
    }

    private Button createButtonFrom(ButtonViewState state) {
        Button button = new Button(this);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT);
        button.setLayoutParams(params);
        button.setTextSize(TypedValue.COMPLEX_UNIT_SP,state.textSize);
        button.setText(state.text);
        button.setBackgroundColor(state.backgroundColor);
        return button;
    }

    static class ButtonViewState implements Parcelable {

        String text;
        int width, height, id;
        float textSize;
        int backgroundColor;

        private ButtonViewState(Button button) {
            text = button.getText().toString();
            width = button.getLayoutParams().width;
            height = button.getLayoutParams().height;
            textSize = button.getTextSize();
            id = button.getId();
            initializeBackgroundColor(button);
        }

        protected ButtonViewState(Parcel in) {
            text = in.readString();
            width = in.readInt();
            height = in.readInt();
            id = in.readInt();
            textSize = in.readFloat();
            backgroundColor = in.readInt();
        }

        public static final Creator<ButtonViewState> CREATOR = new Creator<ButtonViewState>() {
            @Override
            public ButtonViewState createFromParcel(Parcel in) {
                return new ButtonViewState(in);
            }

            @Override
            public ButtonViewState[] newArray(int size) {
                return new ButtonViewState[size];
            }
        };

        private void initializeBackgroundColor(Button button) {
            try {
                ColorDrawable drawable = (ColorDrawable) button.getBackground();
                backgroundColor = drawable.getColor();
            } catch (ClassCastException e) {
                Log.e("MainActivity", "Background of button is not a color");
            }
        }

        static ButtonViewState create(Button button) {
            return new ButtonViewState(button);
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel parcel, int i) {
            parcel.writeString(text);
            parcel.writeInt(width);
            parcel.writeInt(height);
            parcel.writeInt(id);
            parcel.writeFloat(textSize);
            parcel.writeInt(backgroundColor);
        }
    }

}

The layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:textSize="32sp" />


</LinearLayout>

The weird part:

When activity is first created

When activity is first created

Click a button

enter image description here

After rotatation (some state is preserve, text, color, someone could help here)

enter image description here