You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio 中如何为形状添加可自定义参数的投影效果

Android 匹配Adobe XD参数的自定义投影实现方案

下面分两种适配场景给出可直接复用的实现:

方案1:系统原生API实现(Android 9.0+ 适用)

该方案直接用系统自带的阴影能力,不需要自定义View,参数可直接对应XD的投影设置:

  • 投影颜色:对应系统的outlineAmbientShadowColor和outlineSpotShadowColor,两个参数设为相同即可匹配XD的纯色投影
  • x/y轴偏移:对应View的translationX/translationY属性
  • 模糊度:对应View的elevation属性,XD的模糊数值可按1:1转dp后赋值,不满意可微调

代码示例:

// 目标View为需要加投影的形状View
shapeView.apply {
    // 先设置形状背景,示例为圆角矩形
    background = GradientDrawable().apply {
        shape = GradientDrawable.RECTANGLE
        cornerRadius = 16.dpToPx() // 替换为你的圆角尺寸
        setColor(Color.WHITE) // 替换为你的形状填充色
    }
    clipToOutline = false
    outlineProvider = ViewOutlineProvider.BACKGROUND
    // 对应XD投影参数设置
    elevation = 8.dpToPx() // 模糊度
    translationX = 2.dpToPx() // x轴偏移
    translationY = 4.dpToPx() // y轴偏移
    // 设置投影颜色
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        outlineAmbientShadowColor = Color.parseColor("#33000000") // 替换为你的XD投影色
        outlineSpotShadowColor = Color.parseColor("#33000000")
    }
}

// dp转px扩展方法
fun Int.dpToPx() = TypedValue.applyDimension(
    TypedValue.COMPLEX_UNIT_DIP, 
    this.toFloat(), 
    Resources.getSystem().displayMetrics
)

方案2:自定义绘制实现(全安卓版本兼容)

如果需要兼容Android 9以下版本,或者需要100%还原XD的异形投影效果,直接用自定义View绘制:

  • 所有参数完全和XD一一对应,支持任意形状投影
  • 只需要给View预留足够的padding避免投影被裁剪即可,预留尺寸 = 最大偏移量 + 模糊半径

自定义View代码示例:

class XDShadowShapeView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    // 可外部直接修改的投影参数,完全对应XD配置
    var shadowColor = Color.parseColor("#33000000")
        set(value) {
            field = value
            invalidate()
        }
    var shadowOffsetX = 2f.dpToPx()
        set(value) {
            field = value
            invalidate()
        }
    var shadowOffsetY = 4f.dpToPx()
        set(value) {
            field = value
            invalidate()
        }
    var shadowBlur = 8f.dpToPx()
        set(value) {
            field = value
            blurFilter = BlurMaskFilter(value, BlurMaskFilter.Blur.NORMAL)
            invalidate()
        }
    var shapeCornerRadius = 16f.dpToPx()
        set(value) {
            field = value
            invalidate()
        }
    var shapeFillColor = Color.WHITE
        set(value) {
            field = value
            invalidate()
        }

    private val shadowPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val shapePaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private var blurFilter: BlurMaskFilter? = null

    init {
        // BlurMaskFilter需要关闭硬件加速
        setLayerType(LAYER_TYPE_SOFTWARE, null)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        val left = paddingLeft.toFloat()
        val top = paddingTop.toFloat()
        val right = width - paddingRight.toFloat()
        val bottom = height - paddingBottom.toFloat()

        // 先绘制底层投影
        shadowPaint.apply {
            color = shadowColor
            maskFilter = blurFilter
        }
        canvas.drawRoundRect(
            left + shadowOffsetX,
            top + shadowOffsetY,
            right + shadowOffsetX,
            bottom + shadowOffsetY,
            shapeCornerRadius,
            shapeCornerRadius,
            shadowPaint
        )

        // 再绘制上层形状
        shapePaint.color = shapeFillColor
        canvas.drawRoundRect(left, top, right, bottom, shapeCornerRadius, shapeCornerRadius, shapePaint)
    }

    private fun Float.dpToPx() = TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        this,
        Resources.getSystem().displayMetrics
    )
}

注意事项

  • 自定义绘制方案如果需要实现异形投影,只要把drawRoundRect替换为drawPath方法绘制对应的路径即可,投影会完全跟随形状轮廓
  • 如果需要实现带透明度的投影,直接给shadowColor设置对应alpha值即可,和XD的颜色透明度设置完全匹配

内容的提问来源于stack exchange,提问作者Barrow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 15:09:03