Question

I searched carefully here and in other internets, but have not find solution for me. I have ImageView of fixed size. I need to show some bitmaps, loaded in runtime. All of them has different size and aspect ratio. For example: while ImageView is 480x270px bitmaps could be 160x90, 1600x500, 50x100 and so on. And i want them be centered in and fit to ImageView. And rounded corners.

Two most popular approaches is (1) process bitmap and (2) modify draw-stage in imageView subclass.

Romain Guy extends Drawable and use drawRoundRect method in Canvas. Unfortunately his solution does not applied FIT_CENTER, though rounded line is pretty sharp.

There is also variant to process bitmap, render it to another bitmap and get rounded. Set it as source - get centered and fitted ImageView. But in this case rounded rect exists only in bitmap's pixels grid. It could be very blurry if bitmap is small.

And last one solution, which suits best for me, but which need to be upgraded too. We can tune canvas to contain clipPath along it's border. But centered bitmap with 16/5 aspect ratio wont be rounded - it will be drawn outside of cliPath.

Was it helpful?

Solution

So, i completed answer from here so it can solve my problem.

XML:

    <RoundedThumb
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

JAVA:

public class RoundedThumb extends ImageView {

private final float radius = getContext().getResources().getDimension(R.dimen.corner_radius);
private RectF mSrcRect = new RectF();
private RectF mDstRect = new RectF();
private Path mClipPath = new Path();

public RoundedThumb(Context context) {
    super(context);
}

public RoundedThumb(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public RoundedThumb(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

protected void onDraw(Canvas canvas) {
    if (getDrawable() != null && getImageMatrix() != null) {
        mSrcRect.set(0, 0, getDrawable().getIntrinsicWidth(), getDrawable().getIntrinsicHeight());
        getImageMatrix().mapRect(mDstRect, mSrcRect);
        mClipPath.reset();
        mClipPath.addRoundRect(mDstRect, radius, radius, Path.Direction.CW);
        canvas.clipPath(mClipPath);
    }
    super.onDraw(canvas);
}
}

And usage:

thumb.setScaleType(ImageView.ScaleType.FIT_CENTER);
Bitmap thumbnail = BitmapFactory.decodeFile(path);
thumb.setImageBitmap(thumbnail);

So, now rect for Path transformed just like BitmapDrawable inside of ImageView and always circumscribed exactly around any bitmap in ImageView. What is important for me - ImageView still has aspectRatio 16/9 and takes it's place, defined in resources. But bitmap has rounded borders, while it is not modified.

UPD1: I am a little bit confused: unfortunately on some devices clipPath method has no effect (SII) or even crashes (old asus transformer). Can be fixed completely by setting hardwareAccelerated to false. But, damn, that's not good =/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top