This is my layout file
<LinearLayout ...
<ImageView
android:id="#+id/feed_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:adjustViewBounds="true"
android:contentDescription="#string/image_content_description" />
But ImageView width does not match parent width. (width is image source width)
Image Source loaded Lazy-loading from url.
How to scale the width of image view regadless image source ?
I want
Width = match(or fill) parent.
Height = auto-scaled
You can achieve this in two ways:
If your image is larger than the ImageView you can use xml only
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:adjustViewBounds="true"/>
If your image is smaller than the ImageView
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:adjustViewBounds="true"/>
With the second option you have to measure the width and height of the image and set the height of the ImageView in your code, according to the actual width of the image view (same ratio).
You can use android:scaletype="fitXY" property of imageview
2.default Android will scale your image down to fit the ImageView, maintaining the aspect ratio. However, make sure you're setting the image to the ImageView using android:src="..." rather than android:background="...". src= makes it scale the image maintaining aspect ratio, but background= makes it scale and distort the image to make it fit exactly to the size of the ImageView. (You can use a background and a source at the same time though, which can be useful for things like displaying a frame around the main image, using just one ImageView.)
If you want to fit the image in view use android:scaleType="fitXY"
You can achieve this with this, create new AspectRatioImageView that extends imageView:
public class AspectRatioImageView extends ImageView {
public AspectRatioImageView(Context context) {
super(context);
}
public AspectRatioImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AspectRatioImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Drawable drw = getDrawable();
if (null == drw || drw.getIntrinsicWidth() <= 0) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} else {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = width * drw.getIntrinsicHeight() / drw.getIntrinsicWidth();
setMeasuredDimension(width, height);
}
}
}
And then in your layout xml use :
<my.app.AspectRatioImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/ar_imageview"/>
<ImageView
android:id="#+id/idImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"/>
calculate the height according to the aspect ratio that you want
Display display = getActivity().getWindowManager().getDefaultDisplay();
int height = (display.getWidth() * 9) /16; // in this case aspect ratio 16:9
ImageView image = (ImageView) findViewById(R.id.idImage);
image.getLayoutParams().height = height;
Related
Url image having width 900*346, we are using same image for displaying detail image and thumbnail image.Thumbnail image is displaying in Gridview with 2 columns and 200dp height but image is stretching.Is there any way to display larger width image with out stretch. Thanks in advance.
GridView Xml:
<?xml version="1.0" encoding="utf-8"?>
<GridView
android:id="#+id/grid_img"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:horizontalSpacing="#dimen/portfolio_grid_space"
android:verticalSpacing="#dimen/portfolio_grid_space"
android:layout_marginTop="#dimen/portfolio_grid_space"
android:layout_marginBottom="#dimen/portfolio_grid_space"
android:numColumns="2"/>
Gridview Adapter xml:
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/img"
android:scaleType="fitCenter"
android:layout_width="match_parent" android:layout_height="200dp">
</ImageView>
Give in the xml file of your layout android:scaleType="fitXY"
P.S : this applies to when the image is set with android:src="..." rather than android:background="..." as backgrounds are set by default to stretch and fit to the View.
If I do not misunderstand, you want to keep image width/height ratio while stretching the image. You can put the below lines in your xml ImageView:
android:adjustViewBounds="true"
android:scaleType="centerCrop"
You can play around with scaleType to get your desired image.
IF you are using device below API 17, you can custom ImageView:
public class ScaleAspectFillImageView extends ImageView {
public ScaleAspectFillImageView(Context context) {
super(context);
}
public ScaleAspectFillImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScaleAspectFillImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// If API level <= 17,
// Only need custom measurement for image whose size is smaller than imageView size.
// http://developer.android.com/reference/android/widget/ImageView.html#setAdjustViewBounds(boolean)
if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR1) {
float viewWidth = MeasureSpec.getSize(widthMeasureSpec);
float viewHeight = MeasureSpec.getSize(heightMeasureSpec);
// Calculate imageView.height based on imageView.width and drawable aspect ratio using scale-aspect-fill mode.
Drawable drawable = getDrawable();
if (drawable != null) {
float drawableWidth = drawable.getIntrinsicWidth();
float drawableHeight = drawable.getIntrinsicHeight();
// Only need custom measurement for image whose size is smaller than imageView size.
// Avoid divide by zero error.
boolean needCustomMeasurement = drawableWidth < viewWidth || drawableHeight < viewHeight;
if (needCustomMeasurement && drawableHeight > 0) {
float drawableAspectRatio = drawableWidth / drawableHeight;
// imageView.width and drawable aspect ratio must be greater than zero.
if (drawableAspectRatio > 0 && viewWidth > 0) {
float targetHeight = viewWidth / drawableAspectRatio;
setMeasuredDimension((int) viewWidth, (int) targetHeight);
return; // Already set the measured dimension.
}
}
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
I am reopening a question that was asked two years (and yes, I tried all the answers but there was no joy). The question asked two years ago: ImageButton: Force square icon (height = WRAP_CONTENT, width = ?)
I am faced with the same situation where I am attempting to align a Button (with a background image) with an EditText. The following is what I am trying to accomplish:
The RelativeLayout I am using is:
<EditText
android:id="#+id/search_entry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/search_layout_height"
android:layout_marginLeft="#dimen/search_layout_left"
android:padding="#dimen/small_padding"
android:background="#drawable/search_box"
android:inputType="text|number"
android:textSize="#dimen/small_textsize"
android:hint="#string/search_for_hint"
android:textColorHint="#color/mdgray"
android:imeOptions="actionSend" />
<Button
android:id="#+id/search_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#id/search_entry"
android:layout_alignTop="#id/search_entry"
android:layout_toRightOf="#id/search_entry"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:background="#drawable/search_btn" />
However, what I am ending up with is:
As you can see, it wants to stretch laterally.
Thoughts on how to make sure the button stays square?
You can use an ImageButton and make a class that extends ImageButton that will override the onMeasure method of it where in there you can make the background as a square using its background image's minimum size as the width and hieght to form a perfect square that will never deform the image.
example:
public class ImageViewPefectSquare extends ImageButton{
public ImageViewPefectSquare(Context context) {
super(context);
}
public ImageViewPefectSquare(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ImageViewPefectSquare(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int measuredWidth = getDefaultSize(getSuggestedMinimumWidth(),
widthMeasureSpec);
int measuredHeight = getDefaultSize(getSuggestedMinimumHeight(),
heightMeasureSpec);
// Ensure this view is always square.
int min = Math.min(measuredHeight, measuredWidth);
setMeasuredDimension(min, min);
}
}
what it is doing is that it will calculate for the minimum size of the image and use it as the width and height to make it a perfect square.
Use it as xml:
<com.youpackage.ImageViewPefectSquare
android:id="#+id/search_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#id/search_entry"
android:layout_alignTop="#id/search_entry"
android:layout_toRightOf="#id/search_entry"
android:adjustViewBounds="true"
android:scaleType="centerInside"
android:background="#drawable/search_btn" />
This is because you are using Wrap_content you need to instead use an actual value if you want to keep an aspect ratio 1:1. If you want it to scale properly for all devices I would say in java code define the screen size and use the to calculate the width and height of the image for example:
button.setWidth(screenWidth/6);
button.setHeight(screenWidth/6);
I want the width of an ImageView to be set by the parent and the height should be aspect proportional. The reasons for this is that next is shown a TextView that I want to place just under the ImageView.
I can get image to show correctly using
android:layout_width="fill_parent"
android:layout_height="fill_parent"
however the ImageView height become the parent height which is much larger than that of the shown stretched image. One idea was to make parent smaller vertically, but.. there I don't yet know the stretched image size.
The following doesn't work because a small image is not filled up horizontally.
android:layout_width="fill_parent"
android:layout_height="wrap_content"
Messing around with
android:layout_height="wrap_content"
for the RelativeLayout surrounding it all does not help. Also tried FrameLayout and LinearLayout and failed.
Any ideas?
You have to set adjustViewBounds to true.
imageView.setAdjustViewBounds(true);
There is two case if your actual image size is equal or grater than your ImageView width and heigh then you can use adjustViewBounds property and if your actual image size is less than ImageView width and height than use scaleType property to shown image in ImageView based on your requirement.
1.Actual image size is equal or grater than ImageView required width and height.
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="#drawable/ic_launcher"/>
2.Actual image size is less than ImageView required width and height.
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:src="#drawable/ic_launcher"/>
So I have had the same issue more than once and looking through the existing stackoverflow answers have realised that no answer gives a perfect explanation for the real confusion regarding a solution to this problem. So here you go:
API 17+
imageView.setAdjustViewBounds(true);
OR (in XML)
android:adjustViewBounds="true"
solves the issue, it works no matter the actual size of the image resource, i.e. it will scale your image up or down to the desired size you have in your layout.
Below API 17
Below API 17 android:adjustViewBounds="true" will only work for shrinking an image, not growing, i.e. if the actual height of the image source is smaller than the dimensions you are trying to achieve in your layout, wrap_content will use that smaller height and not scale 'up' (enlarge) the image as you desire.
And so for API 17 and lower, you have no choice but to use a custom ImageView to achieve this behaviour. You could either write a custom ImageView yourself or use a library, that has already done that job.
Using a library
There is probably more than one library that fixes this issue, one of them is:
compile 'com.inthecheesefactory.thecheeselibrary:adjustable-imageview:1.0.0'
which is used like this:
<com.inthecheesefactory.thecheeselibrary.widget.AdjustableImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="#drawable/your_drawable"/>
Using a custom View
alternatively to using an existing library, you could write a custom view yourself, e.g.:
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.ImageView;
public class ScalableImageView extends ImageView {
boolean adjustViewBounds;
public ScalableImageView(Context context) {
super(context);
}
public ScalableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ScalableImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void setAdjustViewBounds(boolean adjustViewBounds) {
this.adjustViewBounds = adjustViewBounds;
super.setAdjustViewBounds(adjustViewBounds);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Drawable drawable = getDrawable();
if (drawable == null) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
if (adjustViewBounds) {
int drawableWidth = drawable.getIntrinsicWidth();
int drawableHeight = drawable.getIntrinsicHeight();
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY && widthMode != MeasureSpec.EXACTLY) {
int height = heightSize;
int width = height * drawableWidth / drawableHeight;
if (isInScrollingContainer())
setMeasuredDimension(width, height);
else
setMeasuredDimension(Math.min(width, widthSize), Math.min(height, heightSize));
} else if (widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) {
int width = widthSize;
int height = width * drawableHeight / drawableWidth;
if (isInScrollingContainer())
setMeasuredDimension(width, height);
else
setMeasuredDimension(Math.min(width, widthSize), Math.min(height, heightSize));
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
private boolean isInScrollingContainer() {
ViewParent parent = getParent();
while (parent != null && parent instanceof ViewGroup) {
if (((ViewGroup) parent).shouldDelayChildPressedState()) {
return true;
}
parent = parent.getParent();
}
return false;
}
}
... which you would use as follows (XML):
<com.YOUR_PACKE_NAME.ScalableImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="#drawable/your_drawable" />
This was the only way I could get it working, to have the second ImageView in the center and smaller than the first ImageView, and the TextView under the second ImageView.
Unfortunately, it uses fixed "200dp" image size on the second ImageView, so it does not look the same on different sized devices.
It also destroys my ViewFlipper, since any Layout I tried around the second ImageView and the TextView makes them move or resize.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="#+id/imageview1"
android:contentDescription="#string/desc"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/background" />
<ImageView
android:id="#+id/imageview2"
android:layout_centerInParent="true"
android:contentDescription="#string/desc"
android:layout_height="200dp"
android:layout_width="200dp"
android:adjustViewBounds="true"
android:src="#drawable/image2" />
<TextView
android:id="#+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#id/imageview2"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:gravity="center"
android:textSize="26sp"
android:textColor="#333"
android:background="#fff"
android:text="this is the text under the image right here"
/>
</RelativeLayout>
I have a ListView whose items are ImageViews, for the sake of discussion. I want the image to scale to the width of the ListView's rows, and maintain it's aspect ratio. here's a simplified version of the ListView's item layout,
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="4dp" >
<FrameLayout
android:id="#+id/page_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="visible" >
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="#drawable/some_image" />
</FrameLayout>
</FrameLayout>
</LinearLayout>
the ImageView's width is match_parent, and all ancestors of it are the same. Layout designer shows that the ImageView's dimensions span the entire width, but the image inside does not.
The image is scaling correctly. The problem is that the height of the list view row is such that the width can't scale to the right size. If I use fitXY, it does scale the width, but then the aspect ratio is incorrect.
Any ideas?
I couldn't find any way to accomplish this without creating a custom view. in a nutshell, the custom view sets it's own dimensions to the real (not scaled) dimensions of the drawable behind it.
public class ResizableImageView extends ImageView {
public static interface OnSizeChangedListener {
void onSizeChanged(int width, int height);
}
private OnSizeChangedListener onSizeChangedListener = null;
public ResizableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = width * getDrawable().getIntrinsicHeight() / getDrawable().getIntrinsicWidth();
setMeasuredDimension(width, height);
if (onSizeChangedListener != null) {
onSizeChangedListener.onSizeChanged(width, height);
}
}
public void setOnSizeChangedListener(OnSizeChangedListener listener) {
this.onSizeChangedListener = listener;
}
}
In my case I needed to obtain the resized value in order to size the other views, hence the listener interface.
If what you want is to maintain the aspect ratio, according to the Android API Guide, I think that you have to change android:scaleType="fitCenter" for android:scaleType="centerInside" or maybe android:scaleType="centerCrop" as fitCenter doesn't maintain the aspect ratio of the image.
I download image and set it as a screen background dynamically using Imageview. I have tried ScaleType, to scale the image.
If image height is larger than width then ScaleTypes fitStart, fitEnd and fitCenter don't work. Android scale down the photo and fit it based on the height, but I see some extra blank space as part of the width.
I want to scale down the photo based on the width so that it fits the width and I don't care if there's some extra blank space as part of the height or if height is too long it is fine if it's going out of the view(if that's possible?).
ScaleType.XY scale the photo and fit everything in the ImageView and doesn't care about image height/weight ratio.
<ImageView
android:id="#+id/background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="fitStart"
/>
I ended up using this code:
<ImageView
android:id="#+id/background"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:src="#drawable/name"
/>
Make sure you set the image using src instead of background.
android:adjustViewBounds="true" does the job!
This elegant solution found here will work like a charm for you.
Basically you just have to create a small class that extends ImageView and simply override the onMeasure method to adjust the width and height as you want. Here it scales to fit width by using:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = width * getDrawable().getIntrinsicHeight() / getDrawable().getIntrinsicWidth();
setMeasuredDimension(width, height);
}
You would use this special ImageView like this:
<your.activity.package.AspectRatioImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical"
android:src="#drawable/test" />
There is a simple method if you simply want to fill the width of screen and have height proportional (and know the ratio of the image) you can do this in OnCreate():
setContentView(R.layout.truppview_activity);
trupImage = (ImageView) findViewById(R.id.trupImage);
Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics();
display.getMetrics(outMetrics);
float scWidth = outMetrics.widthPixels;
trupImage.getLayoutParams().width = (int) scWidth;
trupImage.getLayoutParams().height = (int) (scWidth * 0.6f);
Where 0.6 is the ratio adjustment (you could also calc automatically of course if you know the w & h of image).
PS:
Here is the XML side:
<ImageView
android:id="#+id/trupImage"
android:layout_width="match_parent"
android:background="#color/orange"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
if you want to fit the image whole parent block
it will stretch the image
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
And if you want to fit image whole parent with original ratio of image
it will crop out some part of image
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
This works for me.
Create a class extends ImageView
package com.yourdomain.utils;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
public class ResizableImageView extends ImageView {
public ResizableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Drawable d = getDrawable();
if (d != null) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = (int) Math.ceil((float) width * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth());
setMeasuredDimension(width, height);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}
In xml use the following instead of ImageView
<com.yourdomain.utils.ResizableImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/test" />
I think you cant do it only with XML, you need to resize yourself, the bitmap
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
try {
((ImageView) findViewById(R.id.background))
.setImageBitmap(ShrinkBitmap(width));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
then
private Bitmap ShrinkBitmap(int width)
throws FileNotFoundException {
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.img, bmpFactoryOptions);
int widthRatio = (int) android.util.FloatMath
.ceil(bmpFactoryOptions.outWidth / (float) width);
bmpFactoryOptions.inSampleSize = widthRatio;
if (bmpFactoryOptions.inSampleSize <= 0)
bmpFactoryOptions.inSampleSize = 0;
bmpFactoryOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
bmpFactoryOptions.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.img, bmpFactoryOptions);
return bitmap;
}
And the layout
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/background"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>