Swapping images in a table layout - android

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?

Related

IMAGE VIEW ANDROID STUDIO

I have a doubt. While working on an App , I came across this query.
When an Imageview1(smaller size) is dragged and dropped on to Imageview2(bigger size), how to make Imageview1 (fit the area of imageview2), that is, enlarge the Imageview1 automatically to the size of Imageview2.
Instead of doing something so twisted, you can try a simpler solution like:
ImageView2.setImageDrawable(ImageView1.getDrawable());
ImageView1.setVisibility(INVISIBLE); //GONE could be used too, depending on the situation
Overwriting ImageView2 would involve many other operations like moving ImageView1 inside the layout, setting new LayoutParams, etc.
EDIT
Use this:
ImageView1.buildDrawingCache();
Bitmap src = ImageView1.getDrawingCache();
BitmapDrawable destDrawable = new BitmapDrawable(Bitmap.createScaledBitmap(src, ImageView2.getWidth(), ImageView2.getHeight(), false));
ImageView2.setImageDrawable(destDrawable);
In general, it is not a good practice to have views cover other views.
When you do the drag action try this
ImageView.ScaleType(FIT_XY);

Randomly placing drawables in a grid

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

Creating and combining NinePatchDrawables at runtime

I am creating a compound custom control. The control consists of a single element across the bottom and an unknown number of elements across the top. The background for each of these elements is a StateListDrawable defining the NinePatchDrawables to use for each state of that element.
As the individual top elements change their width to suit their content, the region of the bottom element directly below needs to also change width to suit. The top elements may also have their positions shifted left or right.
The images above and below are just quick mock-ups to convey the layout and behavior I need to achieve. I am not responsible for designing the actual background images to be used, but they will not be a uniform flat grey.
I managed to solve the first part of this re-sizing problem by:
Creating a custom class which extends Drawable.
Passing the class an array of NinePatchDrawables defining various potential regions of the Bottom View (eg left_end, right_end, middle_below_control, middle_below_gap).
Changing the bounds of each to match the relevant view above during the custom class' onBoundChange().
Drawing my array of re-sized NinePatches to the Bottom View canvas in onDraw().
Setting a combined padding for the Bottom View based on the padding of the NinePatches in the array.
This solution raises a number of problems though:
You need StateListDrawables for each of the potential regions of the Bottom View.
You need individual NinePatch images for each of the states in each of these StateListDrawables.
You have to design an image for the Bottom View which is restricted to being very uniform across it's width.
You need ear defenders and a thick skin to deal with all the shouting from the graphic designers.
What I really need to achieve is:
Have a single StateListDrawable for the Bottom View.
Extract the single image for each state and slice it up into the required sections.
Create a new NinePatchDrawable for each slice, applying the data Chunk from the view above for width only. Not height.
Then re-combine them as per my previous solution above.
Unfortunately as we know, you can't really play with the data Chunk. It's generated at compile time from the source image to create the NinePatch binary.
One of the better answers on this sort of topic can be found here. Based on this, a possible compromise solution might be:
For each of the top element types, have the graphic designers supply an additional blank dummy NinePatch source with the identical height and width dimensions, identical width padding and patch definitions, but with the height padding and patch definitions as they want for the bottom view.
Use getNinePatchChunk() on the relevant dummy NinePatch compiled resource.
Combine the resulting data Chunk with the relevant Bottom View bitmap slice to create a new NinePatch using NinePatch(Bitmap bitmap, byte[] chunk, String srcName).
Put up with dirty looks from the graphic designers, but at least they've stopped shouting.
This seems like it would be a bit of a clunky way of doing things. Is there a better, more efficient way of going about this to achieve all the required goals?
Note: There are likely to be many instances of this custom control in a scroll view, when used in an app, so nested layouts need to be kept to a minimum.
I have finally come up with a way to avoid using a blank dummy NinePatch source as necessary my compromise solution above.
Based on this excellent solution to a similar problem, I have written a utility method to extract the padding info from a NinePatch resource. Using this, I can extract the necessary padding from the adjacent NinePatch regions, and apply them to my new slice. Hope this is helpful to others.
public static Rect getNinePatchPadding(Context context, int drawableId) {
Rect mPadding = new Rect();
Bitmap bm = BitmapFactory.decodeResource(context.getResources(), drawableId);
final byte[] chunk = bm.getNinePatchChunk();
if (!NinePatch.isNinePatchChunk(chunk)) return null;
ByteBuffer byteBuffer = ByteBuffer.wrap(chunk).order(ByteOrder.nativeOrder());
// Skip to padding
for (int i = 0; i < 12; i++) {
byteBuffer.get();
}
mPadding.left = byteBuffer.getInt();
mPadding.top = byteBuffer.getInt();
mPadding.right = byteBuffer.getInt();
mPadding.bottom = byteBuffer.getInt();
return mPadding;
}

Drawing a large number of ImageViews with the same Bitmap but different size

I am trying to draw multiple ImageViews inside a single LinearLayout.
All the ImageViews need to have a single bitmap.
The ImageViews will only vary in size.
The single bitmap will not be resized.
The simple way is to create one Bitmap per ImageView. But, this runs out of memory quickly.
final Bitmap placeholderBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
final Canvas canvas = new Canvas(placeholderBitmap);
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.placeholder_image), 0, 0, null);
imageView.setImageBitmap(placeholderBitmap);
linearLayout.addView(imageView);
I also tried setting the max and min height and width, no effect. The images remain the same size.
imageView.setImageResource(R.drawable.ic_no_image);
imageView.setMaxHeight(imageViewInfo.height);
imageView.setMaxWidth(imageViewInfo.width);
I believe working with Drawables is the right "Android" way to do it, but I can't find a way to dynamically create a Drawable with the right side and layering the shared bitmap into it.
Just use one Bitmap -- as you say they will all use the same Bitmap, so no duplication is necessary.
If you want the ImageViews to have different sizes and have the Bitmap scale itself to the size of the ImageView then use the setScaleType or android:scaleType attribute to set the scaling of the ImageView. For instance FIT_START maintains the aspect ratio of your image and tries to fill the ImageView starting from the top-left corner.
I don't see any need to create a Drawable, though if you need to you can just create one from a Bitmap using:
Drawable d = new BitmapDrawable(bitmap);
ImageView actually does this automatically when you call setImageBitmap(...).
ImageView will always resize the bitmap to it need proportions.
If you want to save memory, resize the bitmaps manually and set them into the ImageViews this should stop the ImageView from resizing it internally - to make sure, you can set the layout_width and layout_hieght of the image view to 'wrap_content'.
I think may be looking for a ClipDrawable.
You would set the android:drawable property of the clip XML to your bitmap
That or you can do it with the Java code also given in the example

How to set the x position of views in android

I am creating a number of imageviews and textviews on runtime depending on the objects in my webservice. I'm creating linearLayout horizontal and adding imageviews and textviews to layout, now the issue is the text are against images, and images are of different width so i want to set x position of my textviews so they all look align how can this be done,
i tried absolutelayout(warning deprecated) , setx(no method showed)
you can use resized image on runtime based on the pannel height and width for resizing image on runtime view this stack overflow thread
resizing image java getScaledInstance
I presume you mean this is a vertical LinearLayout, and each text/image combo is added below the previous one? In that case, you could have two LinearLayouts next to each other like two columns, adding the images to one and the text fields to the other. Then the widest image would stretch its layout to that width and all text fields would be just to the right of it.
Use weight property in your ImageView and TextView

Categories

Resources