1
\$\begingroup\$

Say I have 4 buttons. I want to have button 2 always swap out with another button, randomly. So, when the user taps button 2, it should swap with another button (randomly).

Now, button 2 is at the bottom right corner. So if the user taps button 2 again, it has the option to swap with the other three buttons. How can I achieve this?

I have already tried to make an array of the four values:

top_right, top_left, bottom_right, bottom_left

And have successfully had them swap, but it was very memory inefficient, and took a while.

\$\endgroup\$
1
\$\begingroup\$

I created a working demo using android's built-in buttons.

This is the main Activity class. Each button have the same onClick method buttonClicked().

List<View> buttons = new ArrayList<View>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Store the button to the buttons array for later.
    buttons.add(findViewById(R.id.button));
    buttons.add(findViewById(R.id.button2));
    buttons.add(findViewById(R.id.button3));
    buttons.add(findViewById(R.id.button4));
}


public void buttonClicked(View v) {
    // Remove the clicked button from it's frame layout parent.
    ViewManager p = (ViewManager) v.getParent();
    p.removeView(v);

    // Find another button randomly.
    Random rng = new Random();
    View v2;
    do {
        int i = rng.nextInt(4);
        v2 = buttons.get(i);
    } while (v2 == v); // Loop until you get a different button to swap with.

    // Remove the other button from it's frame layout parent.
    ViewManager p2 = (ViewManager) v2.getParent();
    p2.removeView(v2);

    // Now simply insert each button into the other buttons frame layout.
    p.addView(v2, v2.getLayoutParams());
    p2.addView(v, v.getLayoutParams());
}

This is how the layout looks like. I have each button in a separate frame layout which stay where they are with the buttons inside swapping which frame container they are inside.

enter image description here

If anything is unclear just ask.

\$\endgroup\$
  • \$\begingroup\$ Also, in this line : while (v2 == v); when wil v2 == v? \$\endgroup\$ – Ruchir Baronia Nov 26 '15 at 19:45
  • \$\begingroup\$ I'm also a bit confused on how to put each frame layout into the gridLayout. Could you post the xml? Thanks. For me, when I try to put the frame layout in, there are many tiny grids to put it into. I have never worked with grid and frame layout, so I would really appreciate it if you also posted your xml. Again, I can't thank you enough! \$\endgroup\$ – Ruchir Baronia Nov 26 '15 at 19:51
  • \$\begingroup\$ @RuchirBaronia nextInt(4) returns an int between 0-3. So it returns a number from 0 and up to but not including the number you passed in. Notice that buttons have all 4 buttons in it, so the indices goes from 0-3. This also means that when you pick a random button to swap with it might pick the one you clicked, and I guess you don't want the button to swap position with itself. So the v2 == v is needed to make sure it loops if this happens. \$\endgroup\$ – Christer Nov 26 '15 at 20:33
  • \$\begingroup\$ Ohhhh that makes so much more sense. Thanks! Do you mind posting the layout xml also? For some reason, when I try to put the frame layout in, the grid layout expands out of being 2x2. I don't know why...' \$\endgroup\$ – Ruchir Baronia Nov 26 '15 at 20:35
  • \$\begingroup\$ @RuchirBaronia Yeah, if you use grid layout can be a pain because the cells start out so small, at least for me. Here is the XML file you see on the image. gist.github.com/61f63e23f313b0d29a72 \$\endgroup\$ – Christer Nov 26 '15 at 20:40
0
\$\begingroup\$

If you want to use the solution you describe in your question, you can achieve it pretty easily with an ArrayList. This is assuming you have some sort of class for your buttons. If not, it might be a bit more cumbersome. The logic's the same though.

Create the initial list at the start of your class with the buttons:

ArrayList<Button> buttons = new ArrayList<Button>();
buttons.add(new Button("button1", xPos, yPos));
buttons.add(new Button("button2", xPos, yPos));
buttons.add(new Button("button3", xPos, yPos));
buttons.add(new Button("button4", xPos, yPos));

Then whenever the user clicks on one of them, run this:

// Make this equal the button the user clicks!
Button userSelection = GetClickedButton();

// Remove that button from the array.
buttons.remove(userSelection);

// Select a random button from the remaining ones.
Button toSwap = buttons.get(new Random().nextInt(buttons.size())));                     

// Now swap. Just swap the positions of the chosen buttons.
SwapButtonPositions(userSelection, toSwap);

// Add the removed button back to the list. 
buttons.add(userSelection); 

EDIT: I misread your question. I thought you wanted any button to be swappable, not just one of them. The logic for doing that is the same as above. Just have some way to tag the swappable button (like giving it a name) and run the code whenever it's clicked, rather than when any button's clicked.

\$\endgroup\$
  • \$\begingroup\$ Great answer! Are xPos and yPos in DP or pixels? \$\endgroup\$ – Ruchir Baronia Nov 26 '15 at 2:35
  • \$\begingroup\$ I had pixels in mind, to be honest. I forgot android uses DP. It doesn't really matter though. Just replace it with whatever co-ordinate system you're using :D \$\endgroup\$ – KevLoughrey Nov 26 '15 at 2:39
  • \$\begingroup\$ buttons.add(new Button("button1", 66, 177)); \$\endgroup\$ – Ruchir Baronia Nov 26 '15 at 2:42
  • \$\begingroup\$ Would that work as a possible button object creation? It is giving me some errors \$\endgroup\$ – Ruchir Baronia Nov 26 '15 at 2:43
  • \$\begingroup\$ That should work to create a button, assuming your button class is setup to take those parameters. Unless you're using a built in button class? \$\endgroup\$ – KevLoughrey Nov 26 '15 at 2:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.