MaterialCardView с MaterialShapeDrawable - PullRequest
3 голосов
/ 26 мая 2020

Я хочу добиться этого:

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 Ответ

2 голосов
/ 26 мая 2020

Поскольку вы рисуете за пределами CardView, в родительском представлении вы должны использовать что-то вроде:

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

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

Затем примените изменения к ShapeAppearanceModel, но получите существующий ShapeAppearanceModel используется cardview (в вашем коде вы заменяете существующий 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, вы также можете использовать OffsetEdgeTreatment с MarkerEdgeTreatment.

Что-то вроде:

MarkerEdgeTreatment markerEdgeTreatment = new MarkerEdgeTreatment(size);
OffsetEdgeTreatment offsetEdgeTreatment = new OffsetEdgeTreatment(markerEdgeTreatment,offset);

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

enter image description here

...