MaterialCardView与MaterialShapeDrawable

4
我想实现这个效果:

enter image description here

所以我想使用MaterialShapeDrawable来实现该转换:
binding.card.background = MaterialShapeDrawable(
    ShapeAppearanceModel.builder()
        .setAllCornerSizes(5.dpToPx().toFloat())
        .setTopEdge(object : TriangleEdgeTreatment(7.dpToPx().toFloat(), false){
            override fun getEdgePath(length: Float, center: Float, interpolation: Float, shapePath: ShapePath) {
                super.getEdgePath(length, 12.dpToPx().toFloat(), interpolation, shapePath)
            }
        })
        .build()
).apply {
    fillColor = resourcesProvider().colorStateListFromAttr(R.attr.colorSurface, R.style.App_CardView)
}

但不幸的是这并没有改变什么。因此,我尝试将其应用于直接子元素,如下所示:

<com.google.android.material.card.MaterialCardView
    style="@style/Widget.MaterialComponents.CardView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="20dp"
    android:layout_marginTop="5dp"
    android:layout_marginEnd="20dp"
    android:clipChildren="false"
    app:cardBackgroundColor="@android:color/transparent"
    app:cardElevation="10dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_marginTop="10dp"> //without this margin nothing is shown

虽然有必要使用app:cardElevation="10dp",但是它导致了一些诡异的结果:

enter image description here

我的问题是:
1 - 是否可以对CardView应用变换?如果可以,怎么做?
2 - 如何解决这个“在顶部的阴影”问题?

谢谢。


1
10dp 的高度太高了,这就是为什么会出现那种奇怪的阴影。你需要将高度减少到 3dp 才能得到所需的输出。或者,如果必须使用 10dp,我建议在父布局中使用它并设置填充,给它一个高度,并减少卡片的高度。这样,您的卡片视图的阴影将减少,但仍然保持相同的高度。或者,您可以使用 Bubble 视图,或者搜索代码库以获取气泡视图的代码,如果您不想使用完整的 Repo。我使用它是因为它的阴影看起来比 CardView 更真实。 - Lalit Fauzdar
1个回答

4

由于您正在CardView之外绘制,因此在父视图中,您应该使用类似以下的内容:

  <LinearLayout
      android:clipChildren="false"
      android:clipToPadding="false"
      android:padding="16dp"
      ..>

        <com.google.android.material.card.MaterialCardView
         app:cardElevation="2dp"
         ../>

然后将更改应用于ShapeAppearanceModel,但获取卡片视图使用的现有ShapeAppearanceModel(在您的代码中,您不仅替换了现有的MaterialShapeDrawable,而且还应用了ShapeAppearanceModel的更改):
cardView.setShapeAppearanceModel(cardView.getShapeAppearanceModel()
        .toBuilder()
        .setTopEdge(new TriangleEdgeTreatment(size, false){

            @Override public void getEdgePath(float length, float center, float interpolation,
              @NonNull ShapePath shapePath) {
              //...... your implementation
            }
          }
        )
        .build());

enter image description here

1.2.0-beta01版本开始,您也可以将OffsetEdgeTreatmentMarkerEdgeTreatment一起使用。
例如:
MarkerEdgeTreatment markerEdgeTreatment = new MarkerEdgeTreatment(size);
OffsetEdgeTreatment offsetEdgeTreatment = new OffsetEdgeTreatment(markerEdgeTreatment,offset);

cardView.setShapeAppearanceModel(cardView.getShapeAppearanceModel()
            .toBuilder()
            .setTopEdge(offsetEdgeTreatment)
            .build());

enter image description here


谢谢您的回复。我有一个问题,如果我添加.setTopEdge(TriangleEdgeTreatment(7.dpToPx().toFloat(), false)),卡片就不会显示出来,如果我注释掉那一行,它就会显示(当然没有顶部三角形)。有什么提示吗? - GuilhE
@GuilhE 你在父视图中添加了填充吗? - Gabriele Mariotti
是的,就像你的例子中一样,使用LinearLayout。 - GuilhE
1
使用 material = "1.2.1",它按预期工作 :) - GuilhE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接