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;
}