25

Here are two pictures.

on Lollipop: on Lollipop:

on Pre-Lollipop: on Pre-Lollipop

we can see that it's just close to the screen side on Lollipop. that's what I want. but on the Pre-Lollipop device, it has extra margin to the screen edge. do you guys have any experience ? thank you.

here is the layout xml:

<android.support.v7.widget.CardView
        android:id="@+id/card_title_schedule"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_centerVertical="true"
        app:cardCornerRadius="0dp"
        app:cardBackgroundColor="@color/colorAccent"
        >
Jaden Gu
  • 9,143
  • 3
  • 23
  • 26

7 Answers7

26

So here it goes perfectly fine on Kitkat, samsung device to be precise.

I tried card_view:cardUseCompatPadding="true" but no avail. Didn't work!

Then I discovered from a stackoverflow post this card_view:cardPreventCornerOverlap="false" and VOILA! Worked! There were no round corners (Since, I wanted none as the Card has an Image background).

The moral is, an extra padding is because of those tiny round corners which, need to be disabled. Basically that is not a flaw rather a Design constraint!

ORIGINAL SOF REPLY

Image: Notice that top corners are edges (A view which has colour and an image in background) while bottom has just TextViews and no backgrounds hence, the round corners. That means if a view is requesting match_parent inside the CardView, card_view:cardPreventCornerOverlap="false" will allow that to be taken up, on the affected corners.

enter image description here

Community
  • 1
  • 1
sud007
  • 5,824
  • 4
  • 56
  • 63
  • It does works in these support library by changing it to false. I think it may be that google has fixed it silently. – Jaden Gu Aug 22 '16 at 21:56
  • Thanks; this made the problem much less noticeable. However, on my Sony Xperia M (Android 4.1.2), there was still one or two pixels of margin/padding around the `cardView`. – Sam Apr 22 '17 at 23:19
  • This worked for me: https://android.jlelse.eu/using-full-width-cards-to-maximize-content-f739cb863ce8 – Sagar Patel Nov 15 '17 at 11:02
  • But this also defeats one of two main purposes of a CardView, one being the shadow that you kept, and the other being rounded corners no matter which views are inside. Unfortunately, I need the rounded corners, as well as the shadow, so this won't fix it for me. – milosmns Sep 12 '19 at 08:02
19

Before L, CardView adds padding to its content and draws shadows to that area. This padding amount is equal to maxCardElevation + (1 - cos45) * cornerRadius on the sides and maxCardElevation * 1.5 + (1 - cos45) * cornerRadius on top and bottom.

From the CardView reference here

Try setting a negative left margin on the CardView like this

<android.support.v7.widget.CardView
        android:id="@+id/card_title_schedule"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_centerVertical="true"
        app:cardCornerRadius="0dp"
        app:cardBackgroundColor="@color/colorAccent" 
        app:cardUseCompatPadding="true"
        android:layout_marginLeft="-2dp" />

You may need to adjust the margin to get the desired result.

PS, this is kind of a hack-y way to do it.

Shrayas
  • 6,784
  • 11
  • 37
  • 54
shemarcl
  • 190
  • 1
  • 4
  • 1
    thank you for your answer. you are right. I haven't noticed the "draws shadows to that area" .. Maybe the hack way is the only one so far. or else I should not use the CardView in this condition. – Jaden Gu Mar 20 '15 at 05:57
  • 1
    You're welcome. It's the only way I can think of right now. If you find a better way to draw shadows on pre-lollipop devices do let me know. **EDIT:** Here's something I ran into just now: https://github.com/dmytrodanylyk/shadow-layout I think it draws shadows in he same way though. Feel free to test it out. – shemarcl Mar 21 '15 at 09:22
17

I realise this has already been answered, but I'd like to add that in addition to card_view:cardPreventCornerOverlap="false", I also had to set CardView.setMaxCardElevation(0) to get rid of the margins on pre-Lollipop. Setting the elevation only to 0 did not work. I'm using support library v23.4.0.

okacat
  • 476
  • 5
  • 6
  • 7
    Thanks for **"setMaxCardElevation"** pointer. In my case To get rid of "extra" padding from all Edges _(Even when there were no corner radius on CardView or its children )_ I had to set these 3 (in xml): `app:cardMaxElevation="0dp" app:cardElevation="0dp" app:cardPreventCornerOverlap="false"`... Using **com.android.support:cardview-v7:25.2.0** – Vinay Vissh Mar 07 '17 at 14:41
  • 1
    I fixed with your comment. Thank you. – semih Apr 05 '18 at 13:10
13

Try with card_view:cardUseCompatPadding="true"

if we set this property to true then margin works same on all versions.

developer note

Add padding in API v21+ as well to have the same measurements with previous versions.

source docs

Sanket Kachhela
  • 10,861
  • 8
  • 50
  • 75
5

If the Android 4 (pre-lollipop) behavior is desired, adding app:cardUseCompatPadding="true" to the CardView should fix it.

If the Android 5+ behavior is desired (which is actually the right behavior of card views according to material guidelines), the exact same thing can not be easily achieved. I usually use this fix to avoid defining multiple layout files and have reasonable output on all devices:

<android.support.v7.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:contentPaddingRight="@dimen/fix_cardview"
    app:contentPaddingLeft="@dimen/fix_cardview"
    app:contentPaddingTop="@dimen/fix_cardview_vertical"
    app:contentPaddingBottom="@dimen/fix_cardview_vertical" />

and in normal values/dimens.xml file we should have:

<dimen name="fix_cardview">-8dp</dimen>
<dimen name="fix_cardview_vertical">-12dp</dimen>

and in values-v21/dimens.xml:

<dimen name="fix_cardview">0dp</dimen>
<dimen name="fix_cardview_vertical">0dp</dimen>

note that the numbers -8dp and -12dp might have to be adjusted for your layout, since they depend on elevation, etc.

This is only a work-around to avoid ugly paddings in Android 4 views, without using different views in different layout files (which usually makes the code more difficult to maintain)

Iman Akbari
  • 2,167
  • 26
  • 31
4

To solve the "shadow space" issue for PRE-L versions, you can dynamically update the CardView margin by negative values to compensate the space.

To get the actual shadow space:

shadowSpaceLeft = getPaddingLeft() - getContentPaddingLeft();

To fix the margin:

layoutParams.leftMargin -= shadowSpaceLeft;

This will work for all Android versions since we are getting the padding values and the contentPadding values dynamically.

For example, here is a class that does it whenever we set new layout params:

public class NoPaddingCardView extends CardView {

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

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

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

    private void init() {
        // Optional: Prevent pre-L from adding inner card padding 
        setPreventCornerOverlap(false);
        // Optional: make Lollipop and above add shadow padding to match pre-L padding
        setUseCompatPadding(true);
    }

    @Override
    public void setLayoutParams(ViewGroup.LayoutParams params) {
        // FIX shadow padding
        if (params instanceof MarginLayoutParams) {
            MarginLayoutParams layoutParams = (MarginLayoutParams) params;
            layoutParams.bottomMargin -= (getPaddingBottom() - getContentPaddingBottom());
            layoutParams.leftMargin -= (getPaddingLeft() - getContentPaddingLeft());
            layoutParams.rightMargin -= (getPaddingRight() - getContentPaddingRight());
            layoutParams.topMargin -= (getPaddingTop() - getContentPaddingTop());
        }

        super.setLayoutParams(params);
    }
}
Eyal Biran
  • 5,656
  • 1
  • 28
  • 29
0

just add this in your code for pre lollipop versions:

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
    {
        cardView.setMaxCardElevation(0f);
        cardView.setPreventCornerOverlap(false);
    }
AREF
  • 125
  • 10