Reputation: 313
I'm trying to create an Activity that contains 10 buttons that are generated programmatically and are positioned in random places on the screen but without exceed the screen size.
I tried doing so but most of the buttons exceeded from the screen size (I couldn't see it).
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.linear);
Random rnd = new Random();
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int height = displaymetrics.heightPixels;
int width = displaymetrics.widthPixels;
for(int x = 0;x<10;x++) {
Button btn = new Button(this);
int Xpoistion = rnd.nextInt(width - 100) + 100;
int Yposition = rnd.nextInt(height - 100) + 100;
btn.setX(Xpoistion);
btn.setY(Yposition);
btn.setText(x +")"+width + "," + height + " | " + Xpoistion + "," + Yposition);
linearLayout.addView(btn);
}
So i'm trying to create the "limits of the screen" from height and width but for some reason I can't figure it out.
I played with Xposition and Yposition a lot but nothing seems to work for me.
Thank for very much for your help.
Upvotes: 3
Views: 137
Reputation: 1799
You should use the RelativeLayout
as said already. But your logic is a bit flawed, you should set variables to garantee your buttons don't go of screen. I added a bit of code to yours already
int height = displaymetrics.heightPixels;
int width = displaymetrics.widthPixels;
int buttonWidth = 150;
int buttonHeigh = 40;
int max_x_val = width - buttonWidth;
int max_y_val = heigth - buttonHeigh; // Edited here
for(int x = 0;x<10;x++) {
Button btn = new Button(this);
int Xpoistion = rnd.nextInt(max_x_val - buttonWidth) + buttonWidth;
int Yposition = rnd.nextInt(max_y_val - buttonHeigh) + buttonHeigh;
btn.setX(Xpoistion);
btn.setY(Yposition);
btn.setWidth(buttonWidth);
btn.setHeight(buttonHeigh);
btn.setText(x +")"+width + "," + height + " | " + Xpoistion + "," + Yposition);
relativeLayout.addView(btn);
Log.d("Debug","Xpos =" + Xpoistion);
Log.d("Debug","Ypos =" + Yposition);
}
This still is not the solution because the buttons might end up overlapped
Last edit
There are still some buttons that get a bit cut.This happens because we have the whole dimensions of the screen, and what we needed was the dimensions of only our Relative Layout
.. That blue bar on top is also being included in the measure when it shouldn't. But this error is a bit more tricky to fix but not impossible, just google a bit and you will find enough help
EDIT: My initial thought was that btn.setX()
and setY()
would center the Button
on those pixels, but no it marks the start of the button in those same pixels, so I had to change the randomize function to simply:
int Xposition = rnd.nextInt(width - buttonWidth);
int Yposition = rnd.nextInt(height - buttonHeight);
Next, to work around overlapping I wrote the following sample
// Create dummy class for holding coordinates
public class ButtonCordinates{
public int x;
public int y;
public ButtonCordinates(int x, int y) {
this.x = x;
this.y = y;
}
}
//In MainActivity class create a array for holding coordinates
ButtonCoordinates [] buttonsCoordinates = new ButtonCoordinates [10];
int x = 0;
while(x < 10) {
int Xposition = rnd.nextInt(width - buttonWidth);
int Yposition = rnd.nextInt(height - buttonHeight);
ButtonCoordinates buttonCoords = new ButtonCoordinates (Xposition,Yposition);
if(!coordinatesFree(buttonCoords,buttonHeight,buttonWidth)){
// Get another chance
continue;
}
Button btn = new Button(this);
btn.setX(Xposition);
btn.setY(Yposition);
btn.setWidth(buttonWidth);
btn.setHeight(buttonHeight);
btn.setText(Xposition+";"+Yposition);
buttonsCoordinatesArray[x++] = buttonCoords;
linearLayout.addView(btn);
Log.d("Debug","Xpos =" + Xposition);
Log.d("Debug","Ypos =" + Yposition);
}
// Method that prevents overlapping
private boolean coordinatesFree(ButtonCoordinates newButton, int buttonHeight, int buttonWidth){
for(ButtonCoordinates existingButton : buttonsCoordinatesArray){
if(existingButton == null){
// First button ever
return true;
}
boolean f1 = existingButton.x + buttonWidth <= newButton.x;
boolean f2 = existingButton.y + buttonHeight <= newButton.y;
boolean f3 = existingButton.x - buttonWidth >= newButton.x;
boolean f4 = existingButton.y - buttonHeight >= newButton.y;
if(!f1 && !f2 && !f3 && !f4){
return false;
}
}
return true;
}
Upvotes: 1