How to override standart padding in CardView while

2020-07-17 16:37发布

问题:

When I use cardUseCompatPadding to show shadow in my card view, top padding is bigger than left one. How to make both padding equal, because my ribbon looking not beautiful, it's bigger on top? Thanks.

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <!-- Green triangles for badge -->
    <FrameLayout
        android:id="@+id/ribbon_parts"
        android:layout_width="58dp"
        android:layout_height="58dp"
        android:background="@drawable/ic_ribbon_parts"
        android:visibility="gone"/>

<FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.CardView
            android:id="@+id/item_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:animateLayoutChanges="true"
            android:background="@color/red"
            android:clickable="true"
            android:foreground="?attr/selectableItemBackground"
            android:theme="@style/LightGrayHighlightTheme"
            card_view:cardBackgroundColor="@color/white"
            card_view:cardCornerRadius="4dp"
            card_view:cardElevation="2dp"
            card_view:cardPreventCornerOverlap="true"
            card_view:cardUseCompatPadding="true">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="130dp"
                android:animateLayoutChanges="true"
                android:orientation="horizontal"
                android:background="@color/blue"
                android:weightSum="3"> </LinearLayout>
</FrameLayout>

<!-- badge -->
<FrameLayout
        android:id="@+id/ribbon_main"
        android:layout_width="58dp"
        android:layout_height="58dp"
        android:background="@drawable/ic_ribbon_main"
        android:visibility="gone"/>

https://www.shutterstock.com/search/new+blue+corner+ribbon

回答1:

Taken from the documentation:

This may cause Cards to have different sizes between Lollipop and before Lollipop. If you need to align CardView with other Views, you may need api version specific dimension resources to account for the changes. As an alternative, you can set this flag to true and CardView will add the same padding values on platforms Lollipop and after.

Next, you can add the indentation you need by using the margin attribute

example.xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#2861">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.CardView
            android:id="@+id/item_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="1dp"
            android:layout_marginEnd="2dp"
            android:layout_marginStart="2dp"
            android:layout_marginTop="1dp"
            android:clickable="true"
            android:focusable="true"
            android:foreground="?attr/selectableItemBackground"
            card_view:cardBackgroundColor="@android:color/white"
            card_view:cardCornerRadius="4dp"
            card_view:cardElevation="2dp"
            card_view:cardPreventCornerOverlap="false"
            card_view:cardUseCompatPadding="true">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="130dp"
                android:animateLayoutChanges="true"
                android:orientation="horizontal"
                android:weightSum="3">

                <!-- Your code here -->

            </LinearLayout>

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

    </FrameLayout>

    <!-- badge -->
    <FrameLayout
        android:id="@+id/ribbon_main"
        android:layout_width="58dp"
        android:layout_height="58dp"
        android:layout_gravity="end"
        android:background="@drawable/corner_ribbon"
        android:visibility="visible" />

</FrameLayout>

Now it looks great on different versions of the API.

API 19 example

API 26 example

comparison side by side

In your project, you can use these settings for both CardView and FrameLayout (ribbon) to achieve the desired result.

example_2.xml:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#2861">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.CardView
            android:id="@+id/item_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginEnd="18dp"
            android:layout_marginTop="17dp"
            android:clickable="true"
            android:focusable="true"
            android:foreground="?attr/selectableItemBackground"
            card_view:cardBackgroundColor="@android:color/white"
            card_view:cardCornerRadius="4dp"
            card_view:cardElevation="2dp"
            card_view:cardPreventCornerOverlap="false"
            card_view:cardUseCompatPadding="true">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="130dp"
                android:animateLayoutChanges="true"
                android:orientation="horizontal"
                android:weightSum="3">

                <!-- Your code here -->

            </LinearLayout>

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

    </FrameLayout>

    <!-- badge -->
    <FrameLayout
        android:id="@+id/ribbon_main"
        android:layout_width="58dp"
        android:layout_height="58dp"
        android:layout_gravity="end"
        android:layout_marginEnd="16dp"
        android:layout_marginTop="16dp"
        android:background="@drawable/corner_ribbon"
        android:visibility="visible" />

</FrameLayout>

increased indentation



回答2:

You can't fix this. When cardUseCompatPadding flag is set, these methods are used to calculate padding on all API levels:

final static float SHADOW_MULTIPLIER = 1.5f;

static float calculateVerticalPadding(float maxShadowSize, float cornerRadius, addPaddingForCorners) {
   if (addPaddingForCorners) {
      return (float) (maxShadowSize * SHADOW_MULTIPLIER + (1 - COS_45) * cornerRadius);
   } else {
      return maxShadowSize * SHADOW_MULTIPLIER;
   }
}

static float calculateHorizontalPadding(float maxShadowSize, float cornerRadius, boolean addPaddingForCorners) {
   if (addPaddingForCorners) {
      return (float) (maxShadowSize + (1 - COS_45) * cornerRadius);
   } else {
      return maxShadowSize;
   }
}

addPaddingForCorners is true when you use card_view:cardPreventCornerOverlap="true".

Perhaps setting some layout_marginTop on ribbon_main and ribbon_parts will give you the desired effect?



回答3:

This is working for me, may be it would work for you too:

    float cardelevation = cardView.getMaxCardElevation();
    float cardradius = cardView.getRadius();
    double cardcos = Math.cos(Math.toRadians(45));

    int horizontalPadding = (int) (cardelevation + (1 - cardcos ) * cardradius);
    int verticalPadding = (int) (cardelevation * 1.5 + (1 - cardcos ) * cardradius);

Thank You.