1

In my android app where I am creating a tic tac toe game, I have this code below where if it's player one move then set their selection as X with a particular colour, else it must be player 2 so set text as O for their selection with a different colour.

@Override
public void onClick(View v) {
    if (!((Button) v).getText().toString().equals("")) {
        return;
    }

    if (playerOneMove) {
        ((Button) v).setText("X");
        ((Button) v).setTextColor(Color.parseColor("#e8e5e5"));
    } else {
        ((Button) v).setText("O");
        ((Button) v).setTextColor(Color.parseColor("#737374"));
    } 

    ...

}

I have a problem though and it is in regards to when I rotate the screen. When I rotate the screen, the text for X and O both change to the default text colour android studio provides. I want to keep the colours for these text but I am not sure how to do that? I have made sure there is no global text colour set.

Below is my code that handles orientation changes:

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBoolean("playerOneMove", playerOneMove);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    playerOneMove = savedInstanceState.getBoolean("playerOneMove");
}
Reaz Murshed
  • 23,691
  • 13
  • 78
  • 98
Merlin
  • 185
  • 2
  • 14
  • Try using a color from a color resource. Use an xml color file then set your color using `((Button) v).setTextColor(R.color.your_color)` – SystemGlitch Jun 03 '18 at 16:47
  • @SystemGlitch I've set the colours as you have said but still problem persists – Merlin Jun 03 '18 at 16:57

1 Answers1

2

You need to save the colours of each box of your tic tac toe board and retain them again on your layout configuration changes (i.e. device rotation).

You might consider looking into the answer here for a detailed explanation of your problem. You might check the developer documentation here for handling the configuration changes as well.

The key idea is to save the layout statues in variables which survives the configuration changes and update them accordingly in your onCreate or onCreateView function in case of Activity and Fragment respectively. However, in your case, you need to store a lot of data and on each configuration change, you need to restore them again which is not an efficient way to do that. I would like to recommend you look for other available options which survive the orientation or configuration changes of your layout.

I would strongly suggest implementing ViewModel in your case, which survives the application configuration change and handles the overall UI representation in the most effective way. The idea is to bind your UI elements with your ViewModel and then retain the UI elements each time from your ViewModel. It can be retained at the exact state until the Activity or Fragment finishes.

In your case, I would like to provide an example of how you can prepare a ViewModel. Let us consider your ViewModel is GameModel which saves the layout items of your board.

public class GameModel extends ViewModel {
     public final LiveData<Game> gameLiveData = new LiveData<>();

     public GameModel() {
         // trigger game load.
     }

     void doAction() {
         // depending on the action, do necessary business logic calls and update the gameLiveData.
     }
}

public class Game {
    public static final int CROSS = 1; 
    public static final int ZERO = 0;

    public int pos1 = -1; // Default values are -1, when the position is yet to be played
    public int pos2 = -1;
    public int pos3 = -1;
    public int pos4 = -1;
    public int pos5 = -1;
    public int pos6 = -1;
    public int pos7 = -1;
    public int pos8 = -1;
    public int pos9 = -1;
}

Now from your Activity, you need to add an observer to your GameModel class to update the UI accordingly.

public class UserActivity extends Activity {

     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.game_activity_layout);
         final GameModel viewModel = ViewModelProviders.of(this).get(GameModel.class);
         viewModel.gameLiveData.observer(this, new Observer() {
            @Override
             public void onChanged(@Nullable Game gameData) {
                 // update ui.
             }
         });
         findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                  // Pass parameters in doAction function to set the items in the Game class and update the ui accordingly inside the onChanged function.
                  viewModel.doAction(); 
             }
         });
     }
}

Hope that helps!

Reaz Murshed
  • 23,691
  • 13
  • 78
  • 98
  • Cool I will keep that for note for my next app I build. As for a quick fix on keeping the colours what will I need to add in my code? Thanks for the answer – Merlin Jun 03 '18 at 17:01
  • Is there a way I can call on my buttons to place in my save instance and restore instance? – Merlin Jun 03 '18 at 17:02
  • As referenced in my answer, you might check this [link here](https://stackoverflow.com/a/39097782/3145960) on how you are going to save the data along with instance state. Hope that helps! – Reaz Murshed Jun 03 '18 at 17:03
  • What I should have said is how can I call on the buttons in the saved instance, thats the part I am struggling on. I want to store the x and o already selected in my onsaveinstance and onrestore but not sure how to call on it? – Merlin Jun 03 '18 at 17:06
  • I would suggest you have a `Game` class saving the actions performed on your tic-tac-toe board. Based on that you will re-instantiate the board. – Reaz Murshed Jun 03 '18 at 17:13
  • And I would suggest strongly on keeping an observer using `ViewModel`. Believe me, this is not too much work for now. It will save time in future. – Reaz Murshed Jun 03 '18 at 17:15
  • 1
    Cool Reaz, I will do that then, Thank you very much :) – Merlin Jun 03 '18 at 17:19