Reputation: 790
I have an ImageView with scaleType="fitCenter"
and layout_width="match_parent"
, so I expect the image inside it to scale and inflate all view.
Layout file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:layout_marginTop="20dp"
android:gravity="center"
android:orientation="vertical">
<FrameLayout
android:layout_width="250dp"
android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:src="@drawable/border" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="6dp">
<ImageView
android:id="@+id/myImageView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="@drawable/aaa"
android:transitionName="image" />
<!-- Some other views... -->
</RelativeLayout>
</FrameLayout>
The problem begins when images are too small (for example, 50x50 px) and it doesn't work as expected on all devices.
The image below shows the difference between API 16 and 22.
Any ideas how to resolve this?
Upvotes: 1
Views: 1066
Reputation: 5375
The problem is not with your code but with the way android:adjustViewBounds
work. This is documented in setAdjustViewBounds
method of ImageView.
Note:If the application targets API level 17 or lower, adjustViewBounds will allow the drawable to shrink the view bounds, but not grow to fill available measured space in all cases.
Based on the post Correct the ImageView's adjustViewBounds behaviour on API Level 17 and below with AdjustableImageView by nuuneoi, the possible solution for this issue is to use custom AdjustableImageView
.
Code:
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;
/**
* Created by nuuneoi on 2/17/15 AD.
*/
public class AdjustableImageView extends ImageView {
boolean mAdjustViewBounds;
public AdjustableImageView(Context context) {
super(context);
}
public AdjustableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AdjustableImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void setAdjustViewBounds(boolean adjustViewBounds) {
mAdjustViewBounds = adjustViewBounds;
super.setAdjustViewBounds(adjustViewBounds);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Drawable mDrawable = getDrawable();
if (mDrawable == null) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
if (mAdjustViewBounds) {
int mDrawableWidth = mDrawable.getIntrinsicWidth();
int mDrawableHeight = mDrawable.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) {
// Fixed Height & Adjustable Width
int height = heightSize;
int width = height * mDrawableWidth / mDrawableHeight;
if (isInScrollingContainer())
setMeasuredDimension(width, height);
else
setMeasuredDimension(Math.min(width, widthSize), Math.min(height, heightSize));
} else if (widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) {
// Fixed Width & Adjustable Height
int width = widthSize;
int height = width * mDrawableHeight / mDrawableWidth;
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 p = getParent();
while (p != null && p instanceof ViewGroup) {
if (((ViewGroup) p).shouldDelayChildPressedState()) {
return true;
}
p = p.getParent();
}
return false;
}
}
Upvotes: 4
Reputation: 9050
If you use fitXy
the image fills the view in both dimensions, disregarding its aspect ratio. This will undoubtedly cause distortion.
Another option is centerCrop
. This scale type will rescale the image until both dimensions x or y are greater or equal to the container while preserving aspect ratio. The result will be centered inside the view.
fitCenter
would be the opposite of centerCrop. It scales the image until at least one dimension x or y is smaller or equal to the view.
That said, the behavior that you show in the screenshots has more to do with screen sizes, not api level.
Upvotes: 0
Reputation: 17140
Use android:scaleType="fitXY"
to Scale the image using FILL that you are looking for.
Upvotes: 0