Mik*_*mov 22 android shadow android-view android-cardview android-elevation
这个问题在很多时候被问过,但我仍然找不到解决这个问题的好方法.
为什么我需要这样做?好吧,因为项目我和我的团队开发有iOS风格.
我尝试了什么?
那么有没有办法改变CardView的阴影颜色,只需对所有布局文件进行最少的编辑,并在视图外部绘制阴影,就像原始的CardView一样?
azi*_*ian 26
在Twitter上考虑这个帖子,Nick Butcher谈到如何实现这个:

有关详细信息,请参阅outlineAmbientShadowColor,和属性.不幸的是,这可以从API 28开始实现.outlineSpotShadowColorspotShadowAlphaambientShadowAlpha
对于较低的API,Nick已经分享了一个要点.这是结果:

在API 21上运行
这种技术没有直接连接CardView,它可以应用于任何View.
对于 Sdk 级别 28 以上,显示阴影 >= 28 或 >= P
在您的 CardView 中使用以下代码
使用 XML
android:outlineAmbientShadowColor="<yourCoolor>"
android:outlineSpotShadowColor="<yourCoolor>"
Run Code Online (Sandbox Code Playgroud)
带有java和kt文件
mCardView.setOutlineAmbientShadowColor(ContextCompat.getColor(getContext(), R.color.color_new_yellow));
mCardView.setOutlineSpotShadowColor(ContextCompat.getColor(getContext(), R.color.color_new_yellow));
Run Code Online (Sandbox Code Playgroud)
像这样显示
您可以在没有cardview的情况下实现此功能,还可以拥有cardview的所有属性
你所要做的:
复制两个类
如示例中所示,将所需的视图与“自定义视图”包装在一起,您无需在布局或其他任何地方做很多更改!
下面的类将创建一个自定义视图,这将包装您的布局/视图以在卡视图中以自定义阴影颜色显示
创建一个类:
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.LinearLayout;
import com.qzion.nfscrew.R;
public class RoundLinerLayoutNormal extends LinearLayout {
public RoundLinerLayoutNormal(Context context) {
super(context);
initBackground();
}
public RoundLinerLayoutNormal(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initBackground();
}
public RoundLinerLayoutNormal(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initBackground();
}
private void initBackground() {
setBackground(ViewUtils.generateBackgroundWithShadow(this,R.color.white,
R.dimen.radius_corner,R.color.colorPrimaryDark,R.dimen.elevation, Gravity.BOTTOM));
}
}
Run Code Online (Sandbox Code Playgroud)
还要为“阴影设置”创建类ViewUtils.java
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.support.annotation.ColorRes;
import android.support.annotation.DimenRes;
import android.support.v4.content.ContextCompat;
import android.view.Gravity;
import android.view.View;
import static android.support.v4.view.ViewCompat.LAYER_TYPE_SOFTWARE;
public class ViewUtils {
public static Drawable generateBackgroundWithShadow(View view, @ColorRes int backgroundColor,
@DimenRes int cornerRadius,
@ColorRes int shadowColor,
@DimenRes int elevation,
int shadowGravity) {
float cornerRadiusValue = view.getContext().getResources().getDimension(cornerRadius);
int elevationValue = (int) view.getContext().getResources().getDimension(elevation);
int shadowColorValue = ContextCompat.getColor(view.getContext(),shadowColor);
int backgroundColorValue = ContextCompat.getColor(view.getContext(),backgroundColor);
float[] outerRadius = {cornerRadiusValue, cornerRadiusValue, cornerRadiusValue,
cornerRadiusValue, cornerRadiusValue, cornerRadiusValue, cornerRadiusValue,
cornerRadiusValue};
Paint backgroundPaint = new Paint();
backgroundPaint.setStyle(Paint.Style.FILL);
backgroundPaint.setShadowLayer(cornerRadiusValue, 0, 0, 0);
Rect shapeDrawablePadding = new Rect();
shapeDrawablePadding.left = elevationValue;
shapeDrawablePadding.right = elevationValue;
int DY;
switch (shadowGravity) {
case Gravity.CENTER:
shapeDrawablePadding.top = elevationValue;
shapeDrawablePadding.bottom = elevationValue;
DY = 0;
break;
case Gravity.TOP:
shapeDrawablePadding.top = elevationValue*2;
shapeDrawablePadding.bottom = elevationValue;
DY = -1*elevationValue/3;
break;
default:
case Gravity.BOTTOM:
shapeDrawablePadding.top = elevationValue;
shapeDrawablePadding.bottom = elevationValue*2;
DY = elevationValue/3;
break;
}
ShapeDrawable shapeDrawable = new ShapeDrawable();
shapeDrawable.setPadding(shapeDrawablePadding);
shapeDrawable.getPaint().setColor(backgroundColorValue);
shapeDrawable.getPaint().setShadowLayer(cornerRadiusValue/3, 0, DY, shadowColorValue);
view.setLayerType(LAYER_TYPE_SOFTWARE, shapeDrawable.getPaint());
shapeDrawable.setShape(new RoundRectShape(outerRadius, null, null));
LayerDrawable drawable = new LayerDrawable(new Drawable[]{shapeDrawable});
drawable.setLayerInset(0, elevationValue, elevationValue*2, elevationValue, elevationValue*2);
return drawable;
}
}
Run Code Online (Sandbox Code Playgroud)
最后是您的XML,那里您需要具有阴影的视图。
<com.qzion.nfscrew.utils.RoundLinerLayoutNormal
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This view will have shadow"/>
</com.qzion.nfscrew.utils.RoundLinerLayoutNormal>
Run Code Online (Sandbox Code Playgroud)
好吧,我想到了一个不使用Java或某些库的简单解决方案。您应该制作一个Drawable形状并将其放在drawable文件夹中,然后将渐变调整为类似于阴影的形状。
例如,在我的解决方案中,我添加了两种颜色:
<color name="yellow_middle">#ffee58</color>
<color name="yellow_end">#7ae7de83</color>
Run Code Online (Sandbox Code Playgroud)
然后我制作了一个文件并将其放在可绘制的文件夹中 drawable\card_view_shape.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size
android:width="10dp"
android:height="10dp" />
<corners android:radius="6dp" />
<stroke
android:width="2dp"
android:color="@color/yellow_end" />
<gradient
android:angle="-90"
android:centerColor="@color/yellow_middle"
android:endColor="@color/yellow_end"
android:startColor="#fff" />
</shape>
Run Code Online (Sandbox Code Playgroud)
然后,从那里,您需要将视图(该视图原本在CardView内)包装在一个容器中,LinearLayout然后像希望将其作为背景一样应用到该容器中,就像cardview一样。为了很好地解决它,请在容器本身中添加一些填充(即您的阴影)。例如检查我的:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.xenolion.ritetrends.MainActivity">
<LinearLayout
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center"
android:background="@drawable/card_view_shape"
android:orientation="vertical"
android:paddingBottom="10dp"
android:paddingLeft="3dp"
android:paddingRight="3dp"
android:paddingTop="3dp">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:gravity="center"
android:text="I love StackOverflow"
android:textColor="#000"
android:textSize="18sp" />
</LinearLayout>
</FrameLayout>
Run Code Online (Sandbox Code Playgroud)
调整底部填充看起来像这样:
评论
由于我不是艺术家,但是如果您与它一起玩,可能会使整个过程看起来完全像CardView检查一些提示:
CardView。