Make ImageView fit width of CardView

AndroidImageviewAndroid AppcompatAndroid Cardview

Android Problem Overview


I have a CardView with rounded corners, I want to have an ImageView at the top like shown in the example taken from the material design guidelines below.

components_cards8.png

<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
     android:id="@+id/card_view"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     card_view:cardCornerRadius="4dp">

     <!-- ... --> 
 </android.support.v7.widget.CardView>

Then inside the CardView I have this ImageView

<ImageView
    android:id="@+id/imageView"
    android:layout_width="fill_parent"
    android:layout_height="150dp"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_alignParentTop="true"
    android:scaleType="centerCrop"
    android:src="@drawable/default_cover" />

If I have the card_view:cardCornerRadius set to 0dp then the ImageView fits the card like how I want it to.

image_1

However, the material design guidelines state that cards should have rounded corners, and not square corners.

The problem I have is when I set the card_view:cardCornerRadius to something other than 0dp, e.g. 4dp, then the following happens:

image_2

As can be seen, the ImageView does not fit into the CardView.

My question is, how can I make this ImageView fit to the layout of the CardView when it has rounded corners.

Android Solutions


Solution 1 - Android

You need to do 2 things :

  1. Call setPreventCornerOverlap(false) on your CardView.

  2. Put rounded Imageview inside CardView

About rounding your imageview, I had the same problem so I made a library that you can set different radii on each corners. There is one good library(vinc3m1’s RoundedImageView) that supports rounded corners on ImageView, but it only supports the same radii on every corners. But I wanted it to be rounded only top left and top right corners.

Finally I got the result what I wanted like below.

https://github.com/pungrue26/SelectableRoundedImageView

Rounded ImageView inside CardView

Solution 2 - Android

If your image size (width) is fixed with your ImageView width, you just only have to do is change your ImageView attribute to :

android:scaleType="fitXY"

That is. No additional image corner rounding, no busy work. Beside it efficient for app's performance.

Note : my suggestion may not appropriate for small image with large size ImageView.

Solution 3 - Android

CardView with ImageView

I got this to work by putting a RoundedImageView inside of a CardView. Also you need to set the appropriate CardView attributes.

https://medium.com/@etiennelawlor/layout-tips-for-pre-and-post-lollipop-bcb2e4cdd6b2#.kmb24wtkk

Solution 4 - Android

EDIT 2015/09/29

https://github.com/vinc3m1/RoundedImageView added support of rounding of selected corners

You can also use makeramen RoundedImageView https://github.com/vinc3m1/RoundedImageView, and to remove auto padding in CardView for pre LolliPop use

yourCardView.setPreventCornerOverlap(false);

And then set padding you needded to show shadows of cardview

Solution 5 - Android

Make a bck_rounded.xml in drawable folder. Give it a radius that is same as the card_view.

<?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android" >
        <corners android:radius="4dp" />
    </shape>

Apply inside your imageView: android:background="@drawable/bck_rounded"

Solution 6 - Android

just add this line in to your CardView

app:cardPreventCornerOverlap="false"

and set ImageScale on your ImageView

android:scaleType="fitXY"

Solution 7 - Android

I solved the problem with setting

  1. app:cardUseCompatPadding="false"

  2. setting a rounded imageView background

    http://schemas.android.com/apk/res/android" >

Solution 8 - Android

You have to Customize Your ImageView.

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;

public class RoundedImageView extends android.support.v7.widget.AppCompatImageView {
private Paint mPaint;
private Path mPath;
private Bitmap mBitmap;
private Matrix mMatrix;
private int mRadius = convertDpToPixel(10);
private int mWidth;
private int mHeight;
private Drawable mDrawable;

 public RoundedImageView(Context context) {
    super(context);
    init();
}

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

public RoundedImageView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
}

private void init() {
    mPaint = new Paint();
    mPaint.setColor(Color.WHITE);

    mPath = new Path();
}

public int convertDpToPixel(int dp) {
    DisplayMetrics displayMetrics = Resources.getSystem().getDisplayMetrics();
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, displayMetrics);
}

@Override
public void setImageDrawable(Drawable drawable) {
    mDrawable = drawable;
    if (drawable == null) {
        return;
    }
    mBitmap = drawableToBitmap(drawable);
    int bDIWidth = mBitmap.getWidth();
    int bDIHeight = mBitmap.getHeight();
    //Fit to screen.
    float scale;
    if ((mHeight / (float) bDIHeight) >= (mWidth / (float) bDIWidth)) {
        scale = mHeight / (float) bDIHeight;
    } else {
        scale = mWidth / (float) bDIWidth;
    }
    float borderLeft = (mWidth - (bDIWidth * scale)) / 2;
    float borderTop = (mHeight - (bDIHeight * scale)) / 2;
    mMatrix = getImageMatrix();
    RectF drawableRect = new RectF(0, 0, bDIWidth, bDIHeight);
    RectF viewRect = new RectF(borderLeft, borderTop, (bDIWidth * scale) + borderLeft, (bDIHeight * scale) + borderTop);
    mMatrix.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.CENTER);
    invalidate();
}

private Bitmap drawableToBitmap(Drawable drawable) {
    Bitmap bitmap;
    if (drawable instanceof BitmapDrawable) {
        BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
        if (bitmapDrawable.getBitmap() != null) {
            return bitmapDrawable.getBitmap();
        }
    }
    if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
        bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
    } else {
        bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    }
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);
    return bitmap;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    mWidth = MeasureSpec.getSize(widthMeasureSpec);
    mHeight = MeasureSpec.getSize(heightMeasureSpec);
    if ((mDrawable != null) && (mHeight > 0) && (mWidth > 0)) {
        setImageDrawable(mDrawable);
    }
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (mBitmap == null) {
        return;
    }
    canvas.drawColor(Color.TRANSPARENT);
    mPath.reset();
    mPath.moveTo(0, mRadius);
    mPath.lineTo(0, canvas.getHeight());
    mPath.lineTo(canvas.getWidth(), canvas.getHeight());
    mPath.lineTo(canvas.getWidth(), mRadius);
    mPath.quadTo(canvas.getWidth(), 0, canvas.getWidth() - mRadius, 0);
    mPath.lineTo(mRadius, 0);
    mPath.quadTo(0, 0, 0, mRadius);
    canvas.drawPath(mPath, mPaint);
    canvas.clipPath(mPath);
    canvas.drawBitmap(mBitmap, mMatrix, mPaint);
}
}

And in layout.xml

<com.example.widget.RoundedImageViewmageView
            android:id="@+id/ivProductImg"
            android:layout_width="match_parent"
            android:layout_height="150dp"
            android:scaleType="fitXY"
            />

Solution 9 - Android

Sometimes using Glide instead of Picasso for loading images also helps.

Solution 10 - Android

i try to using combination with cardview and imageview, so it will be like this :

    android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="160dp"
            android:layout_marginStart="16dp"
            android:layout_marginLeft="16dp"
            android:layout_marginTop="8dp"
            android:layout_marginEnd="16dp"
            android:layout_marginRight="16dp"
            app:cardCornerRadius="8dp"
            android:elevation="10dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView">
    
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/kmp_warna1"
                android:scaleType="centerCrop"/>
    
  </android.support.v7.widget.CardView>

I just adding the corner radius and elevation attribute on cardview, and scaletype = centerCrop on image view

Hope it will help

Solution 11 - Android

I tried using the MaskedCardView and worked for me

    class MaskedCardView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = R.attr.materialCardViewStyle
) : MaterialCardView(context, attrs, defStyle) {
    @SuppressLint("RestrictedApi")
    private val pathProvider = ShapeAppearancePathProvider()
    private val path: Path = Path()
    private val shapeAppearance: ShapeAppearanceModel = ShapeAppearanceModel.builder(
        context,
        attrs,
        defStyle,
        R.style.Widget_MaterialComponents_CardView
    ).build()

    private val rectF = RectF(0f, 0f, 0f, 0f)

    override fun onDraw(canvas: Canvas) {
        canvas.clipPath(path)
        super.onDraw(canvas)
    }

    @SuppressLint("RestrictedApi")
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        rectF.right = w.toFloat()
        rectF.bottom = h.toFloat()
        pathProvider.calculatePath(shapeAppearance, 1f, rectF, path)
        super.onSizeChanged(w, h, oldw, oldh)
    }
}

And use with it the attribute app:cardPreventCornerOverlap="false"

Solution 12 - Android

An updated solution that worked for me:

Go to your AndroidManifest.xml file and find the parent activity that is mentioned in the manifest file. Simply add the following line inside the activity tag. android:hardwareAccelerated="true" Just run the application again and see it has been resolved the corner radius issue.

Example:


        <activity
            android:name=".mvvm.activities.ABCDActivity"
            android:exported="true"
            android:hardwareAccelerated="true"
            android:configChanges="keyboardHidden|orientation|screenSize">

            <nav-graph android:value="@navigation/app_navigation"/>

        </activity>

Solution 13 - Android

You can use these codes to fit an image into circle cardview:

XML:

    <androidx.cardview.widget.CardView
        android:layout_width="70dp"
        android:layout_height="70dp"
        app:cardCornerRadius="35dp"
        android:shape="ring"
        android:thicknessRatio="1.9"
        app:cardPreventCornerOverlap="false">

        <ImageView
            android:id="@+id/imageView_id"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:scaleType="center"></ImageView>
    </androidx.cardview.widget.CardView>

NOTE: cardCornerRadius attribute usually equal 1/2 width and height of CardView

USE PICASSO TO LOAD ONLINE IMAGE:

    ImageView imv = findViewById(R.id.imageView_id);
    Picasso.get().load("link image").resize(300, 300).centerCrop().into(imv);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDanView Question on Stackoverflow
Solution 1 - Android김준호View Answer on Stackoverflow
Solution 2 - AndroidjamesView Answer on Stackoverflow
Solution 3 - AndroidEtienne LawlorView Answer on Stackoverflow
Solution 4 - AndroidPenzzzView Answer on Stackoverflow
Solution 5 - AndroidMohammed AliView Answer on Stackoverflow
Solution 6 - AndroidTarif ChakderView Answer on Stackoverflow
Solution 7 - AndroidS Ravi KumarView Answer on Stackoverflow
Solution 8 - AndroidVishal G. GohelView Answer on Stackoverflow
Solution 9 - AndroidBekView Answer on Stackoverflow
Solution 10 - AndroidCevin WaysView Answer on Stackoverflow
Solution 11 - AndroidMohamedHarmoushView Answer on Stackoverflow
Solution 12 - AndroidA S M SayemView Answer on Stackoverflow
Solution 13 - AndroidHoàng ViệtView Answer on Stackoverflow