Android Advanced Road - sombra de fondo, fondo de sombra

No sé si escuchas a menudo estas palabras: Tu sombra no tiene efecto de sombra; tu sombra es demasiado espesa; tu sombra es demasiado espesa; tu sombra es demasiado sólida; el color de tu sombra no es el correcto, tu sombra...

En el desarrollo oficial, hay un enlace llamado aceptación de UI antes del lanzamiento (la aceptación del producto se puede hacer antes y después), principalmente para verificar si el efecto de desarrollo es consistente con el dibujo de diseño. Por supuesto, muchas UI también pueden ser temporalmente modificado...

Volviendo al principio, a menudo surgen preguntas sobre las sombras durante el proceso de aceptación, lo que se puede decir que es tedioso.Recientemente, tengo algo de tiempo para registrar mis implementaciones de sombras conocidas.

Cada efecto en este artículo ha pasado demola prueba, siempre debe haber uno que pueda satisfacer las necesidades del diseño.

Resumen de efectos

以下均为真机测试效果

inserte la descripción de la imagen aquí

pseudo sombra de forma

La razón por la que se registra este efecto de sombra falsa es porque algunos métodos de implementación de sombra posteriores necesitan usar este conocimiento.

Si no conoce la forma, o si no está familiarizado con ella, puede ir directamente al manual de la niñera de la forma

Efecto
inserte la descripción de la imagen aquí

shape_shadow (estilo de forma)

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 这里是设置背景色-->
    <solid android:color="#ffffff" />
    <!-- 设置四周圆角,可统一设置,也可以单独设置某个位置为圆角-->
    <corners android:radius="5dp" />
    <!--    <corners-->
    <!--        android:bottomLeftRadius="5dp"-->
    <!--        android:bottomRightRadius="5dp"-->
    <!--        android:topLeftRadius="5dp"-->
    <!--        android:topRightRadius="5dp" />-->
    <!-- 这里设置边框 -->
    <stroke
        android:width="1dp"
        android:color="#eeeeee" />
</shape>

establecer controlesbackground

    <TextView
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        android:background="@drawable/shape_shadow"
        android:gravity="center"
        android:text="伪阴影" />

pseudo-sombra de lista de capas

Para ser honesto, nunca antes había usado layer-listuna forma de ensamblarlo shape, pero también aprendí una ola mientras miraba las sombras.

Al usar layer-listel método de implementación, puede transponerlo a un control escrito en xml, porque esta también es una capa de ensamblaje

Efecto

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

capa_sombra

  • 绘制俩个长方形的shape,上层视图添加内边距,就会形成视觉错觉,也是一种伪阴影效果
  • 对比前者,这种方式可以改变底部背景,类似修改伪阴影颜色
  • 对比前者,这种方式可以改变图层边距,类似修改伪阴影深度
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="#CAEEEEEE" />
            <corners android:radius="2dp" />
        </shape>
    </item>

    <item
        android:bottom="2dp"
        android:left="2dp"
        android:right="2dp"
        android:top="2dp">
        <shape android:shape="rectangle">
            <solid android:color="@android:color/white" />
            <corners android:radius="2dp" />
        </shape>
    </item>
</layer-list>

establecer controlesbackground

    <TextView
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:layout_gravity="center_horizontal"
        android:layout_margin="10dp"
        android:background="@drawable/layer_shadow"
        android:gravity="center"
        android:text="layer-list 阴影" />

sombra de alzado

elevationEs Material Designun efecto de sombra provisto, solo API21及以上compatible; no lo he usado mucho antes, cuando escribí la demostración尝试了一下这些属性主要作用于 ViewGroup

Si el enlace de aceptación no es muy estricto, esta implementación también puede pasar la prueba, y el uso también es muy simple. El atributo se usa principalmente. Si no está configurado, el sistema elevation + translationZ + outlineSpotShadowColorusará outlineSpotShadowColorel gris predeterminado

  • altura de elevación
  • profundidad de traducciónZ
  • contornoSpotShadowColor color de sombra

Efecto

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

Cómo utilizar

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginBottom="10dp"
        android:background="@color/white"
        android:elevation="5dp"
        android:orientation="vertical"
        android:outlineSpotShadowColor="#f00000"
        android:translationZ="1dp">

        <TextView
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:layout_gravity="center_horizontal"
            android:gravity="center"
            android:text="elevation 阴影" />
    </LinearLayout>

Sombra de CardView

CardViewEs Material Designun control de capa externa (ViewGroup) proporcionado por , solo API21及以上compatible; el método interno parece ser elevation + translationZun método de combinación

Si no sabe mucho sobre CardView, puede echar un vistazo al efecto de cardado de CardView , que puede lograr rápidamente esquinas redondeadas, sombras, etc.

Efecto

inserte la descripción de la imagen aquí
Cómo utilizar

    <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="10dp"
        android:background="@color/white"
        android:translationZ="3dp"
        app:cardElevation="5dp">

        <TextView
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:layout_gravity="center_horizontal"
            android:gravity="center"
            android:text="CardView 阴影" />
    </androidx.cardview.widget.CardView>

.9 Figura Sombras

Los requisitos de diseño provienen del diseño, por lo que también es necesario encontrar una solución a partir del diseño: para usar la imagen .9, el diseño primero debe proporcionar la imagen original que se puede usar para hacer la imagen .9. El efecto se ha realizado en la imagen original, y solo necesitamos ser responsables de hacer la imagen .9.

Muchos diseños no deben proporcionar imágenes .9, por lo que a menudo necesitamos hacer imágenes .9 por nosotros mismos , no las haré aquí, porque las imágenes originales de cada persona son diferentes, por lo que es mejor dominar el método para hacer imágenes .9

项目:像我项目中这样的阴影背景布局(需要设计提供一张一半高度+自带阴影的背景图),.9图可自动拉伸

inserte la descripción de la imagen aquí


sombra de control personalizado

Cuando estaba buscando un control de sombra personalizado directamente en Baidu, encontré una biblioteca de tres partes en github y luego tomé una clase de control personalizado ShadowDrawable , que también se puede usar directamente después de la prueba.

Este control admite la configuración dinámica del color de la sombra, controlar las esquinas redondeadas, controlar el color de fondo, etc.

Representaciones oficiales

inserte la descripción de la imagen aquí

Clase personalizada ShadowDrawable , se puede copiar directamente

package com.example.kotlindemo;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;

public class ShadowDrawable extends Drawable {
    
    

    private Paint mShadowPaint;
    private Paint mBgPaint;
    private int mShadowRadius;
    private int mShape;
    private int mShapeRadius;
    private int mOffsetX;
    private int mOffsetY;
    private int mBgColor[];
    private RectF mRect;

    public final static int SHAPE_ROUND = 1;
    public final static int SHAPE_CIRCLE = 2;

    private ShadowDrawable(int shape, int[] bgColor, int shapeRadius, int shadowColor, int shadowRadius, int offsetX, int offsetY) {
    
    
        this.mShape = shape;
        this.mBgColor = bgColor;
        this.mShapeRadius = shapeRadius;
        this.mShadowRadius = shadowRadius;
        this.mOffsetX = offsetX;
        this.mOffsetY = offsetY;

        mShadowPaint = new Paint();
        mShadowPaint.setColor(Color.TRANSPARENT);
        mShadowPaint.setAntiAlias(true);
        mShadowPaint.setShadowLayer(shadowRadius, offsetX, offsetY, shadowColor);
        mShadowPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));

        mBgPaint = new Paint();
        mBgPaint.setAntiAlias(true);
    }

    @Override
    public void setBounds(int left, int top, int right, int bottom) {
    
    
        super.setBounds(left, top, right, bottom);
        mRect = new RectF(left + mShadowRadius - mOffsetX, top + mShadowRadius - mOffsetY, right - mShadowRadius - mOffsetX,
                bottom - mShadowRadius - mOffsetY);
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
    
    
        if (mBgColor != null) {
    
    
            if (mBgColor.length == 1) {
    
    
                mBgPaint.setColor(mBgColor[0]);
            } else {
    
    
                mBgPaint.setShader(new LinearGradient(mRect.left, mRect.height() / 2, mRect.right,
                        mRect.height() / 2, mBgColor, null, Shader.TileMode.CLAMP));
            }
        }

        if (mShape == SHAPE_ROUND) {
    
    
            canvas.drawRoundRect(mRect, mShapeRadius, mShapeRadius, mShadowPaint);
            canvas.drawRoundRect(mRect, mShapeRadius, mShapeRadius, mBgPaint);
        } else {
    
    
            canvas.drawCircle(mRect.centerX(), mRect.centerY(), Math.min(mRect.width(), mRect.height())/ 2, mShadowPaint);
            canvas.drawCircle(mRect.centerX(), mRect.centerY(), Math.min(mRect.width(), mRect.height())/ 2, mBgPaint);
        }
    }

    @Override
    public void setAlpha(int alpha) {
    
    
        mShadowPaint.setAlpha(alpha);
    }

    @Override
    public void setColorFilter(@Nullable ColorFilter colorFilter) {
    
    
        mShadowPaint.setColorFilter(colorFilter);
    }

    @Override
    public int getOpacity() {
    
    
        return PixelFormat.TRANSLUCENT;
    }

    public static void setShadowDrawable(View view, Drawable drawable) {
    
    
        view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        ViewCompat.setBackground(view, drawable);
    }

    /**
     * 为指定View添加阴影
     * @param view 目标View
     * @param shapeRadius View的圆角
     * @param shadowColor 阴影的颜色
     * @param shadowRadius 阴影的宽度
     * @param offsetX 阴影水平方向的偏移量
     * @param offsetY 阴影垂直方向的偏移量
     */
    public static void setShadowDrawable(View view, int shapeRadius, int shadowColor, int shadowRadius, int offsetX, int offsetY) {
    
    
        ShadowDrawable drawable = new ShadowDrawable.Builder()
                .setShapeRadius(shapeRadius)
                .setShadowColor(shadowColor)
                .setShadowRadius(shadowRadius)
                .setOffsetX(offsetX)
                .setOffsetY(offsetY)
                .builder();
        view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        ViewCompat.setBackground(view, drawable);
    }

    /**
     * 为指定View设置带阴影的背景
     * @param view 目标View
     * @param bgColor View背景色
     * @param shapeRadius View的圆角
     * @param shadowColor 阴影的颜色
     * @param shadowRadius 阴影的宽度
     * @param offsetX 阴影水平方向的偏移量
     * @param offsetY 阴影垂直方向的偏移量
     */
    public static void setShadowDrawable(View view, int bgColor, int shapeRadius, int shadowColor, int shadowRadius, int offsetX, int offsetY) {
    
    
        ShadowDrawable drawable = new ShadowDrawable.Builder()
                .setBgColor(bgColor)
                .setShapeRadius(shapeRadius)
                .setShadowColor(shadowColor)
                .setShadowRadius(shadowRadius)
                .setOffsetX(offsetX)
                .setOffsetY(offsetY)
                .builder();
        view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        ViewCompat.setBackground(view, drawable);
    }

    /**
     * 为指定View设置指定形状并带阴影的背景
     * @param view 目标View
     * @param shape View的形状 取值可为:GradientDrawable.RECTANGLE, GradientDrawable.OVAL, GradientDrawable.RING
     * @param bgColor View背景色
     * @param shapeRadius View的圆角
     * @param shadowColor 阴影的颜色
     * @param shadowRadius 阴影的宽度
     * @param offsetX 阴影水平方向的偏移量
     * @param offsetY 阴影垂直方向的偏移量
     */
    public static void setShadowDrawable(View view, int shape, int bgColor, int shapeRadius, int shadowColor, int shadowRadius, int offsetX, int offsetY) {
    
    
        ShadowDrawable drawable = new ShadowDrawable.Builder()
                .setShape(shape)
                .setBgColor(bgColor)
                .setShapeRadius(shapeRadius)
                .setShadowColor(shadowColor)
                .setShadowRadius(shadowRadius)
                .setOffsetX(offsetX)
                .setOffsetY(offsetY)
                .builder();
        view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        ViewCompat.setBackground(view, drawable);
    }

    /**
     * 为指定View设置带阴影的渐变背景
     * @param view
     * @param bgColor
     * @param shapeRadius
     * @param shadowColor
     * @param shadowRadius
     * @param offsetX
     * @param offsetY
     */
    public static void setShadowDrawable(View view, int[] bgColor, int shapeRadius, int shadowColor, int shadowRadius, int offsetX, int offsetY) {
    
    
        ShadowDrawable drawable = new ShadowDrawable.Builder()
                .setBgColor(bgColor)
                .setShapeRadius(shapeRadius)
                .setShadowColor(shadowColor)
                .setShadowRadius(shadowRadius)
                .setOffsetX(offsetX)
                .setOffsetY(offsetY)
                .builder();
        view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        ViewCompat.setBackground(view, drawable);
    }

    public static class Builder {
    
    
        private int mShape;
        private int mShapeRadius;
        private int mShadowColor;
        private int mShadowRadius;
        private int mOffsetX;
        private int mOffsetY;
        private int[] mBgColor;

        public Builder() {
    
    
            mShape = ShadowDrawable.SHAPE_ROUND;
            mShapeRadius = 12;
            mShadowColor = Color.parseColor("#4d000000");
            mShadowRadius = 18;
            mOffsetX = 0;
            mOffsetY = 0;
            mBgColor = new int[1];
            mBgColor[0] = Color.TRANSPARENT;
        }

        public Builder setShape(int mShape) {
    
    
            this.mShape = mShape;
            return this;
        }

        public Builder setShapeRadius(int ShapeRadius) {
    
    
            this.mShapeRadius = ShapeRadius;
            return this;
        }

        public Builder setShadowColor(int shadowColor) {
    
    
            this.mShadowColor = shadowColor;
            return this;
        }

        public Builder setShadowRadius(int shadowRadius) {
    
    
            this.mShadowRadius = shadowRadius;
            return this;
        }

        public Builder setOffsetX(int OffsetX) {
    
    
            this.mOffsetX = OffsetX;
            return this;
        }

        public Builder setOffsetY(int OffsetY) {
    
    
            this.mOffsetY = OffsetY;
            return this;
        }

        public Builder setBgColor(int BgColor) {
    
    
            this.mBgColor[0] = BgColor;
            return this;
        }

        public Builder setBgColor(int[] BgColor) {
    
    
            this.mBgColor = BgColor;
            return this;
        }

        public ShadowDrawable builder() {
    
    
            return new ShadowDrawable(mShape, mBgColor, mShapeRadius, mShadowColor, mShadowRadius, mOffsetX, mOffsetY);
        }
    }
}

Cómo utilizar

   var testView = findViewById<TextView>(R.id.test_view)
   /* 为指定View设置带阴影的背景
   * @param view 目标View
   * @param bgColor View背景色
   * @param shapeRadius View的圆角
   * @param shadowColor 阴影的颜色
   * @param shadowRadius 阴影的宽度
   * @param offsetX 阴影水平方向的偏移量
   * @param offsetY 阴影垂直方向的偏移量
   */
   ShadowDrawable.setShadowDrawable(
       testView, Color.parseColor("#FFFFFF"), 8,
       Color.parseColor("#992979FF"), 6, 0, 0
   ); }

GradientDrawable shadow (para uso propio del proyecto)

Se usa la función de extensión escrita por kt, y es muy conveniente llamar. Actualmente se usa en el proyecto, y la interfaz de usuario también ha pasado la aceptación.

Eché un breve vistazo, y el método utilizado actualmente en el proyecto es el Shape + GradientDrawablemejor método, porque fue escrito por el jefe de la empresa, y no he mirado cuidadosamente algunos códigos fuente. Las partes clave han sido extraídas y probadas. .normal después

Principalmente dividido en tres partes.

  • método de extensión de nivel superior de forma
  • ver el método de extensión de nivel superior
  • Cómo utilizar

因为具体阴影设置是在代码中统一设置,固相关效果查看总效果图即可

forma método de nivel superior

package com.example.kotlindemo

import android.graphics.drawable.GradientDrawable

typealias ColorInt = Int
typealias Px = Int
typealias FloatPx = Float

internal const val NO_GETTER = "Getter not available"

inline fun shapeDrawable(fill: GradientDrawable.() -> Unit): GradientDrawable =
    GradientDrawable().also {
    
    
        it.gradientType = GradientDrawable.LINEAR_GRADIENT
        it.fill()
    }

enum class Shape {
    
    
    RECTANGLE, OVAL, LINE, RING,
}

typealias ShapeInt = Int

fun toInt(s: Shape): ShapeInt = when (s) {
    
    
    Shape.RECTANGLE -> GradientDrawable.RECTANGLE
    Shape.OVAL -> GradientDrawable.OVAL
    Shape.LINE -> GradientDrawable.LINE
    Shape.RING -> GradientDrawable.RING
}

enum class Orientation {
    
    
    TOP_BOTTOM, TR_BL, RIGHT_LEFT, BR_TL, BOTTOM_TOP, BL_TR, LEFT_RIGHT, TL_BR,
}

private fun GradientDrawable.toOrientation(orientation: Orientation): GradientDrawable.Orientation =
    when (orientation) {
    
    
        Orientation.TOP_BOTTOM -> GradientDrawable.Orientation.TOP_BOTTOM
        Orientation.TR_BL -> GradientDrawable.Orientation.TR_BL
        Orientation.RIGHT_LEFT -> GradientDrawable.Orientation.RIGHT_LEFT
        Orientation.BR_TL -> GradientDrawable.Orientation.BR_TL
        Orientation.BOTTOM_TOP -> GradientDrawable.Orientation.BOTTOM_TOP
        Orientation.BL_TR -> GradientDrawable.Orientation.BL_TR
        Orientation.LEFT_RIGHT -> GradientDrawable.Orientation.LEFT_RIGHT
        Orientation.TL_BR -> GradientDrawable.Orientation.TL_BR
    }

var GradientDrawable.shapeEnum: Shape
    set(value) {
    
    
        shape = toInt(value)
    }
    @Deprecated(message = NO_GETTER, level = DeprecationLevel.HIDDEN) get() = error(NO_GETTER)

fun rectangleGradientShape(
    radius: FloatPx = Float.NaN,
    colors: IntArray,
    orientation: Orientation,
    fill: GradientDrawable.() -> Unit = {
    
    }
): GradientDrawable =
    shapeDrawable {
    
    
        shapeEnum = Shape.RECTANGLE
        setColors(colors)
        this.orientation = toOrientation(orientation)
        // DO NOT CHANGE
        // RADIUS AND COLOR ORDER IS IMPORTANT FOR RIPPLES!
        if (!radius.isNaN()) {
    
    
            cornerRadius = radius
        }
        fill.invoke(this)
    }

fun rectangleShape(
    radius: FloatPx = Float.NaN,
    color: ColorInt,
    size: Px? = null,
    fill: GradientDrawable.() -> Unit = {
    
    }
): GradientDrawable =
    shapeDrawable {
    
    
        shapeEnum = Shape.RECTANGLE
        solidColor = color
        size?.let {
    
    
            this.size = it
        }
        // DO NOT CHANGE
        // RADIUS AND COLOR ORDER IS IMPORTANT FOR RIPPLES!
        if (!radius.isNaN()) {
    
    
            cornerRadius = radius
        }
        fill.invoke(this)
    }

fun circleShape(color: ColorInt, size: Px? = null): GradientDrawable = shapeDrawable {
    
    
    shape = GradientDrawable.OVAL
    solidColor = color
    size?.let {
    
    
        this.size = it
    }
}

var GradientDrawable.solidColor: ColorInt
    set(value) = setColor(value)
    @Deprecated(message = NO_GETTER, level = DeprecationLevel.HIDDEN) get() = error(NO_GETTER)

var GradientDrawable.size: Px
    set(value) = setSize(value, value)
    get() = intrinsicWidth

class Stroke {
    
    
    var width: Px = -1
    var color: ColorInt = -1
    var dashWidth: FloatPx = 0F
    var dashGap: FloatPx = 0F
}

inline fun GradientDrawable.stroke(fill: Stroke.() -> Unit): Stroke = Stroke().also {
    
    
    it.fill()
    setStroke(it.width, it.color, it.dashWidth, it.dashGap)
}

class Size {
    
    
    var width: Px = -1
    var height: Px = -1
}

inline fun GradientDrawable.size(fill: Size.() -> Unit): Size = Size().also {
    
    
    fill(it)
    setSize(it.width, it.height)
}

class Corners {
    
    
    var radius: FloatPx = 0F

    var topLeft: FloatPx = Float.NaN
    var topRight: FloatPx = Float.NaN
    var bottomLeft: FloatPx = Float.NaN
    var bottomRight: FloatPx = Float.NaN

    internal fun FloatPx.orRadius(): FloatPx = takeIf {
    
     it >= 0 } ?: radius
}

fun Corners.render(): FloatArray = floatArrayOf(
    topLeft.orRadius(), topLeft.orRadius(),
    topRight.orRadius(), topRight.orRadius(),
    bottomRight.orRadius(), bottomRight.orRadius(),
    bottomLeft.orRadius(), bottomLeft.orRadius()
)

inline fun GradientDrawable.corners(fill: Corners.() -> Unit): Corners = Corners().also {
    
    
    it.fill()
    cornerRadii = it.render()
}

fun GradientDrawable.corners(
    radius: FloatPx = 0f,
    topLeft: FloatPx = Float.NaN,
    topRight: FloatPx = Float.NaN,
    bottomLeft: FloatPx = Float.NaN,
    bottomRight: FloatPx = Float.NaN
): Corners = Corners().also {
    
    
    it.radius = radius
    it.topLeft = topLeft
    it.topRight = topRight
    it.bottomLeft = bottomLeft
    it.bottomRight = bottomRight
    cornerRadii = it.render()
}

Ver funciones de extensión

package com.example.kotlindemo

import android.view.View
import androidx.core.graphics.toColorInt


fun View.warpInWhiteShadow(radius: Float = 0f, topLeft: Float = Float.NaN, topRight: Float = Float.NaN, bottomLeft: Float = Float.NaN, bottomRight: Float = Float.NaN) {
    
    
    background = rectangleShape(color = "#1AFFFFFF".toColorInt()) {
    
    
        corners(radius, topLeft, topRight, bottomLeft, bottomRight)
    }
    translationZ = 6f
}


//application的上下文,我这边demo就不复杂化了,主要是为了尺寸适配更好看一些
//inline val Int.dp: Int
//    get() = (this * AppContext.resources.displayMetrics.density + 0.5f).toInt()
//
//inline val Float.dp: Float
//    get() = (this * AppContext.resources.displayMetrics.density + 0.5f).toInt().toFloat()

Cómo utilizar

   //先设置底层的阴影背景
   var selfView = findViewById<TextView>(R.id.self_view)
   selfView.warpInWhiteShadow(topLeft = 6f, topRight = 6f)
   //再设置控件的背景
   selfView.background = rectangleShape(color = Color.WHITE) {
    
    
       corners(topLeft = 4f, topRight = 4f)
   }

resumen xml

Para evitar que algunos amigos vean xmlla configuración, se registra aquí

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical">

    <TextView
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        android:background="@drawable/shape_shadow"
        android:gravity="center"
        android:text="伪阴影" />

    <TextView
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:layout_gravity="center_horizontal"
        android:layout_margin="10dp"
        android:background="@drawable/layer_shadow"
        android:gravity="center"
        android:text="layer-list 阴影" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginBottom="10dp"
        android:background="@color/white"
        android:elevation="5dp"
        android:orientation="vertical"
        android:translationZ="1dp">

        <TextView
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:layout_gravity="center_horizontal"
            android:gravity="center"
            android:text="elevation 阴影" />
    </LinearLayout>

    <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="10dp"
        android:background="@color/white"
        android:translationZ="3dp"
        app:cardElevation="5dp">

        <TextView
            android:layout_width="100dp"
            android:layout_height="50dp"
            android:layout_gravity="center_horizontal"
            android:gravity="center"
            android:text="CardView 阴影" />
    </androidx.cardview.widget.CardView>

    <TextView
        android:id="@+id/test_view"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="自定义 阴影" />

    <TextView
        android:id="@+id/self_view"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="项目 阴影" />

</LinearLayout>

Guess you like

Origin blog.csdn.net/qq_20451879/article/details/131510444