I would like my ImageView
to scale in a particular fashion:
ImageView
A picture speaks louder than a 1000 words, so here is a representation of how I want my ImageView
to behave. Suppose it has a fixed height of say 100dp and suppose its width is match_parent
.
Note that
CROP_CENTER
.ImageView
height, behaving like FIT_CENTER
I suspect I need scaleType:matrix
, but after that I'm lost. How can I make sure an image fits Y, but crops X?
Bookmark this question.
Tap the image you want to adjust. You can adjust the size of an image or rotate it: Resize: Touch and drag the squares along the edges. Rotate: Touch and drag the circle attached to the image.
android:adjustViewBounds—If set to true, the attribute adjusts the bounds of the ImageView control to maintain the aspect ratio of the image displayed through it.
In xml, use:
android:scaleType="centerCrop"
android:adjustViewBounds="true"
from & thanks to: https://stackoverflow.com/a/15600295/2162226
With a little help from my friends Carlos Robles and pskink, came up with the following custom ImageView
:
public class FitYCropXImageView extends ImageView {
boolean done = false;
@SuppressWarnings("UnusedDeclaration")
public FitYCropXImageView(Context context) {
super(context);
setScaleType(ScaleType.MATRIX);
}
@SuppressWarnings("UnusedDeclaration")
public FitYCropXImageView(Context context, AttributeSet attrs) {
super(context, attrs);
setScaleType(ScaleType.MATRIX);
}
@SuppressWarnings("UnusedDeclaration")
public FitYCropXImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setScaleType(ScaleType.MATRIX);
}
private final RectF drawableRect = new RectF(0, 0, 0,0);
private final RectF viewRect = new RectF(0, 0, 0,0);
private final Matrix m = new Matrix();
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (done) {
return;//Already fixed drawable scale
}
final Drawable d = getDrawable();
if (d == null) {
return;//No drawable to correct for
}
int viewHeight = getMeasuredHeight();
int viewWidth = getMeasuredWidth();
int drawableWidth = d.getIntrinsicWidth();
int drawableHeight = d.getIntrinsicHeight();
drawableRect.set(0, 0, drawableWidth, drawableHeight);//Represents the original image
//Compute the left and right bounds for the scaled image
float viewHalfWidth = viewWidth / 2;
float scale = (float) viewHeight / (float) drawableHeight;
float scaledWidth = drawableWidth * scale;
float scaledHalfWidth = scaledWidth / 2;
viewRect.set(viewHalfWidth - scaledHalfWidth, 0, viewHalfWidth + scaledHalfWidth, viewHeight);
m.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.CENTER /* This constant doesn't matter? */);
setImageMatrix(m);
done = true;
requestLayout();
}
}
If you use scaleType:matrix
you will need to create your own Matrix and asign it to the view by means of setImageMatrix(Matrix)
or manually modify the matrix at hen onMEasure method of a customImageView.
public class MyImageView extends ImageView {
boolean done=false;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (done)
return;
final Drawable d = getDrawable();
final int drawableW = d.getIntrinsicWidth();
final int drawableH = d.getIntrinsicHeight();
float ratio = drawableW / drawableH;
//int width = getMeasuredWidth();
int height = getMeasuredHeight();
float scale=height/drawableH;
Matrix m = getImageMatrix();
float[] f = new float[9];
m.getValues(f);
f[Matrix.MSCALE_X]=scale;
f[Matrix.MSCALE_Y]=scale;
m.setValues(f);
done = true;
requestLayout();
}
}
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
LayoutParams params;
final ImageView iv0 = new ImageView(this);
//iv0.setBackgroundColor(0xffff0000);
params = new LayoutParams(LayoutParams.MATCH_PARENT, 100);
ll.addView(iv0, params);
final ImageView iv1 = new ImageView(this);
//iv1.setBackgroundColor(0xff00ff00);
params = new LayoutParams(60, 100);
ll.addView(iv1, params);
setContentView(ll);
Runnable action = new Runnable() {
@Override
public void run() {
Drawable d = getResources().getDrawable(R.drawable.layer0);
int dw = d.getIntrinsicWidth();
int dh = d.getIntrinsicHeight();
RectF src = new RectF(0, 0, dw, dh);
ImageView[] iviews = {iv0, iv1};
for (int i = 0; i < iviews.length; i++) {
ImageView iv = iviews[i];
iv.setImageDrawable(d);
iv.setScaleType(ScaleType.MATRIX);
float h = iv.getHeight();
float w = iv.getWidth();
float cx = w / 2;
float scale = h / dh;
float deltaw = dw * scale / 2;
RectF dst = new RectF(cx - deltaw, 0, cx + deltaw, h);
Matrix m = new Matrix();
m.setRectToRect(src, dst, ScaleToFit.FILL);
iv.setImageMatrix(m);
}
}
};
iv1.post(action);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With