Appcompat CardView and Picasso no rounded Corners
Asked Answered
A

5

19

I do not know where Exactly i Should Adress this issue, if it is my fault, there is something in the Picasso Lib Wrong or in the Cardview Library.

Basicly i have a CardView containing an image (Full Card Covered) and A TextView overlaying.

When Running the Code on a Android 5.0 Device, everything works fine and the Image Gets its Rounded Corners.

However if i run it on a pre 5.0 device, the image overlaps the Cardlayout and does not have rounded Corners.

You can See a Comparison on this Image: comparison

Here are some Code Snippets:

layout_row.xml

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/pandaImage"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        android:scaleType="centerCrop" />

    <TextView
        android:id="@+id/pandaName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/pandaImage"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:background="@color/photo_tint"
        android:clickable="true"
        android:focusable="true"
        android:gravity="center"
        android:textColor="@android:color/white"
        android:textSize="24sp" />

</RelativeLayout>

And the Recycler Adapter Loading the Image:

@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
    Photo p = photos.get(i);
    Picasso.with(mContext).load(p.getUrl()).fit().into(viewHolder.mImage);
    viewHolder.mPandaName.setText(p.getTitle());
}
Anomalism answered 24/10, 2014 at 16:37 Comment(1)
What happens if you set the image as background for the card?Troupe
W
20

According to the docs, this as designed:

Due to expensive nature of rounded corner clipping, on platforms before L, CardView does not clip its children that intersect with rounded corners. Instead, it adds padding to avoid such intersection (See setPreventCornerOverlap(boolean) to change this behavior).

See the CardView docs for more info.

Watson answered 24/10, 2014 at 16:56 Comment(2)
when setting setPreventCornerOverlap(false) on pre L devices, the imageview exceeds the CardView and aligns with the shadow.. Any thoughts on that?Mary
@Mary I believe you are referencing this bug code.google.com/p/android/issues/detail?id=77821 my comment seems to fix the issue Pre-L. At least on the one device I've tested on.Tewell
C
20

As @kcoppock mentioned, this is by design.

Here is what I would do in this situation.

1) You can use Picasso Transformation interface to specify custom transformation for your image (in our case - image with rounded corners)

2) Apply this transformation to the Picasso request on pre-L devices

3) Since CardView adds some margin for the image - get rid of it on pre-L devices by calling setPreventOverlap(false)

Back to the code:

Custom transformation:

public class RoundedTransformation implements com.squareup.picasso.Transformation {
    private final int radius;
    private final int margin;

    public RoundedTransformation(final int radius, final int margin) {
        this.radius = radius;
        this.margin = margin;
    }

    @Override
    public Bitmap transform(final Bitmap source) {
        final Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));

        Bitmap output = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        canvas.drawRoundRect(new RectF(margin, margin, source.getWidth() - margin, source.getHeight() - margin), radius, radius, paint);

        if (source != output) {
            source.recycle();
        }

        return output;
    }

    @Override
    public String key() {
        return "rounded(radius=" + radius + ", margin=" + margin + ")";
    }
}

Picasso:

//feel free to play with radius to match your CardView
Picasso.with(mContext).load(p.getUrl()).transform(new RoundedTransformation(12, 0)).fit().into(viewHolder.mImage);
Coloratura answered 24/10, 2014 at 17:55 Comment(4)
setPreventOverlap(false) is a very important call whenever dealing with card backgrounds. Very good to have mentioned it here.Ultramicroscopic
great solution! how to only make the top corner rounded while keeping the bottom squared?Jorin
@Jorin unfortunately achieving one rounded corner effect takes a little bit more work than just calling one API. Usually it takes drawing in two passes. You can refer to similar questions on SOColoratura
@PavelDudka. I found a good solution here: github.com/wasabeef/picasso-transformations/blob/master/… It allows you to customize which corner to be rounded.Jorin
B
3

It works for me like this:

  1. Replace the ImageView with RoundedImageView (https://github.com/vinc3m1/RoundedImageView).
  2. Set the riv_corner_radius attribute on the RoundedImageView to be the same as CardView's corner.
  3. Set cardPreventCornerOverlap to false on the CardView (app:cardPreventCornerOverlap="false").
  4. It looks the same on L and pre-L now.
Bilge answered 7/1, 2016 at 3:42 Comment(0)
E
1

If you wish to have a global solution for that issue, you can use Carbon's CardView. It correctly clips its content to rounded corners on all devices back to Froyo. See the image:

enter image description here

Eddieeddina answered 1/10, 2015 at 13:15 Comment(0)
O
0

Use the code below.

Important: don't set background for ImageView in XML.

<android.support.v7.widget.CardView 
                                    android:layout_width="match_parent"
                                    android:layout_height="130dp"
                                    app:cardCornerRadius="5dp"
                                    app:cardElevation="0dp"
                                    app:cardUseCompatPadding="true">

    <RelativeLayout
        android:id="@+id/rl_target_marry"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/textView2"
        >

        <ImageView
            android:id="@+id/img_target_marry"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitXY"
            />
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:foreground="?attr/selectableItemBackground">

            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_gravity="right|center_vertical"
                android:layout_marginRight="16dp"
                android:text="Marry"
                android:textColor="@color/colorWhite"
                android:textSize="28sp"/>

        </FrameLayout>

    </RelativeLayout>
</android.support.v7.widget.CardView>
Orwin answered 24/6, 2017 at 4:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.