Android - Is there a way to clear all Buttons from a Layout and reinsert them according to a State Class? (State Design Pattern)

StackOverflow https://stackoverflow.com/questions/19057071

Pregunta

Greetings Stackoverflowians

I'm working on an Android Card Game App. I've got the whole game's dynamic into a GameClass that I implemented using a State Design Pattern (State Machine), considering either of the two Players at a certain State of the game will have different actions available.

For example, when the game starts, Player A can only execute 5 out of the total 21 methods that the GameClass has. According to what actions and Cards are played the methods will transition the different States and in every different State, different methods will be available.

So, I've solved the availability of the different methods with a Class called CurrentActions which sets and gets booleans for each method. So, if I want to show the Player the actions he can choose upon beginning with the game, I have a series of IF's (about 21...) checking to see if any of the Getters are set to true, if they are I add the Button to the Layout and everything works like a charm.

Now, my biggest problem is that I can't figure out how to show the first State's Buttons and then once Player A clicks on one of those Buttons(Methods), flush out all the buttons that were available in the previous State and now show the new Buttons for the new State that the game is at.

Is there any way to do this? I already use the Layout.removeAllViews() method to clear all the buttons, but the setting up all of them again according to the following State is my biggest problem. I'd really appreciate any sort of guidance on this matter.

In response to your requests to see some code, I've added the code that is in my Activity which handles the Game, Layouts, Buttons and Possible Actions:

// CurrentActions CA holds the current actions that are available 
//for the current State of the game.
final CurrentActions CA = new CurrentActions();

//JuegoTruco JT is the game itself

    final JuegoTruco JT = new JuegoTruco(CA);

//I've changed the names up to make it understandable
//If Action1 is performable at the current State of the game, set the button up and
//await a posible Click 
    if(CA.performAction1())
    {
        Action1Button = new Button(this);
        Action1Button.setId(13);
        Action1Button.setLayoutParams(paramsActions);
        Action1Button.setText("Action1");
        layoutAcciones.addView(Action1Button);
        Action1Button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (TOGGLE_ON_CLICK) {
                    mpButton.start();

//Here I change the state of JT, by performing an action and 
//I also give it instance CA, so the State Handler
//can change the available Actions for the following state

                    JT.performAction(otherParameters, CA);
                    layoutActions.removeAllViews();

                }
            }
        });
    }
if(CA.performAction2())
    {
        Action2Button = new Button(this);
        Action2Button.setId(13);
        Action2Button.setLayoutParams(paramsActions);
        Action2Button.setText("Action2");
        layoutAcciones.addView(Action2Buttonn);
        Action2Button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (TOGGLE_ON_CLICK) {
                    mpButton.start();
                    JT.performAction2(OtherParameters, CA);
                    layoutActions.removeAllViews();

                }
            }
        });
    }

I will have one of these IFs for every single action existent in the Game. So....after I click on one of the available Buttons (according to the State of the game), is there a way to clear the actionsLayout and do a fresh set of the Buttons and continuously do this after every single button press (ie: every single change of State)?

¿Fue útil?

Solución

I think the most simple approach would be to let the Activity determine the state in onCreate() and create the valid Buttons accordingly (sounds like that is just about what you are doing).

Now, instead of manipulating the existing view (which can be a pain as complexity grows) simply restart the Activity, recreating the game with the same code as before.

// Move to new state
startActivity(new Intent(MainActivity.this, MainActivity.class));

This could cause some problems if the user would press the back button, although moving back would still show a correct state, it would be confusing behaviour. Atleast that is my opinion. To prevent this:

@Override
public void onBackPressed() {
    // confirm exit being a dialog, this just mocks the intent of the code
    if (confirmExit()) {
          Intent startMain = new Intent(Intent.ACTION_MAIN);
            startMain.addCategory(Intent.CATEGORY_HOME);
            startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(startMain);
    }
}

Eyecandy: You can define the transition between your activites to make it look a bit cooler.

Example with left to right transition in onCreate() of your MainActivity:

overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);

And here is the /res/anim/slide_in_right.xml and anim.slide_out_left.xml:

/// in_right
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false" >

<translate
    android:duration="200"
    android:fromXDelta="100%"
    android:fromYDelta="0%"
    android:toXDelta="0%"
    android:toYDelta="0%" />

</set>

// out_left
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false" >

<translate
    android:duration="200"
    android:fromXDelta="0%"
    android:fromYDelta="0%"
    android:toXDelta="-100%"
    android:toYDelta="0%" />

</set>

There are of course many answers to this question. I though honestly think this is the easiest to program, read and maintain, that I can think of.

Fragments: This approach could later be improved with fragments. This would give the same improvement to your app as Ajax does to server-based website (That is the most fitting anology in my mind). This is however outside the scope of this post to digg into. Just wanted to mention it.

As a final note, then my suggestion to the solution will be very much less painful to migrate to fragment based in the future than fiddling around adding/removing views from the activity would be.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top