Anm*_*mol 5 android android-cardview materialcardview
我的用例是编辑 shapeAppearanceModelcom.google.android.material.card.MaterialCardView
card.shapeAppearanceModel = card.shapeAppearanceModel
.toBuilder()
.setTopEdge(TriangleEdgeTreatment(triangleSize))
.build()
Run Code Online (Sandbox Code Playgroud)
上面的代码按预期工作,但是由于上面以编程方式设置了 shapeAppearanceModel
<com.google.android.material.card.MaterialCardView
android:id="@+id/card"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cardBackgroundColor="?myCustomColor"
app:cardCornerRadius="8dp"
app:cardElevation=4dp"
app:cardPreventCornerOverlap="true"
app:cardUseCompatPadding="false">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:src="@drawable/myImageDrawable"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</com.google.android.material.card.MaterialCardView>
Run Code Online (Sandbox Code Playgroud)
在 Android studio 中,由于 TopEdge 以编程方式定义,编辑器不会复制该错误,但在模拟器/真实设备中,子项不会被剪切,并且圆角会被 ImageView 重叠。
当我删除 shapeAppearanceModel 设置时,裁剪工作将按预期进行。
原因是因为只有当形状被标记为圆形时才MaterialCardView
锁定行为,不幸的是,该实现默认情况下也被组件本身锁定:clipToOutline
如果你打开MaterialCardView.java,你可以找到这样的代码:
@Override
public void setShapeAppearanceModel(@NonNull ShapeAppearanceModel shapeAppearanceModel) {
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
setClipToOutline(shapeAppearanceModel.isRoundRect(getBoundsAsRectF()));
}
cardViewHelper.setShapeAppearanceModel(shapeAppearanceModel);
}
Run Code Online (Sandbox Code Playgroud)
如果你更深入的话, , 的实现isRoundRect
将是这样的:
@RestrictTo(LIBRARY_GROUP)
public boolean isRoundRect(@NonNull RectF bounds) {
boolean hasDefaultEdges =
leftEdge.getClass().equals(EdgeTreatment.class)
&& rightEdge.getClass().equals(EdgeTreatment.class)
&& topEdge.getClass().equals(EdgeTreatment.class)
&& bottomEdge.getClass().equals(EdgeTreatment.class);
float cornerSize = topLeftCornerSize.getCornerSize(bounds);
boolean cornersHaveSameSize =
topRightCornerSize.getCornerSize(bounds) == cornerSize
&& bottomLeftCornerSize.getCornerSize(bounds) == cornerSize
&& bottomRightCornerSize.getCornerSize(bounds) == cornerSize;
boolean hasRoundedCorners =
topRightCorner instanceof RoundedCornerTreatment
&& topLeftCorner instanceof RoundedCornerTreatment
&& bottomRightCorner instanceof RoundedCornerTreatment
&& bottomLeftCorner instanceof RoundedCornerTreatment;
return hasDefaultEdges && cornersHaveSameSize && hasRoundedCorners;
}
Run Code Online (Sandbox Code Playgroud)
如果形状具有相同或所有角都是圆角,则有一个条件使其返回 true。
您无法通过以编程方式设置来欺骗它,card.setClipToOutline(true)
因为它发生在渲染过程之后。
他们这样做的原因是由于设计上的一些限制:
(进一步阅读:https://github.com/material-components/material-components-android/issues/1950)
好消息是,您可以通过创建自己的MaterialCardView
并覆盖一些实现来解决这个问题,如下所示:
package com.example.myapp;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import com.google.android.material.card.MaterialCardView;
import com.google.android.material.shape.ShapeAppearancePathProvider;
public class MaskedCardView extends MaterialCardView {
private ShapeAppearancePathProvider pathProvider = new ShapeAppearancePathProvider();
private Path path = new Path();
private RectF rectF = new RectF(0f, 0f, 0f, 0f);
public MaskedCardView(Context context) {
super(context);
}
public MaskedCardView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MaskedCardView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.clipPath(path);
super.onDraw(canvas);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
rectF.right = (float) w;
rectF.bottom = (float) h;
pathProvider.calculatePath(getShapeAppearanceModel(), 1f, rectF, path);
super.onSizeChanged(w, h, oldw, oldh);
}
}
Run Code Online (Sandbox Code Playgroud)
我希望它能回答你的问题。
归档时间: |
|
查看次数: |
1273 次 |
最近记录: |