简体   繁体   English

更改 CardView 阴影颜色

[英]Changing CardView shadow color

This question was asked on SO many times, but still I didn't find a good solution for this problem.这个问题被问了很多次,但我仍然没有找到解决这个问题的好方法。

Why do I need this to do?为什么我需要这样做? Well because project me and my team develops has iOS style.好吧,因为我和我的团队开发的项目具有 iOS 风格。

What did I try?我尝试了什么?

  1. 9.pathch shadow generator but 9.pathes are essentially pngs and it gives me no flexibility and if I'll use this approach I should edit margins everywhere. 9.pathch 阴影生成器,但 9.pathes 本质上是 png,它没有给我任何灵活性,如果我使用这种方法,我应该编辑所有地方的边距。
  2. Carbon library it supports custom shadows and they get drawn outside of view borders, but there is issue regarding rounded rectangles, when library doesn't draw shadow for rounded corners. Carbon 库它支持自定义阴影,它们会绘制在视图边界之外,但是当库不为圆角绘制阴影时,存在关于圆角矩形的问题
  3. using old CardView implementation and overriding its shadow color, but it gets drawn inside of card bounds, so it isn't option.使用旧的 CardView 实现并覆盖其阴影颜色,但它被绘制在卡片边界内,因此它不是选项。

So is there a way to change shadow color of CardView with minimum edits of all layout files and with drawing shadow outside of the view like original CardView does?那么有没有一种方法可以像原始 CardView 一样,通过对所有布局文件进行最少的编辑并在视图外部绘制阴影来更改 CardView 的阴影颜色?

Consider this thread in twitter, where Nick Butcher talks about how to implement the feature:考虑推特上的这个帖子,尼克·布彻 (Nick Butcher) 谈到了如何实现该功能:

在此处输入图片说明

See outlineAmbientShadowColor , outlineSpotShadowColor , spotShadowAlpha and ambientShadowAlpha attributes for details.有关详细outlineAmbientShadowColor ,请参阅outlineAmbientShadowColoroutlineSpotShadowColorspotShadowAlphaambientShadowAlpha属性。 Unfortunately, that's possible from API 28 onwards.不幸的是,从 API 28 开始这是可能的。

For lower APIs Nick has shared a gist .对于较低的 API,Nick 分享了一个要点 Here's the result:结果如下:

Running on API 21在 API 21 上运行

This technique isn't directly connected to CardView , it can be applied to any View .这种技术不直接连接到CardView ,它可以应用于任何View

You Can Implement this without having a cardview, and can also have all the properties of cardview你可以在没有cardview的情况下实现这个,也可以拥有cardview的所有属性

You have to Do:你必须要做:

  1. Copy the two classes复制两个类

  2. Wrap your required view with the Custom View as in the example, you don't have to do much changes in your layout or anywhere else!如示例中所示,使用自定义视图包装所需的视图,您无需对布局或其他任何地方进行太多更改!

The below class will create a custom view, this will be wrapping your layout/View to be displayed in cardview with custom shadow color下面的类将创建一个自定义视图,这将包装您的布局/视图以使用自定义阴影颜色显示在 cardview 中

Create a class:创建一个类:

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));
    }
}

Also create the class for the Shadow Settings, ViewUtils.java还要为 Shadow Settings 创建类 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;

    }
}

and finally your XML, where you have the views required to have shadow.最后是您的 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>

Well I think of an easy solution without using a Java or Some Libraries.好吧,我想到了一个不使用 Java 或某些库的简单解决方案。 You should make a Drawable shape and put it in the drawable folder and then adjust the gradient to be like a shadow.您应该制作一个 Drawable 形状并将其放在drawable文件夹中,然后将渐变调整为像阴影一样。

For example, in my solution I have added two colors:例如,在我的解决方案中,我添加了两种颜色:

<color name="yellow_middle">#ffee58</color>
<color name="yellow_end">#7ae7de83</color>

Then I made a file and put it in drawable folder drawable\\card_view_shape.xml然后我制作了一个文件并将其放入可绘制文件夹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>

Then from there you need to wrap a your view( that would have been inside CardView ) in a container like LinearLayout then apply as the background to the container that you want to be seen like a cardview.然后从那里你需要将你的视图(本来在 CardView 里面)包装在一个像LinearLayout这样的容器中,然后作为背景应用到你想要像 cardview 一样被看到的容器。 To solve it well add some padding (Thats your shadow) to the Container itself.为了很好地解决它,向容器本身添加一些填充(那是你的阴影)。 For instance check mine:例如检查我的:

<?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>

Then the results looks like this:然后结果如下所示:
测试结果

Adjusting the bottom padding it will look like this:调整底部填充它看起来像这样:

测试结果

COMMENT评论
Since I am not of an artist but if you play with it you may make the whole thing look exactly like CardView check some hints:因为我不是艺术家,但如果你玩它,你可能会让整个事情看起来和CardView完全一样, CardView检查一些提示:

  • Putting multiple gradients in the shape在形状中放置多个渐变
  • Adjust the end colors of gradients to appear more greyish调整渐变的结束颜色以显得更灰
  • The end colours must also be a little transparent结束颜色也必须有点透明
  • Adjust your View's padding to appear like a shadow and coloured but greyish调整您的视图的填充看起来像一个阴影和彩色但灰色
  • The main View's background also matters to bring the reality From there redesign the shape to look even more realistic like a CardView .主 View 的背景对于带来现实也很重要,从那里重新设计形状,使其看起来更像CardView逼真。

display shadow >= 28 or >= P for above Sdk level 28显示阴影 >= 28 或 >= P 高于 Sdk 级别 28

use below code in your CardView在您的 CardView 中使用以下代码

with xml xml

android:outlineAmbientShadowColor="<yourCoolor>"
android:outlineSpotShadowColor="<yourCoolor>"

with java and kt file带有 java 和 kt 文件

mCardView.setOutlineAmbientShadowColor(ContextCompat.getColor(getContext(), R.color.color_new_yellow));
mCardView.setOutlineSpotShadowColor(ContextCompat.getColor(getContext(), R.color.color_new_yellow));

display like this像这样显示

在此处输入图像描述

Use Fake Shadow.使用假阴影。

Well, it is not possible to change the color of the shadow of cardview before API 28 but we can add a custom shadow behind a layout.好吧,在 API 28 之前无法更改 cardview 阴影的颜色,但我们可以在布局后面添加自定义阴影。 You need to use a drawable background ( shadow.xml ) in the parent layout which is looking like a shadow.您需要在看起来像阴影的父布局中使用可绘制背景( shadow.xml )。

shadow.xml - shadow.xml -

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <padding
                android:bottom="2dp"
                android:left="2dp"
                android:right="2dp"
                android:top="2dp" />

            <solid android:color="#05FF46A9" />
            <corners android:radius="15dp" />
        </shape>
    </item>
    <item>
        <shape>
            <padding
                android:bottom="2dp"
                android:left="2dp"
                android:right="2dp"
                android:top="2dp" />

            <solid android:color="#10FF46A9" />
            <corners android:radius="15dp" />
        </shape>
    </item>
    <item>
        <shape>
            <padding
                android:bottom="2dp"
                android:left="2dp"
                android:right="2dp"
                android:top="2dp" />

            <solid android:color="#15FF46A9" />
            <corners android:radius="15dp" />
        </shape>
    </item>
    <item>
        <shape>
            <padding
                android:bottom="2dp"
                android:left="2dp"
                android:right="2dp"
                android:top="2dp" />

            <solid android:color="#20FF46A9" />
            <corners android:radius="15dp" />
        </shape>
    </item>

    <item>
        <shape>
            <padding
                android:bottom="2dp"
                android:left="2dp"
                android:right="2dp"
                android:top="2dp" />

            <solid android:color="#25FF46A9" />
            <corners android:radius="15dp" />
        </shape>
    </item>
</layer-list>

Now use the following code -现在使用以下代码 -

<FrameLayout
    android:layout_width="match_parent"
    android:background="@drawable/shadow"
    android:layout_height="200dp">

    <CardView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:cardCornerRadius="15dp"
        app:cardElevation="0dp">

            <!--  your code here  -->

    </CardView>

</FrameLayout>

You can replace FF46A9 in shadow.xml to change the color of shadow.您可以替换FF46A9中的shadow.xml来更改阴影的颜色。 Also android:backgroundTint="@color/colorShadow" works but you have to adjust colors alpha in shadow.xml. android:backgroundTint="@color/colorShadow"可以工作,但您必须在 shadow.xml 中调整颜色 alpha。

Adjust the <corners android:radius="15dp"/> as app:cardCornerRadius="15dp" .<corners android:radius="15dp"/>app:cardCornerRadius="15dp"

This trick is difficult to achieve in most cases , due Official Android Framework do not have any way to change the cardview shadow color.这个技巧在大多数情况下很难实现,因为官方 Android 框架没有任何方法来改变 cardview 阴影颜色。 In this case you refers to ilumination light on the cardview .在这种情况下,您指的是 cardview 上的照明灯。 This library is optimized for this this trick.该库针对此技巧进行了优化。

Library Link: https://github.com/meetsl/SCardView-master I hope can help you!库链接: https : //github.com/meetsl/SCardView-master希望能帮到你! Good Luck祝你好运

enter image description here I know I'm late but I want to share the solution as I searched hard for this issue and solved the issue The solution is, You have to use "ComplexView" to create your custom shadow,在这里输入图片描述我知道我来晚了,但我想分享解决方案,因为我努力搜索这个问题并解决了这个问题解决方案是,你必须使用“ComplexView”来创建你的自定义阴影,

dependency: implementation 'com.github.BluRe-CN:ComplexView:v1.1'依赖: implementation 'com.github.BluRe-CN:ComplexView:v1.1'

XML: XML:

<com.blure.complexview.ComplexView
   android:id="@+id/shadow_card_1"
   android:layout_width="@dimen/_65sdp"
   android:layout_height="@dimen/_65sdp"
   android:layout_centerInParent="true"
   app:radius="@dimen/_30sdp"
   app:shadow="true"
   app:shadowAlpha="250"
   app:shadowSpread="2"/>

//this will create the circular shadow for my need you can reduce the radius //这将为我的需要创建圆形阴影你可以减少半径

Custom View自定义视图

val shadow = ComplexView(context)
val radii = floatArrayOf(100f, 100f, 100f, 100f, 100f, 100f, 100f, 100f)//customise according to your requirement
val opacity = 150//customise according to your requirement
 shadow.shadow =Shadow(
       2,
       opacity,
       "#96B9BB",
       GradientDrawable.RECTANGLE,
       radii,
       Shadow.Position.CENTER
      )

val param: RelativeLayout.LayoutParams =
                    RelativeLayout.LayoutParams(
                        context.resources.getDimension(R.dimen._160sdp).toInt(),
                        context.resources.getDimension(R.dimen._160sdp).toInt()
                    )
shadow.layoutParams = param
shadow.addView(yourCustomView)

here is the result:这是结果:

also

thanks:)谢谢:)

Simple way to change card 's shadow color is to set android:outlineSpotShadowColor="@color/#CCCCCC" inside your CardView更改卡片阴影颜色的简单方法是在android:outlineSpotShadowColor="@color/#CCCCCC"设置android:outlineSpotShadowColor="@color/#CCCCCC"

           <androidx.cardview.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                
                app:cardElevation="15dp"
                android:outlineAmbientShadowColor="@color/#CCCCCC"
                android:outlineSpotShadowColor="@color/#CCCCCC" />

Already late for the answer.回答已经晚了。

Some trick can work perfectly for me一些技巧可以完美地为我工作在此处输入图片说明

And XML file like和 XML 文件一样

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical">
    <androidx.cardview.widget.CardView
        android:id="@+id/cardview"
        android:layout_width="@dimen/_150sdp"
        android:layout_height="@dimen/_150sdp"
        android:layout_marginLeft="@dimen/_10sdp"
        android:layout_marginRight="@dimen/_10sdp"
        app:cardBackgroundColor="@color/white"
        app:cardCornerRadius="@dimen/_5sdp"
        app:cardUseCompatPadding="true">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/_50sdp"
            android:orientation="vertical">
        </LinearLayout>
        <View
            android:id="@+id/view_color"
            android:layout_width="match_parent"
            android:layout_height="@dimen/_2sdp"
            android:layout_gravity="bottom"
            android:background="@color/app_green" />
    </androidx.cardview.widget.CardView>

</LinearLayout>

Enjoy coding享受编码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM