赞
踩
CardView
经常使用的属性cardview_cardBackgroundColor 设置背景色
cardview_cardCornerRadius 设置圆角大小
cardview_cardElevation 设置z轴阴影
cardview_cardMaxElevation 设置z轴最大高度值
cardview_cardUseCompatPadding 是否使用CompatPadding
cardview_cardPreventCornerOverlap 是否使用PreventCornerOverlap ,防止内容和边角的重叠
cardview_contentPadding 内容的padding
xml里面加上这么一句话 xmlns:card_view="http://schemas.android.com/apk/res-auto"
CardView
继承Framelayout
。CardView
内部持有了一个CardViewImpl
实例和一个CardViewDelegate
实例,CardViewImpl
主要是CardView
内部对于圆角阴影等 cardview
重要特性在不同版本上的兼容,CardViewImpl
是对CardView
具有的行为的抽象,在不同版本下有不同的实现,比如CardViewApi21
,CardViewJellybeanMr1
,CardViewGingerbread
。CardView
对于Lollipop以上版本,是直接通过elevation
来实现的阴影。
android:elevation
设置该组件“浮”起来的高度,to难过过设置该属性可以让该组件呈现3D效果。android:translationZ
设置该组件在Z方向(垂直屏幕方向)上的位移。eleavation
是静态的成员,translationZ
是用来做动画。elevation
需要有margin
配合才能透出阴影,比如elevation:10dp
, margin:10dp
, 这样才能配合实现阴影。padding
里面透出阴影来实现的,查看源码发现是通过RoundRectDrawableWithShadow
这个drawble
充当背景来实现的,而RoundRectDrawableWithShadow
这个里面是通过RadialGradient
和LinearGradient
两种shader
(纹理)来实现的渐变模拟的阴影效果。CardView
直接设置setPadding
时是没有用的,为什么呢,里面重写了setPadding
方法,是空实现。@Override
public void setPadding(int left, int top, int right, int bottom) {
// NO OP
}
setContentPadding
,我们可以看一下setContentPadding
的实现,可以看到CardViewDelegate
里面有这么一句话@Override
public void setShadowPadding(int left, int top, int right, int bottom) {
mShadowBounds.set(left, top, right, bottom);
CardView.super.setPadding(left + mContentPadding.left, top + mContentPadding.top,
right + mContentPadding.right, bottom + mContentPadding.bottom);
}
shadow
的阴影由padding
漏出,是必须留出来的,而剩下设置的contentPadding
才是你设置的padding
。CardView
,我踩了个坑,在把cardview
的BackgroundDrawable
给替换了之后,结果之后再怎么设置颜色和圆角等属性都不起作用了,这是为什么呢?private final CardViewDelegate mCardViewDelegate = new CardViewDelegate() { private Drawable mCardBackground; @Override public void setCardBackground(Drawable drawable) { mCardBackground = drawable; setBackgroundDrawable(drawable); } @Override public boolean getUseCompatPadding() { return CardView.this.getUseCompatPadding(); } @Override public boolean getPreventCornerOverlap() { return CardView.this.getPreventCornerOverlap(); } @Override public void setShadowPadding(int left, int top, int right, int bottom) { mShadowBounds.set(left, top, right, bottom); CardView.super.setPadding(left + mContentPadding.left, top + mContentPadding.top, right + mContentPadding.right, bottom + mContentPadding.bottom); } @Override public void setMinWidthHeightInternal(int width, int height) { if (width > mUserSetMinWidth) { CardView.super.setMinimumWidth(width); } if (height > mUserSetMinHeight) { CardView.super.setMinimumHeight(height); } } @Override public Drawable getCardBackground() { return mCardBackground; } @Override public View getCardView() { return CardView.this; } };
mCardViewDelegate
来完成的,而通过mCardViewDelegate
获取的背景Drawable
是它保存的mCardBackground
实例,一旦直接给CardView
设置了一个BackgroundDrawble
,这个drawble
和mCardViewDelegate
保存的mCardBackground
就不再是一个,那么之后对于背景的操作就是对牛弹琴,改变的只是mCardBackground
的属性,而真正的cardview
的属性没有改变。cardview_cardPreventCornerOverlap
是否使用PreventCornerOverlap
,防止内容和边角的重叠,之前一直没搞懂这个属性的意思,直到我看到了RoundRectDrawableWithShadow
中这段源码,还记得之前说的吗,RoundRectDrawableWithShadow
实现了5.0以下的阴影static float calculateVerticalPadding(float maxShadowSize, float cornerRadius,
boolean addPaddingForCorners) {
if (addPaddingForCorners) {
return (float) (maxShadowSize * SHADOW_MULTIPLIER + (1 - COS_45) * cornerRadius);
} else {
return maxShadowSize * SHADOW_MULTIPLIER;
}
}
addPaddingForCorners
对应的就是PreventCornerOverlap
这个boolean
变量,通过+ (1 - COS_45) * cornerRadius
,保证了内容不会超过圆角的边界。CardView
水波纹效果。既然CardView
继承自Framelayout
,那么和Framelayout
实现水波纹是一个效果。直接给 CardView
加上android:foreground="?attr/selectableItemBackground"
这个属性会在 Lollipop 上自动加上 Ripple
效果,在旧版本则是一个变深/变亮的效果。Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。