Get width of ImageView returning 0 - java

I realize there is a question similar to this on stack overflow (getWidth() and getHeight() of View returns 0) that has gotten much attention. It seems like I may be calling getWidth too early, but how can I be sure that it does have an actual width though? I'm worried because I believe I may be getting a size of zero because of how I'm implementing an imageBitmap and not an imageResource.
My onCreate:
// Byte array to bitmap
BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
mainImageBitmap = BitmapFactory.decodeByteArray(byteArray, 0,
byteArray.length, options);
// Set bitmap
mainImageView.setImageBitmap(mainImageBitmap);
Log.e("", mainImageView.getWidth() + " ");
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(400, 400); //Want to use getWidth and getHeight here, just hardcoding to 400 for now
layout.setLayoutParams(params);

use GlobalLayout
example :
Global Layout Example
attach the Global layout to the view u want
when the view will be ready it will callback to this function with width and height
in your case try using the next Code
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);

Related

BitmapFactory.Options inSampleSize documentation confusion

Following is the code from the official Android documentation.
https://developer.android.com/training/camera/photobasics
private void setPic() {
// Get the dimensions of the View
int targetW = imageView.getWidth();
int targetH = imageView.getHeight();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(currentPhotoPath, bmOptions);
imageView.setImageBitmap(bitmap);
}
I am not able to understand the use of Math.min function here. So what Math.min is doing, is selecting the smallest ratio between photoW/targetW and photoH/targetH.
Now, let us suppose there is an image whose width is two times larger than that of the imageView and its height is four times larger than that of the imageView. So, the ratios come to be two and four and the Math.min function will give us two in the scaleFactor.
And what bmOptions.inSampleSize does is
https://developer.android.com/reference/android/graphics/BitmapFactory.Options#inSampleSize
If set to a value > 1, requests the decoder to subsample the original
image, returning a smaller image to save memory. The sample size is
the number of pixels in either dimension that corresponds to a single
pixel in the decoded bitmap. For example, inSampleSize == 4 returns an
image that is 1/4 the width/height of the original
According to this, our image will get half it's size whose height will still be two times bigger than that of the imageView.
Shouldn't we use Math.max or am I missing something?

Set a view's width to be relative to device screen programmatically

I have a horizontal RecyclerView with child elements which I want to change the width of to be a bit less than the current match_parent set via the layout. I want to do this so that the next element in list is a bit visible on screen.
In the adapter onCreateViewHolder I am doing this:
ViewGroup.LayoutParams params = view.getLayoutParams();
params.width = MainActivity.deviceWidth - (int) MainActivity.dpToPx(40.0f);
view.setLayoutParams(params);
where MainActivity.deviceWidth is:
DisplayMetrics displaymetrics = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
deviceWidth = displaymetrics.widthPixels;
screenDensity = Resources.getSystem().getDisplayMetrics().density;
and dpToPx is this function:
public static float dpToPx(float dp) {
return (dp * screenDensity + 0.5f);
}
This works. however, I noticed that on different devices, the "margin" I am setting is not always the same. I.e. the next card in the RecyclerView is not always showing the same amount.
Is the dpToPx conversion correct? I might be missing something else in my calculation but I am not sure what.
Update
Changing:
params.width = MainActivity.deviceWidth - (int) MainActivity.dpToPx(40.0f);
To:
params.width = (int) (MainActivity.deviceWidth *0.9);
works!. I am fine with this solution. I just want to know why the previous one does not work...

Android how to resize (scale) an xml vector icon programmatically

This is driving me crazy. I would like to be able to resize an xml vector drawable icon programmatically in order to use it in an ImageView.
This is what I've done so far which is not working
Drawable drawable = ResourcesCompat.getDrawable(getResources(),R.drawable.ic_marker,null);
drawable.setBounds(0,0,512,512);
imageVenue.setImageDrawable(drawable);
The vector icon ic_marker is not resized. It just keeps the hardcoded width and height values every time.
Any ideas?
You can change the width and height of your imageview programmatically. Since vector drawables will preserve the original quality of the image, this will make the desired output happen.
ImageView iv = (ImageView) findViewById(R.id.imgview);
int width = 60;
int height = 60;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(width,height);
iv.setLayoutParams(params);
I'm currently facing the same problem.
I'm trying something like this, cause ViewParent has actually height set explicitly, so I use match_parent and set margins. It doesn't work all the time though, cause I simply use this view in a viewholder for RecyclerView... Also I've noticed that sometimes I see scaled up version with artifacts, sometimes full size, sometimes there are margins, and bigger margins... But it still might work for you, if you use it in a simpler scenario.
mImageViewFront.setImageDrawable(vectorDrawable);
final int paddingLR = mImageViewFront.getWidth() / 4;
final int paddingTB = mImageViewFront.getHeight() / 4;
LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.setMargins(paddingLR, paddingTB, paddingLR, paddingTB);
mImageViewFront.setLayoutParams(params);

ImageView disappears after LayoutParams Change

I added a ImageView to my LinearLayout in the onCreate method programmatically and it worked as it should.
img = new ImageView(this);
img.setImageResource(R.drawable.source);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.setMargins(0, 50, 0, 0);
img.setLayoutParams(params);
layout = (LinearLayout) findViewById(R.id.index_view);
layout.addView(img);
And the I want to change it's x and y coordinates when the user touches the screen.
onTouch method - case ACTION_MOVE:
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.setMargins(newX, newY, 0, 0);
img.setLayoutParams(params);
the newX and newY are calculated based on the users touch-coordinates
But this code doesn't seem to work correctly.
I created toasts to show me the Image width after every touch and it showed me that the width is set to zero after first touch. This tells me: ImageView disappeared.
Any guesses?
I am assuming that you made sure that you are getting newX, newY values in onTouch().
I feel that your aim is to edit the Layout parameters but instead of doing that what you are doing is, you are assigning a new set of parameters with width and height as LayoutParams.WRAP_CONTENT and then setting the margins.
You might try to first get the existing parameters as follows:
LinearLayout.LayoutParams params =
( LinearLayout.LayoutParams) img.getLayoutParams();
Then change the margin:
params.setMargins(newX, newY, 0, 0);
img.setLayoutParams(params);
Try it and notify if it helps. If not then we can talk further.

Android, Java: Resized Bitmap ignores bitmap options

I am creating this Android game with Java. However, I load the bitmaps and then resize them to fit screens and such (dpi isn't really exact). BUT my thought is also to load the bitmaps in 16b (mBitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_4444) for devices with a small amount of ram. But when I resize the bitmaps they seem to go back to 32b (Bitmap.Config.ARGB_8888).
This is how I declare the options:
mBitmapOptions = new BitmapFactory.Options();
mBitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_4444;
This is how I load the bitmaps:
mBitmaps.add(getResizedBitmap(BitmapFactory.decodeResource(mResources, imagePath, mBitmapOptions)));
And this is the getResizeBitmap method:
public Bitmap getResizedBitmap(Bitmap bm)
{
//Original size
int width = bm.getWidth();
int height = bm.getHeight();
//New size (percent)
float newWidth = 1 * mScaleWidth;
float newHeight = 1 * mScaleHeight;
//Create the matrix
Matrix matrix = new Matrix();
matrix.postScale(newWidth, newHeight);
//Recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
//Recycle the old Bitmap
bm.recycle();
return resizedBitmap;
}
Any ideas why the new Bitmap ignores the options?
Why don't you use the createScaledBitmap method? It should preserve the options. In your case, you are creating a completely new Bitmap and it probably applies a default config.
EDIT: Another option would be to use your code and add a call to the copy method like this:
Bitmap smallerBitmap = resizedBitmap.copy (Bitmap.Config.ARGB_4444, false);
resizedBitmap.recycle ();
However, I don't think this will have a nice performance...

Categories