Android 中的可变形视图

Shapeable View in Android

我们如何为 ConstraintLayout 应用 shapeAppearance 样式,因为 material 组件仅支持 Android.

中的以下组件


    <style name="Header_ShapeAppearance" parent="ShapeAppearance.MaterialComponents">
      <item name="cornerFamily">rounded</item>
      <item name="cornerSizeTopLeft">16dp</item>
      <item name="cornerSizeTopRight">16dp</item>
    </style>

这是适用于 CardView 的代码

<com.google.android.material.card.MaterialCardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="@dimen/mtrl_card_spacing"
    android:layout_marginTop="@dimen/mtrl_card_spacing"
    android:layout_marginRight="@dimen/mtrl_card_spacing"
    app:shapeAppearanceOverlay="@style/Header_ShapeAppearance">

这是支持 shapeAppearance 的 ConstraintLayout。

class ShapeableLayout : ConstraintLayout {

     private var shapeModel: ShapeAppearanceModel

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        setup(attrs, defStyleAttr)
    }

    private fun setup(attrs: AttributeSet?, defStyleAttr: Int) {
        shapeModel = ShapeAppearanceModel.builder(
            view.context, attrs, defStyleAttr, defStyleRes
        ).build()
    }

   fun applyShape() = apply {
        val bgDrawable = MaterialShapeDrawable(shapeModel)
        if (view.background is ColorDrawable) {
            bgDrawable.setTint((view.background as ColorDrawable).color)
        } else {
            bgDrawable.setTint(Color.WHITE)
        }
        view.background = bgDrawable
    }

    override fun getShapeAppearanceModel() = shapeModel

    override fun setShapeAppearanceModel(shapeAppearanceModel: ShapeAppearanceModel) {
        shapeModel = shapeAppearanceModel
        applyShape()
    }

}