Regenarate location if (X,Y) already contains ImageView there - android

I have an ImageViewArray and I am randomizing their locations, I want to check if the current location already contains an ImageView without keeping a lot of values of x,y for every ImageView in the array.
Here is my code:
ImageView[] imageViewArray = new ImageView[40];
for (int i = 0; i < 40; i++) {
imageViewArray[i] = new ImageView(this);
imageViewArray[i].setTag(i);
imageViewArray[i].setImageResource(R.mipmap.enemy);
rlt.addView(imageViewArray[i]);
imageViewArray[i].setX(rand.nextInt(rlt.getWidth()));
imageViewArray[i].setY(rand.nextInt(rlt.getHeight()));
if(imageViewArray[i].getX()=) // here I want to check if it already contains an ImageView.
}
Possible Solution
Creating IntArray and adding X value to it and also every Y value for it, then compare between them, is it the best solution?
Problem with the solution - nothing happens, the imageview doesn't change the place and the Toast is not executed.
code:
ImageView[] imageViewArray = new ImageView[20];
ArrayList<Float> xarray = new ArrayList<>();
ArrayList<Float> yarray = new ArrayList<>();
for (int i = 0; i < 20; i++) {
imageViewArray[i] = new ImageView(this);
imageViewArray[i].setTag(i);
imageViewArray[i].setImageResource(R.mipmap.enemy);
imageViewArray[i].setX((float)rand.nextInt(1 + layoutwidth));
imageViewArray[i].setY((float)rand.nextInt(1 + layoutheight));
xarray.add(imageViewArray[i].getX());
yarray.add(imageViewArray[i].getY());
rlt.addView(imageViewArray[i]);
Toast.makeText(MainActivity.this,imageViewArray[i].getX() +"blabla",Toast.LENGTH_LONG);
}
EDIT
layoutwidth is zero :
private int layoutwidth, layoutheight, randx, randy;
private RelativeLayout rlt;
....
rlt = (RelativeLayout) findViewById(R.id.layout);
rlt.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
rlt.getViewTreeObserver().removeOnGlobalLayoutListener(this);
layoutwidth = rlt.getWidth();
layoutheight = rlt.getHeight();
}
});

Yes, that is the best solution. You need to load the rectangles from somewhere. You might merge rectangles if one contains the other, but then you would over-complicate your task and in your quest of writing a more performant and a clearer code, you would end up with a slow and complicated code. Write your code with storing pairs of X, Y points where X is the let-top corner position and Y is the right-bottom corner position.
Note, that I have assumed that the pictures are not rotated. If the images might be rotated, then you need a more general solution, using the inequalities defining the rectangles to see where a point set of a rectangle intersects the point set of the other rectangle. If the intersection is empty set, then the "space is not used up".

Related

Android - How to get a view's x and y coordinates into a gridLayout?

the actual wondering is the following : I have a full-screen GridLayout which has half of it visible. To see the second part we have to scroll.
I tried some ways and looked around for answers but none of whichs I found gave me what I need. In my grid there are square cells and each one contains a view, and I need to get the x and the y of these views.
Problem is that I could get the coordinates of the views that were put into the visible cells, the views that are not displayed have a x and a y set to 0... Whereas they were drawn..
Here it is, hope some of you guys could help! :)
private void createGrid(){
//I call the function several times
int gridsLength = 19*48*grids;
for(int i = 0; i < 19; i++) {
for (int j = 0; j < 48; j++) {
GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams();
layoutParams.width = 40;
layoutParams.height = 40;
View view = new View(this);
view.setLayoutParams(layoutParams);
Util.setDrawableBackground(view, R.drawable.border_black, this);
view.setOnTouchListener(newViewListener());
gridViews.add(view);
//glMain is my gridLayout that i put into global variable
glMain.addView(view, i + j + gridsLength);
}
}
grids++;
}
EDIT : I finally found out that I was not always accessing the views AFTER the grid were drawn so I changed that and it's working... Figured out that I was just a fool ^^

How to change the color of programmatically added buttons?

I recently started making a chess-like game for android. The first thing I needed was to make the 8 by 8 board. I figured adding 64 buttons and organizing them in the XML wouldn't be much efficient, so I found a way to create them programmatically using a simple 8x8 matrix of buttons. Until this point, everything worked as intended, and I had this:
The next thing I tried was to change the colors of the buttons to match a chessboard. On the internet I found some ways of doing it, but pretty much all of them just made my buttons invisible, and did not change their color.
Here's the onCreate method (the only thing I modified so far):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_menu);
//GETTING SCREEN DIMENSIONS
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
//SETTING THE BOARD
int TILESIZE = width/8;
LinearLayout back = (LinearLayout) findViewById(R.id.back);
LinearLayout[] rows = new LinearLayout[8];
Button[][] tiles = new Button[8][8];
for(int i = 0; i < 8; i++){
rows[i] = new LinearLayout(this);
back.addView(rows[i]);
for(int j = 0; j < 8; j++){
tiles[i][j] = new Button(this);
tiles[i][j].setWidth(TILESIZE);
tiles[i][j].setHeight(tiles[i][j].getWidth());
if((i + j) % 2 == 0){
tiles[i][j].setBackgroundColor(0xFFFFFFFF);
tiles[i][j].invalidate();
}
else{
//TODO: Make tiles black
}
rows[i].addView(tiles[i][j]);
}
}
}
The XML file contains a single vertical linear layout called back.
My question is how can I make the buttons change color, and where am I doing something wrong. I would also gladly accept alternative (or better) ways to make the board.
Change your loop like this and try
for(int i = 0; i < 8; i++){
rows[i] = new LinearLayout(this);
for(int j = 0; j < 8; j++){
tiles[i][j] = new Button(this);
tiles[i][j].setWidth(TILESIZE);
tiles[i][j].setHeight(tiles[i][j].getWidth());
if((i + j) % 2 == 0){
tiles[i][j].setBackgroundColor(0xFFFFFFFF);
tiles[i][j].invalidate();
}
else{
//TODO: Make tiles black
}
rows[i].addView(tiles[i][j]);
}
back.addView(rows[i]);
}
Change your if loop like this:
if((i + j) % 2 == 0)
tiles[i][j].setBackgroundColor(android.R.color.holo_blue_dark);
else
tiles[i][j].setBackgroundColor(android.R.color.holo_red_dark);
You can define black and white colors in your color.xml file and add them instead using tiles[i][j].setBackgroundColor(getResources().getColor(R.color.white)); and similarly for black.
But make sure, you use a different background so they are clearly visible.

TableRow rescales after all elements of row are clicked

I am creating a Table of buttons, to control a LED Matrix via Bluetooth.
I have found on the web Brian's Video Tutorials and followed his Dynamic Buttons and Images video to implement this.
Here is the code:
public class DrawerMode extends Activity {
private static final int NUMOFCOL = 15;
private static final int NUMOFROW = 8;
Button buttons[][] = new Button[NUMOFROW][NUMOFCOL];
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Assign content
setContentView(R.layout.activity_draw_mod);
fillTable();
}
private void fillTable() {
TableLayout tableLayout = (TableLayout) findViewById(R.id.drawer_table);
for( int iter_R = 0; iter_R!= NUMOFROW; iter_R++){
TableRow tableRow = new TableRow(this);
tableRow.setLayoutParams(new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT,TableLayout.LayoutParams.WRAP_CONTENT,1.0f));
tableLayout.addView(tableRow);
for(int iter_C = 0; iter_C != NUMOFCOL; iter_C++){
final int FINAL_COL = iter_C;
final int FINAL_ROW = iter_R;
Button button = new Button(this);
button.setLayoutParams(new TableRow.LayoutParams( TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.MATCH_PARENT, 1.0f));
button.setText("" + iter_C + "," + iter_R);
button.setPadding(0, 0, 0, 0);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
whenBtnClicked(FINAL_COL, FINAL_ROW);
}
});
tableRow.addView(button);
buttons[iter_R][iter_C] = button;
}
}
}
private void whenBtnClicked(int col, int row) {
//Toast.makeText(this, "Button clicked: " + FINAL_COL + "," + FINAL_ROW, Toast.LENGTH_SHORT).show();
Button button = buttons[row][col];
// Lock Button Sizes:
lockButtonSizes();
int newWidth = button.getWidth();
int newHeight = button.getHeight();
Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_dark_blue);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(originalBitmap, newWidth, newHeight, true);
Resources resource = getResources();
button.setBackground(new BitmapDrawable(resource, scaledBitmap)); // Change text on button:
button.setText(" ");
}
private void lockButtonSizes(){
for (int row = 0; row < NUMOFROW; row++){
for (int col = 0; col < NUMOFCOL; col++){
Button button = buttons[row][col];
int width = button.getWidth();
button.setMinWidth(width);
button.setMaxWidth(width);
int height = button.getHeight();
button.setMinHeight(height);
button.setMaxHeight(height);
}
}
}
}
It works great, but while testing I have found the following issue.
When I click random buttons it works great:
[img]http://i.imgur.com/OYFJ6zJ.png?1[/img]
But when I complete a row (all elements on row are clicked), and I mean any row it starts to rescale the buttons in the whole table:
[img]http://i.imgur.com/ttAz4U0.png?1[/img]
I was thinking that maybe the LayoutParams of the TableRow should be changed, but not sure about that. What am I missing here?
I think you're right about the layout parameters needing to change. This line
tableRow.setLayoutParams(new TableLayout.LayoutParams(TableLayout.LayoutParams.WRAP_CONTENT,TableLayout.LayoutParams.WRAP_CONTENT,1.0f));
would cause the row's height to shrink in size if no button had displayed text, which seems to be what's happening. The TableLayout.LayoutParams does support setting fixed width/height, which you could sensibly calculate by first getting the device's screen width/height and dividing accordingly.
Or, if that gets to cumbersome, you could set -- though this may be too much of a hack -- the default text in the TextViews in the "unset" buttons with some transparent text (e.g., "1,1") so that the height is the same as a set button. This SO answer answer shows how to make transparent text.
I am certain that this is not a good solution for all cases. But just as I thought, the problem was with
button.setLayoutParams(new TableRow.LayoutParams( TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.MATCH_PARENT, 1.0f));
If I understand correctly after the entire row was clicked, since the LayoutParams change according to the MATCH_PARENT value, the TableRow rescales the whole row to meet this criteria,since the height of the entire row is the same now. Not sure if it happens exactly this way, but I think this is the case because of my solution.
My work around is to add specific values for the LayoutParams, instead of leaving it the system to figure it out:
button.setLayoutParams(new TableRow.LayoutParams( 75, 50, 1.0f));
I am aware this is not how it should be done. But since I have a deadline to met soon, I can't spend any more time with it. Most likely the correct way to do this is Jason's suggestion to get the screen size and calculate it. You can do this with:
Display display = getWindowManager().getDefaultDisplay(); Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
The problem is to come up with a correct formula to calculate this values you can pass to the LayoutParam. If anyone can figure this out please do post your solution and I will accept that answer. At this point I accept Jason's suggestion.

Android - Dynamic textViews - setMargins not applying?

I'm trying to make a dynamic grid layout, it being API 10+ is the part that's been making it slow going. I tried to make it wrap automatically.. but in the end found it easier just to try to force it into a grid pattern using coordinates. This script was working by itself when I did the positioning at time of creation, but now I am trying to loop through each item as a sort. So if one item is deleted, they all float back into a grid without a hole in the middle.
Problem is, it seems the layout parameters are only applying to the last object.
Here's some base variables and onCreate setup:
int screenWidth;
int screenHeight;
int distStep = 130;
int leftPad = 20;
int numCols;
int baseID = 0;
android.util.DisplayMetrics metrics = this.getResources().getDisplayMetrics();
screenWidth = metrics.widthPixels;
screenHeight = metrics.heightPixels;
numCols = (int) (screenWidth - leftPad) / distStep;
int scrRemain = screenWidth - ((numCols * distStep) + leftPad);
distStep += (int) scrRemain / numCols;
Then on to the main function for adding:
public void addObjToLayout() {
RelativeLayout relLay = (RelativeLayout) this.findViewById(R.id.mainWindow);
for(int i = 1; i <= currQuantity; i++){
TextView tv=new TextView(this);
tv.setTextSize(40);
tv.setId(baseID + i);
tv.setPadding(24, 4, 24, 4);
tv.setBackgroundColor(0x110000FF);
tv.setText(String.valueOf(baseID + i)); //Val for debugging
tv.setTextColor(0xFFFFFFFF);
relLay.addView(tv);
}
baseID += currQuantity;
sortLayout();
}
Then the sorting:
public void sortLayout() {
int leftNum = 20;
int topNum = 0;
for(int i = 1; i <= baseID; i++){
TextView tv= (TextView) this.findViewById(baseID);
MarginLayoutParams mp = new MarginLayoutParams(tv.getLayoutParams());
mp.setMargins(leftNum, topNum, 0, 0);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(mp);
tv.setLayoutParams(lp);
leftNum += distStep;
if(leftNum >= distStep * numCols){
leftNum = leftPad;
topNum += distStep;
}
}
}
What I am getting is all the textViews pile up in the top left corner, except the last one which is positioned exactly where it should be. So it seems in my head, the params object isn't applying until the loop ends or something.. but logically I don't see why.
As I said, this worked when I set the params at the get go, problem is mass updating them all at once. I am pretty new to android, so I hope I'm not just doing something stupid.
Thanks for your time
Margin means it will set a gap between the previous view and current view.
When you add view1, view2 and view3 to grid layout and if you remove view2 at some point of time, then the margin for view3 is set according to view1. So, it won't leave empty space in place of view2. Instead of removing view2 at run time, set the background for view2 as null and set the text as empty as below.
textView.setBackground(null);
textView.setText("");
So that the view is still available but looks as deleted.
Started looking into GridView using an extended baseAdapter. Looks promising:
For more (see #2):
http://www.mkyong.com/android/android-gridview-example/

Android How to iterate an R.drawable object

I'm trying to display a frame by frame animation and want to iterate through the drawables so I don't have to type all their names in case the number of frames increases.
However I can't seem to find how to iterate through the drawables. I have looked up a fair bit of java for loop tutorials but they all just printed stuff which (as far as I'm sure) don't have to use here.
Here's the relevant code (the image's names are dude1, dude2, ...):
private void startAnimation(){
animation = new AnimationDrawable();
for (int i = 1; i < 4; i++) {
animation.addFrame(getResources().getDrawable(R.drawable.dude(i)), 100);
}
animation.setOneShot(true);
ImageView imageView = (ImageView) findViewById(R.id.img);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(80, 90);
params.alignWithParent = true;
params.addRule(RelativeLayout.CENTER_IN_PARENT);
imageView.setLayoutParams(params);
imageView.setImageDrawable(animation);
imageView.post(new Starter());
}
Thx!
I think the last answer is varely true but it may be:
for (int i=0; i <10;i++){
animation.addFrame(
getResources().getDrawable(getResources().getIdentifier("dude" + i,"drawable",
getPackageName()),100);
}
Try this. getResources() needs a context.
for (int i=0;i<10;i++){
animation.addFrame(getResources().getIdentifier("dude" + i,"drawable", getPackageName()),100);
}
Here, I have assumed 10 frames (i<10).
I have used Simon's answer to iterate through my drawables that are named "c1" through "c54" and placed in an array. Here is the code I just used that works for me.
private void getDeckDrawables() {
for (int i=1; i<53; i++){
intArrDeck[i-1] = getResources().getIdentifier("c"+i,"drawable",getPackageName());
}
}
Previously, I typed them manually which took up too much room for my taste.
private void getDeckDrawables() {
intArrDeck[0]=R.drawable.c1;
intArrDeck[1]=R.drawable.c2;
intArrDeck[2]=R.drawable.c3;
}

Categories

Resources