Android LinearLayout how to access a cell in a matrix - android

I am developing a Tic-Tac-Toe game in which the size is N*N and not 3*3, and I am using ImageView to implement the game board.
As a beginning I am trying to implement the board as a matrix in which I will be able to access any cell because I am adding a single player mode with an AI.
The code that builds the board on the screen in the onCreate method is this:
//defining the board and parameters
main = new LinearLayout(this);
main.setOrientation(LinearLayout.VERTICAL);
LayoutParams params = new LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
main.setLayoutParams(params);
//implementing the board
for (int j = 0; j < k; j++) {
row = new LinearLayout(this);
row.setOrientation(LinearLayout.HORIZONTAL);
row.setLayoutParams(params);
for (int i = 0; i < k; i++) {
//drawing empty spaces in the squares, player=1 is for the player and player=2 is for the AI
player=0;
MyImageView cell = new MyImageView(this,player); //code that draws on the board using MyImageView - a class that extends ImageView
Board[j][i]=player;
cell.setLayoutParams(new LayoutParams(width / k, width / k));
cell.setOnClickListener(this);
row.addView(cell);
}
main.addView(row);
}
setContentView(main);
k is the order of the board matrix.
Now, my problem is that I don't know how to access to a certain cell through the MainActivity class and draw a Circle in it, because the player is the X and the AI is the Circle.
I only need help in implementing the board so that I will be able to access any cell on it.

You need a coordinate-system and a way to identify the different cells. For instance each cell could get an id like this
cell.setId(numCells++);
where numCells is set to 0 before the first for-loop.
An other way is maybe to create a grid and store the coordinate in the tag of the cell:
cell.setTag(tag)
where tag is
tag = String.valueOf(j)+"x"+String.valueOf(i)
Or you could store the formentioned ids of the cells in a array-grid and access the right cell based on the position in the grid.
EDIT:
You can access a specific sell by calling :
cellToDrawIn = findViewById(AI-prefered cell ID);
or
cellToDrawIn = findViewByTag(AI-prefered cell TAG);
How the get the ids or tags depend on how your AI calculates where it whant to put a circle.
Remeber, this a one of many possible solutions...
And are GridView out of the question?

Related

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

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".

Position ImageViews with an offset programmatically

I have to create a stack of images programmatically (because they have to be dynamic).
I want to stack ImageViews like this:
I've tried this, but the images all land up on top of each other:
for(int i=0; i<limit; i++){
dynamicButtons[i] = new ImageView(contextSosFragment);
int offsetLeft = 15 * i;
int offsetTop = 15 * i;
layoutParamsDynamicButton.setMargins(offsetLeft, offsetTop, 0, 0);
dynamicButtons[i].setAdjustViewBounds(true);
dynamicButtons[i].setScaleType(ScaleType.FIT_CENTER);
dynamicButtons[i].setImageResource(R.drawable.img_badge_dynamic_loading);
dynamicButtons[i].setTag(id);
containerDynamicButtons.addView(dynamicButtons[i], layoutParamsDynamicButton);
}
I've even removed the android:gravity="center" from my xml layout file.
I've also tried to add the layout params on the ImageView after setting the margins (dynamicButtons[i].setLayoutParams(layoutParamsDynamicButton);), but I read that that this might not take effect, because the layout params are for the parent and not the child of the container to which I add the ImageViews, that's why I tried to use addView(view, layoutParams).
How can I position the ImageViews like this, programmatically?
SOLUTION:
The solution was that I had to create a new layout params instance for each image - just like Devunwired suggested. However, I also found that I had to change the LinearLayout.LayoutParams to be RelativeLayout.LayoutParams. Only then did the change take effect.
The final for loop looks like this:
for(int i=0; i<limit; i++){
RelativeLayout.LayoutParams layoutParamsDynamicButton = new RelativeLayout.LayoutParams(width, height);
layoutParamsDynamicButton.bottomMargin = (int) getActivity().getResources().getDimension(R.dimen.margin_badges);
int offsetLeft = AppConstants.dynamic_button_offset_multiplier * i;
int offsetTop = AppConstants.dynamic_button_offset_multiplier * i;
layoutParamsDynamicButton.setMargins(offsetLeft, offsetTop, 0, 0);
Log.d(TAG, "offset = "+offsetLeft);
dynamicButtons[i] = new ImageView(contextSosFragment);
dynamicButtons[i].setAdjustViewBounds(true);
dynamicButtons[i].setScaleType(ScaleType.FIT_CENTER);
dynamicButtons[i].setImageResource(R.drawable.img_badge_dynamic_loading);
dynamicButtons[i].setTag(id);
containerDynamicButtons.addView(dynamicButtons[i], layoutParamsDynamicButton);
}
Each view needs its own LayoutParams object. It looks like your code just updates the same LayoutParams instance each time and passes it to addView(). If this is the case, all your views are pointing to the same params when it comes time to do layout...and their margins will all be the last value set.
As a performance optimization, if you are just placing several static images on top of each other, you could achieve the same effect (including the offsets) with a LayerDrawable (docs link) inside a single ImageView. This is the object created by <layer-list> in XML, but since you need to dynamically set the offset you could create one in code as well. Fewer views typically leads to cleaner UI.

Creating a GridView-like layout in Android without using GridView

So I'm trying to create a GridView style layout in Android without actually using a custom Gridview adapter, since I don't want it to scroll. I've tried just turning scrolling off, but it ruins my layout since I'm adding other elements around it in a vertical LinearLayout.
My next experiment was to use a TableLayout and then just add inflated layouts as table cells, but I'm also having an issue with this. Here is a test that I am running for a brief proof of concept:
TableRow trackingActivityRow = new TableRow(getActivity());
for(int j = 0; j < trackingActivities.size(); j ++) {
TrackingActivity trackingActivity = trackingActivities.get(j);
View trackingActivityCell = getActivity().getLayoutInflater()
.inflate(R.layout.table_cell_tracking_activity, trackingActivityRow, true);
TextView txtDescription = (TextView)trackingActivityCell.findViewById(R.id.txtDescription);
txtDescription.setText(trackingActivity.getDescription());
}
tableLayout.addView(trackingActivityRow);
It seems to create the number of cells correctly, but it doesn't want to set the text like it should be. Furthermore, I'm having an issue of logic when it comes to creating a new row for every 4 TrackingActivities.
If anyone has any input it would be appreciated.
/Update/
Here is a graphic of the issue. The cell with "Walk" in it is displaying correctly, but the other cells only display the placeholder text inside the textview which should have been replaced.
I created a customized GridView based on a tablelayout with a listadapter.
Simplified version of the setAdapterMethod in the extended TableLayout:
int itemPos = -1;
int numRows = (int) Math.ceil((double) adapter.getCount() / (double) mNumColumns);
for (int yPos = 0; yPos < numRows; yPos++) {
//Create new row
TableRow tableRow = new TableRow(this.getContext());
for (int xPos = 0; xPos < mNumColumns; xPos++) {
itemPos++;
View itemView = adapter.getView(itemPos, null, tableRow);
tableRow.addView(itemView);
}
this.addView(tableRow, new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT, TableLayout.LayoutParams.MATCH_PARENT));
}

Android: How do I randomly place an array of buttons in an activity?

I was wondering how I could "randomly" place an array of Buttons in a RelativeLayout?
Is it possible to space the buttons around the entire view?
Thanks for your help! I tried using setX() and setY() but they are float numbers and I'm unsure how they place the buttons in proportion to the size of the screen.
You can add layout margins to your buttons. As margins will be interpreted not relative to each other but to the frame, it will in fact position your buttons.
To set the margins you have to set the view's layout params:
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
Random random = new Random();
params.leftMargin = random.nextInt(100);
params.topMargin = random.nextInt(100);
button.setLayoutParams(params);
However this may cause your buttons to overlap, or be outside the Activity, so it's best not to use entirely random values for positions but to perform checks for overlapping and set random ranges according to the device resolution and button size.
To get device display size:
Display display= activity.getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int Height = display.getHeight();
instead do something like this first create a button array and find the respective id...
LayoutParams lp = new LinearLayout.LayoutParams(widthOfButtons,LayoutParams.WRAP_CONTENT);
Button[] buttons;
for(int i=0; i<4; i++) { //suppose you have four buttons
{
String buttonID = "button" + (i+1);
int resID = getResources().getIdentifier(buttonID, "id", getPackageName());
buttons[i] = ((Button) findViewById(resID));
buttons[i].setHeight(yourvalue);
buttons[i].setWidth(yourvalue);
buttons[i].setLayoutParams(lp);
}
hope it works for your

How to can i control on the Bitmap size that will be draw on ImageButton?

On my code i need to create some table that each column contain Bitmap and text - and i create this table dynamically.
So i doing this by using this code:
for (int i = 0; i < collection.size(); i++)
{
ObjectITem item = collection.get(i);
LinearLayout linearLayout = new LinearLayout(this);
linearLayout.setOrientation(LinearLayout.HORIZONTAL);
TextView textView = new TextView(this);
textView.setText(item.getText());
linearLayout.addView(textView);
linearLayout.addView( (new ImageButton(this)).setImageBitmap(item.getBitmap());
layout.addView(linearLayout, LayoutParams.WRAP_CONTENT);
}
this code is working good - but because the originaly images are not in same size - i see that the images that appear on the ImageButton are look not good.
How can i make all the images on the ImageButton to look the same ?
Is there some better way to make the layout that i did here ?
1) You can use Bitmap.createScaledBitmap() to scale all the images to a desired size. Like this...
Bitmap buttonBmp = Bitmap.createScaledBitmap(item.getBitmap(), buttonW, buttonH, true);
linearLayout.addView((new ImageButton(this)).setImageBitmap(buttonBmp);
2) You might want to consider using a ListActivity and a ListView. This is more complicated, but may be more efficient if your collection is large and needs to scroll over many pages.

Categories

Resources