首页 > 解决方案 > Android CardView 圆角在 27 之前在 Android API 上被破坏

问题描述

我在具有圆角的父 CardView 中嵌入了卡片视图(我将此父卡片视图命名为 CV1)。当我滚动CV1的内容时,子cardview与CV1重叠并取消了CV1的圆角(如视频中的箭头所示),另一方面TextView,ImageView被很好地裁剪,我们总是看到圆角的地图。请参阅:threadvintage:注意:这只发生在 Android API <= 27 的版本上,在 APIs> 28 上一切都很好。

即使我添加app:cardPreventCornerOverlap="true"app:cardUseCompatPadding="true"

下面的代码

<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
fibe:cardCornerRadius="15dp"
android:layout_margin="32dp">

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        
        <include layout="@layout/item_list" />
        <include layout="@layout/item_list" />
        <include layout="@layout/item_list" />
        <include layout="@layout/item_list" />
        <include layout="@layout/item_list" />
        <include layout="@layout/item_list" />
        <include layout="@layout/item_list" />
        <include layout="@layout/item_list" />
    </LinearLayout>
</ScrollView>
</androidx.cardview.widget.CardView>

视频可在此处获得。

使用 Android API 24 在平板电脑上渲染:我们这里有错误

使用 Android API 28 在平板电脑上渲染:一切都很好

更新 1:item_list 布局代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="216dp"
    android:layout_height="match_parent"
    android:layout_marginStart="16dp"
    android:orientation="vertical">

    <androidx.cardview.widget.CardView
        style="@style/RoundedCornersContentItem"
        android:layout_width="match_parent"
        android:layout_height="148dp"
        app:cardElevation="0dp"
 app:cardBackgroundColor="@color/content_item_badge_background"/>

    <TextView
        style="@style/FlowPanelHeaderTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:text="Very long title for my card" />

</LinearLayout>

标签: androidandroid-layoutandroid-cardview

解决方案


这在 API 27 及以下版本中肯定被破坏了。这似乎是一个已知问题,但我没有看到任何解决方法。

以下布局,根据您的布局稍作修改,如果有人想看一下,将重现该问题。

activity_main.xml

<androidx.cardview.widget.CardView 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="32dp"
    app:cardCornerRadius="15dp">

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

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/holo_blue_light"
            android:orientation="vertical">

            <include layout="@layout/item_list" />

            <include layout="@layout/item_list" />

            <include layout="@layout/item_list" />

            <include layout="@layout/item_list" />

            <include layout="@layout/item_list" />

            <include layout="@layout/item_list" />

            <include layout="@layout/item_list" />

            <include layout="@layout/item_list" />
        </LinearLayout>
    </ScrollView>
</androidx.cardview.widget.CardView>

item_list.xml

<androidx.cardview.widget.CardView 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="32dp"
    app:cardCornerRadius="15dp">

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

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/holo_blue_light"
            android:orientation="vertical">

            <include layout="@layout/item_list" />

            <include layout="@layout/item_list" />

            <include layout="@layout/item_list" />

            <include layout="@layout/item_list" />

            <include layout="@layout/item_list" />

            <include layout="@layout/item_list" />

            <include layout="@layout/item_list" />

            <include layout="@layout/item_list" />
        </LinearLayout>
    </ScrollView>
</androidx.cardview.widget.CardView>

这是 API 27 模拟器上的演示:

在此处输入图像描述

我不能确切地说出问题是什么,奇怪的是嵌套的CardView覆盖了外部CardView的角落,而TextView尊重这些角落。

代替彻底修复,一种解决方法是创建一个自定义CardView来完成它自己的角剪裁。这是这样一个自定义视图:

MyCardView.kt

类 MyCardView @JvmOverloads 构造函数(上下文:上下文,attrs:AttributeSet?= null):CardView(上下文,attrs){

    private lateinit var mRectF: RectF
    private val mPath = Path()
    private var mCornerRadius = 0f

    init {
        val a = context.obtainStyledAttributes(
            attrs, R.styleable.CardView, 0,
            R.style.CardView
        )
        mCornerRadius = a.getDimension(androidx.cardview.R.styleable.CardView_cardCornerRadius, 0f)
        a.recycle()
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        mRectF = RectF(0f, 0f, w.toFloat(), h.toFloat())
        resetPath()
    }

    override fun draw(canvas: Canvas) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
            canvas.withClip(mPath) {
                super.draw(canvas)
            }
        }
    }

    private fun resetPath() {
        mPath.apply {
            reset()
            addRoundRect(mRectF, mCornerRadius, mCornerRadius, Path.Direction.CW)
            close()
        }
    }
}

这是在同一个 API 27 模拟器上使用自定义CardView的演示:

在此处输入图像描述


推荐阅读