How to override standart padding in CardView while

2020-07-17 16:11发布

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.

enter image description here

<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

3条回答
疯言疯语
2楼-- · 2020-07-17 16:51

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

查看更多
Anthone
3楼-- · 2020-07-17 16:56

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.

查看更多
姐就是有狂的资本
4楼-- · 2020-07-17 17:04

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?

查看更多
登录 后发表回答