Randomly placing drawables in a grid - android

I have a grid layout where the number of rows and columns in it varies depending on the value of an int that is parsed to the activity. I'm now trying to randomly put one of the 12 images I have into each of the grid spaces to get a random mix of images in a square on the screen. So how do I put drawables into grid spaces without using xml and would a table layout be better? I will also need to be able to detect what image is in the grid space when it is clicked on.

I had the same problem while implementing a memory game some time ago.
To get a drawable object you first need to get your app resources.
Resources res = getResources();
Then, what I do for generate the random position is to put all my images in an ArrayList that has the number of elements equal to the number of grids your have:
ArrayList<Drawable> imagesArray = new ArrayList<Drawable>();
imagesArray.add(res.getDrawable(R.drawable.yourdrawablename));
imagesArray.add(res.getDrawable(R.drawable.yourdrawable2name));
//and so on for the following drawables you have.
After that, you could generate a random number using your ArrayList's size, that is the same amount of images you have, and after that, you put the images on your grid and remove it from the array.
for(int i = 0 ; i < imagesArray.size() ; i++) {
int randomPosition = Random.nextInt(imagesArray.size());
//here's the code to put your drawable in your grid view, in my case, it was just a button
//background, so I didn't know exactly how to put it inside a position of the grid, but it
//should not be that difficult to get it from documentation
//In my case, I do:
button.setBackground(imagesArray.get(randomPosition));
//And then delete that position on the array...
imagesArray.remove(randomPosition);
//And repeat until array's length is null;
}
For the last question, for discovering witch drawable is in which grid, you could get the constantState of it like this:
gridViewElement.getBackground();
This will return the background as a drawable that is associated with that gridView.
Also, be aware that if you want to compare to drawables inside two differente grids, you should use this:
if(gridViewElement1.getBackground().getConstantState()
.equals(gridViewElement2.getBackground().getConstantState())) {
//code goes here.
}

Related

How to display images in a Recycler View (Grid Layout)?

How to display all images in drawable res folder in a Recycler View (Grid Layout)? What if there are hundereds of them?
I tried the regular method and it worked but I had only 5 images then. How to do the same for 100 images, it is a lot of work.
recyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
and to view image you have to use Picasso in your recycler adapter
You could try creating a drawbles array that would store all your images, then using a loop to display all of them.
Drawble [] drawables = new Drawable[]{ContextCompat.getDrawable(getActivity(), R.drawable.digit00),ContextCompat.getDrawable(getActivity(),R.drawable.digit01),ContextCompat.getDrawable(getActivity(), R.drawable.digit02));
You can also use a loop to print out what you will put in the drawable array, so you can save on typing.
For example create a loop that prints 'ContextCompat.getDrawable(getActivity(), R.drawable.digit' + int')' to the logcat (the int is an int that will be incremented each time, this is why i said to name your drawables with a number at the end, like digit00 - digit99). Then you can just copy all that into your real code.

How to speed up for loop

I dynamically add textviews to a relative layout based on user response to create a coloured grid pattern. Typically this can contain 5000+ textviews which have different background colors based on the value in textview tag.
I have this method where I iterate through all the textviews to show only those that have the same color and set the rest to gray. This works well when there are say 500 textviews but when the number is higher, say 5000 it take 13 seconds to complete.
if (code.equals("all")) {
for (int i = 0; i < textViewIDs.size(); i++) {
TextView tv = (TextView) findViewById(textViewIDs.get(i));
if (!tv.getTag().toString().equals("header")) {
tv.setBackgroundColor(Color.parseColor("#" + tv.getTag().toString()));
}
}
} else {
for (int i = 0; i < textViewIDs.size(); i++) {
TextView tv = (TextView) findViewById(textViewIDs.get(i));
if (!tv.getTag().equals(code)) {
if (!tv.getTag().toString().equals("header")) {
tv.setBackgroundColor(Color.LTGRAY);
}
}else{
tv.setBackgroundColor(Color.parseColor("#" + tv.getTag().toString()));
}
}
}
textViewIDs is the array holding all the textview ids.
What if anything can be done to speed this up?
Update:
I understand that having that number of widgets is not ideal however I could not come up with a better solution.
As well as each grid cells, in this case each texview, having different colors I also need to be able to manage onclick event for the cell so that I can add text. That was the reasoning for the textviews. Prior to using textviews I drew all the elements but that's when I couldn't find a way to add onclick event to each cell.
I'd better detail the concept to help you guys with what I'm trying to achieve and if I've gone down the wrong road.
This is part of a much larger app where I'm converting images into stitch charts.
Based on user input a grid of colored cells is drawn where each cell is a solid color that has been calculated from the original image most dominant color.
The grid will be larger than the screen so my views are placed in both horizontal and scroll views so they can be panned and zoomed. (This is all working well).
The grid cells have to click-able so I can turn on or off the background colors and also add a single text "X" character to mark stitch (cell) as completed.(This is to slow when the number of textview (cells) are > 500)
Hope there is enough detail there...
findViewById() seems to be your pressure point.
Instead of keeping a list of the ids, I'd a keep a list of references to the Views themselves (WeakReferences if leaks are a possibility)!
1 - for (int i = 0; i < textViewIDs.size(); i++) { ...
It's not optimized: precalculate your limit in a variable before starting the cycle:
int len = textViewIDs.size(); and use len in your cycle.
2 - i-- (I call it "reverse loop") seems to be faster than i++. See a nice loop comparison here
It's a bad practice to have that many TextView's, low-end devices will not be able to load it.
Try making one TextView with multiple styles in it, you can use HTML tags for background colors.
Or even better is to create just one ListView, this will recycle the views for you.

how to apply the Animation in viewflipper in Android

I create one simple image banner apps in which I use the viewflipper for swipe image one by one. My apps run very well but the first image is repeated two time. Here I use the image array and apply in view flipper.
The Array is:
int imageDrawable[] = new int[]{R.drawable.advanturestorybanner_ipad_landscap,
R.drawable.femouspeopleofthebiblebanner_ipad_landscap,
R.drawable.littlebanner_ipad_landscap,
R.drawable.thechildrenbiblebanner_ipad_landscap,
R.drawable.thecomicbookbiblebanner_ipad_landscap,
R.drawable.thehandybiblebanner_ipad_landscap };
bannerImageView.setBackgroundResource(imageDrawable[j]);

Swapping images in a table layout

I have a 2D array of ImageViews and am currently displaying each of them in a tableLayout. If I wanted to switch the ImageViews, I think that I need to swap the bitmaps that each [i][j] imageViews are assigned to. For example, if I wanted to swap positions of the images at [0][0] and [0][1], how would I do this?
I have a feeling that I would need to reassign each underlying bitmap to the appropriate imageview.
You could try getting the Drawable, on the imageviews and save it to variables:
Drawable d1 = imageViews[0][0].getDrawable();
Drawable d2 = imageViews[0][1].getDrawable();
Then you swap the drawables by:
imageViews[0][0].setImageDrawable(d2);
imageViews[0][1].setImageDrawable(d1);
I think that will switch the images of the views, or do you actually need to move the positions of the imageviews?

Android - fix TextView width by string

I think the answer to this question is probably so simple, but I'm struggling....
I have a TableLayout with multiple columns. I want the last column to be of a fixed width, but I want to define that width to just be able to hold the widest possible string from my program. i.e. it is always wide enough to contain "THIS STRING" without wrapping, or wasting any space.
I would like to do this as I have these TableLayouts within a ListView, so it looks very poor when the last column is of variable widths.
I have tried obtaining the string width, even going so far as to put it into a TextView, call getTextSize() then setWidth() on all appropriate TextViews. The problem I hit there is that gettextSize() returns pixels, but setWidth uses ScaledPixels.
I'm sure there is a really simple solution. Can anyone help?
Are you using android:width="wrap_content" in your XML layout to define the width of that last column?
Edit: I think I just understood, you have a list view, that holds a table and you want all rows of the list view to have the same length for the last row of the table. Right?
I can only think of one, very unelegant solution right now and it involves going over all strings before building the list view.
The general logic would be as follows:
Im going to suppose you are getting al strings from an array, lets call it data.
Establish a global float variable to represent the longest string you have, lets call it maxLength.
Create a textview (lets call it invisibleText) in your layout that wont be visible, you can do this by setting
android:visibility="gone"
Then:
int size = data.length;
maxLength = 0.0f;
for(int i = 0;i<size;i++){
invisibleText.setText(data[i]);
float thisLength = invisibleText.getTextSize();
if(thisLength>maxLength) maxLength = thisLength;
}
In you list view constructor:
TextView text = (TextView)findViewById(R.id.the_text_view_you_want);
text.setText(data[position]);
text.setWidth(maxLength)
The table columns should use android:width="wrap_content"
I didnt test this code, but it should work, i've done similar stuff before.

Categories

Resources