CardView 在 Pre-Lollipop 上的每个边缘都有额外的边距
CardView has extra margin in each edge on Pre-Lollipop
这里有两张照片。
关于棒棒糖:
关于 Pre-Lollipop:
我们可以看到它刚好靠近棒棒糖的屏幕一侧。这就是我想要的。但在 Pre-Lollipop 设备上,它在屏幕边缘有额外的边距。你们有什么经验吗?谢谢。
布局如下xml:
<android.support.v7.widget.CardView
android:id="@+id/card_title_schedule"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
app:cardCornerRadius="0dp"
app:cardBackgroundColor="@color/colorAccent"
>
Before L, CardView adds padding to its content and draws shadows to that area. This padding amount is equal to maxCardElevation + (1 - cos45) * cornerRadius on the sides and maxCardElevation * 1.5 + (1 - cos45) * cornerRadius on top and bottom.
来自 CardView 参考资料 here
尝试像这样
在 CardView
上设置负左边距
<android.support.v7.widget.CardView
android:id="@+id/card_title_schedule"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
app:cardCornerRadius="0dp"
app:cardBackgroundColor="@color/colorAccent"
app:cardUseCompatPadding="true"
android:layout_marginLeft="-2dp" />
您可能需要调整边距以获得所需的结果。
PS,这是一种 hack-y 的方式。
试试 card_view:cardUseCompatPadding="true"
如果我们将此 属性 设置为 true,则边距在所有版本上都相同。
开发者说明
Add padding in API v21+ as well to have the same measurements with
previous versions.
来源docs
要解决 PRE-L 版本的 "shadow space" 问题,您可以通过负值动态更新 CardView 边距以补偿 space。
获取实际阴影space:
shadowSpaceLeft = getPaddingLeft() - getContentPaddingLeft();
固定边距:
layoutParams.leftMargin -= shadowSpaceLeft;
这将适用于所有 Android 版本,因为我们正在动态获取填充值和 contentPadding 值。
例如,这里有一个 class,每当我们设置新的布局参数时它都会执行此操作:
public class NoPaddingCardView extends CardView {
public NoPaddingCardView(Context context) {
super(context);
init();
}
public NoPaddingCardView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public NoPaddingCardView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
// Optional: Prevent pre-L from adding inner card padding
setPreventCornerOverlap(false);
// Optional: make Lollipop and above add shadow padding to match pre-L padding
setUseCompatPadding(true);
}
@Override
public void setLayoutParams(ViewGroup.LayoutParams params) {
// FIX shadow padding
if (params instanceof MarginLayoutParams) {
MarginLayoutParams layoutParams = (MarginLayoutParams) params;
layoutParams.bottomMargin -= (getPaddingBottom() - getContentPaddingBottom());
layoutParams.leftMargin -= (getPaddingLeft() - getContentPaddingLeft());
layoutParams.rightMargin -= (getPaddingRight() - getContentPaddingRight());
layoutParams.topMargin -= (getPaddingTop() - getContentPaddingTop());
}
super.setLayoutParams(params);
}
}
因此它在 Kitkat 上运行得非常好,准确地说是三星设备。
我尝试了 card_view:cardUseCompatPadding="true"
但无济于事。没用!
然后我从Whosebug上发现了post这个
card_view:cardPreventCornerOverlap="false"
瞧!成功了!没有圆角(因为我想要 none 因为卡片有图像背景)。
道德是,额外的填充是因为那些需要禁用的小圆角。基本上这不是缺陷而是设计限制!
图片:请注意,顶角是边缘(具有颜色和背景图像的视图),而底部只有 TextView,没有背景,因此是圆角。这意味着如果一个视图在 CardView 中请求 match_parent
,card_view:cardPreventCornerOverlap="false"
将允许在受影响的角落占用它。
我知道这个问题已经得到解答,但我想补充一点,除了 card_view:cardPreventCornerOverlap="false"
之外,我还必须设置 CardView.setMaxCardElevation(0)
以消除 Lollipop 之前的边距.仅将高程设置为 0 不起作用。我正在使用支持库 v23.4.0.
如果需要 Android 4(前棒棒糖)行为,将 app:cardUseCompatPadding="true"
添加到 CardView
应该可以解决它。
如果需要 Android 5+ 行为(根据 material 指南,这实际上是卡片视图的正确行为),则无法轻易实现完全相同的事情。我通常使用这个修复来避免定义多个布局文件并在所有设备上都有合理的输出:
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentPaddingRight="@dimen/fix_cardview"
app:contentPaddingLeft="@dimen/fix_cardview"
app:contentPaddingTop="@dimen/fix_cardview_vertical"
app:contentPaddingBottom="@dimen/fix_cardview_vertical" />
在正常的 values/dimens.xml
文件中我们应该有:
<dimen name="fix_cardview">-8dp</dimen>
<dimen name="fix_cardview_vertical">-12dp</dimen>
并在 values-v21/dimens.xml
中:
<dimen name="fix_cardview">0dp</dimen>
<dimen name="fix_cardview_vertical">0dp</dimen>
请注意,数字 -8dp
和 -12dp
可能需要根据您的布局进行调整,因为它们取决于海拔等因素。
这只是避免在 Android 4 个视图中使用丑陋的填充的变通方法,而不是在不同的布局文件中使用不同的视图(这通常会使代码更难维护)
只需将此添加到棒棒糖前版本的代码中:
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
{
cardView.setMaxCardElevation(0f);
cardView.setPreventCornerOverlap(false);
}
这里有两张照片。
关于棒棒糖:
关于 Pre-Lollipop:
我们可以看到它刚好靠近棒棒糖的屏幕一侧。这就是我想要的。但在 Pre-Lollipop 设备上,它在屏幕边缘有额外的边距。你们有什么经验吗?谢谢。
布局如下xml:
<android.support.v7.widget.CardView
android:id="@+id/card_title_schedule"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
app:cardCornerRadius="0dp"
app:cardBackgroundColor="@color/colorAccent"
>
Before L, CardView adds padding to its content and draws shadows to that area. This padding amount is equal to maxCardElevation + (1 - cos45) * cornerRadius on the sides and maxCardElevation * 1.5 + (1 - cos45) * cornerRadius on top and bottom.
来自 CardView 参考资料 here
尝试像这样
在CardView
上设置负左边距
<android.support.v7.widget.CardView
android:id="@+id/card_title_schedule"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
app:cardCornerRadius="0dp"
app:cardBackgroundColor="@color/colorAccent"
app:cardUseCompatPadding="true"
android:layout_marginLeft="-2dp" />
您可能需要调整边距以获得所需的结果。
PS,这是一种 hack-y 的方式。
试试 card_view:cardUseCompatPadding="true"
如果我们将此 属性 设置为 true,则边距在所有版本上都相同。
开发者说明
Add padding in API v21+ as well to have the same measurements with previous versions.
来源docs
要解决 PRE-L 版本的 "shadow space" 问题,您可以通过负值动态更新 CardView 边距以补偿 space。
获取实际阴影space:
shadowSpaceLeft = getPaddingLeft() - getContentPaddingLeft();
固定边距:
layoutParams.leftMargin -= shadowSpaceLeft;
这将适用于所有 Android 版本,因为我们正在动态获取填充值和 contentPadding 值。
例如,这里有一个 class,每当我们设置新的布局参数时它都会执行此操作:
public class NoPaddingCardView extends CardView {
public NoPaddingCardView(Context context) {
super(context);
init();
}
public NoPaddingCardView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public NoPaddingCardView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
// Optional: Prevent pre-L from adding inner card padding
setPreventCornerOverlap(false);
// Optional: make Lollipop and above add shadow padding to match pre-L padding
setUseCompatPadding(true);
}
@Override
public void setLayoutParams(ViewGroup.LayoutParams params) {
// FIX shadow padding
if (params instanceof MarginLayoutParams) {
MarginLayoutParams layoutParams = (MarginLayoutParams) params;
layoutParams.bottomMargin -= (getPaddingBottom() - getContentPaddingBottom());
layoutParams.leftMargin -= (getPaddingLeft() - getContentPaddingLeft());
layoutParams.rightMargin -= (getPaddingRight() - getContentPaddingRight());
layoutParams.topMargin -= (getPaddingTop() - getContentPaddingTop());
}
super.setLayoutParams(params);
}
}
因此它在 Kitkat 上运行得非常好,准确地说是三星设备。
我尝试了 card_view:cardUseCompatPadding="true"
但无济于事。没用!
然后我从Whosebug上发现了post这个
card_view:cardPreventCornerOverlap="false"
瞧!成功了!没有圆角(因为我想要 none 因为卡片有图像背景)。
道德是,额外的填充是因为那些需要禁用的小圆角。基本上这不是缺陷而是设计限制!
图片:请注意,顶角是边缘(具有颜色和背景图像的视图),而底部只有 TextView,没有背景,因此是圆角。这意味着如果一个视图在 CardView 中请求 match_parent
,card_view:cardPreventCornerOverlap="false"
将允许在受影响的角落占用它。
我知道这个问题已经得到解答,但我想补充一点,除了 card_view:cardPreventCornerOverlap="false"
之外,我还必须设置 CardView.setMaxCardElevation(0)
以消除 Lollipop 之前的边距.仅将高程设置为 0 不起作用。我正在使用支持库 v23.4.0.
如果需要 Android 4(前棒棒糖)行为,将 app:cardUseCompatPadding="true"
添加到 CardView
应该可以解决它。
如果需要 Android 5+ 行为(根据 material 指南,这实际上是卡片视图的正确行为),则无法轻易实现完全相同的事情。我通常使用这个修复来避免定义多个布局文件并在所有设备上都有合理的输出:
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentPaddingRight="@dimen/fix_cardview"
app:contentPaddingLeft="@dimen/fix_cardview"
app:contentPaddingTop="@dimen/fix_cardview_vertical"
app:contentPaddingBottom="@dimen/fix_cardview_vertical" />
在正常的 values/dimens.xml
文件中我们应该有:
<dimen name="fix_cardview">-8dp</dimen>
<dimen name="fix_cardview_vertical">-12dp</dimen>
并在 values-v21/dimens.xml
中:
<dimen name="fix_cardview">0dp</dimen>
<dimen name="fix_cardview_vertical">0dp</dimen>
请注意,数字 -8dp
和 -12dp
可能需要根据您的布局进行调整,因为它们取决于海拔等因素。
这只是避免在 Android 4 个视图中使用丑陋的填充的变通方法,而不是在不同的布局文件中使用不同的视图(这通常会使代码更难维护)
只需将此添加到棒棒糖前版本的代码中:
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
{
cardView.setMaxCardElevation(0f);
cardView.setPreventCornerOverlap(false);
}