'Make ImageView fit width of CardView
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.
<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.
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:
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.
Solution 1:[1]
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.
Solution 2:[2]
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:[3]
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:[4]
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:[5]
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:[6]
just add this line in to your CardView
app:cardPreventCornerOverlap="false"
and set ImageScale
on your ImageView
android:scaleType="fitXY"
Solution 7:[7]
I solved the problem with setting
1) app:cardUseCompatPadding="false"
2) setting a rounded imageView
background
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<corners android:radius="4dp" />
</shape>
Solution 8:[8]
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:[9]
Sometimes using Glide
instead of Picasso
for loading images also helps.
Solution 10:[10]
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:[11]
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:[12]
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:[13]
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);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow