android - 贝塞尔曲线自定义 View 的阴影效果

标签 android android-canvas android-custom-view

如何在弯曲的自定义 View 组底部添加阴影效果?我正在实现贝塞尔曲线路径以将底部曲线添加到矩形形状。我想添加一个平行于弯曲底部边缘的底部阴影,任何人都可以建议这样做的方法吗?

class CurveContainer : ConstraintLayout{

var mainPaint = Paint()
var mShadowPaint = Paint()
var mainPath = Path()

var xWidth = 0f
var xHeight = 0f
var biezerYValue = 50

constructor(context: Context?) : super(context){
    init()
}
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
    init()
}
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr){
    init()
}


open fun setBiezerY(y : Int){
    biezerYValue = y
    invalidate()
}

private fun init() {
    mainPaint.color = ContextCompat.getColor(context, R.color.showContainer)
    mainPaint.style = Paint.Style.FILL
    mainPaint.isAntiAlias = true
}


override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    xWidth = measuredWidth.toFloat()
    xHeight = measuredHeight.toFloat()
    invalidate()
}

override fun onDraw(canvas: Canvas?) {
    super.onDraw(canvas)
    mainPath.reset()
    canvas!!.drawColor(Color.TRANSPARENT)

    mainPath.moveTo(0f, 0f)
    mainPath.lineTo(xWidth, 0f)
    mainPath.lineTo(xWidth, xHeight - biezerYValue)
    mainPath.quadTo(xWidth/2, xHeight + biezerYValue - 10, 0f, xHeight - biezerYValue)
    mainPath.lineTo(0f, 0f)
    canvas!!.drawPath(mainPath, mainPaint)
}
}

这是它目前的样子 enter image description here

最佳答案

你可以做的是在原始形状下方绘制相同的形状,但使用 BlurMaskFilter,我稍微重构了你的类,但结果看起来很有希望

class CurveContainer @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
    : ConstraintLayout(context, attrs, defStyleAttr) {

    private val mainPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = 0xffff0000.toInt()
        style = Paint.Style.FILL
    }

    private val shadowPaint = Paint(Paint.ANTI_ALIAS_FLAG.or(Paint.DITHER_FLAG)).apply {
        color = 0xff000000.toInt()
        style = Paint.Style.FILL
        maskFilter = BlurMaskFilter(32f, BlurMaskFilter.Blur.OUTER)
    }

    private val mainPath = Path()
    private val shadowPath = Path()

    private var bezierEdgeY = 0f
    private var bezierHandleY = 0f

    private var edgePercentY = 0.25f
    private var handlePercentY = 0.5f

    init {
        setWillNotDraw(false)
        setLayerType(View.LAYER_TYPE_SOFTWARE, shadowPaint)
    }

    fun setBezierPositionPercent(edgePercentY: Float, handlePercentY: Float) {
        this.edgePercentY = edgePercentY
        this.handlePercentY = handlePercentY
        computePath(width.toFloat(), height.toFloat())
    }

    private fun computePath(width: Float, height: Float) {
        bezierEdgeY = height * 0.25f
        bezierHandleY = height * 0.5f

        val halfWidth = width / 2

        shadowPath.reset()
        shadowPath.moveTo(0f, 0f)
        shadowPath.lineTo(width, 0f)
        shadowPath.lineTo(width, bezierEdgeY)
        shadowPath.quadTo(halfWidth, bezierHandleY, 0f, bezierEdgeY)
        shadowPath.lineTo(0f, 0f)

        mainPath.reset()
        mainPath.moveTo(0f, 0f)
        mainPath.lineTo(width, 0f)
        mainPath.lineTo(width, bezierEdgeY)
        mainPath.quadTo(halfWidth, bezierHandleY, 0f, bezierEdgeY)
        mainPath.lineTo(0f, 0f)

        invalidate()
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        computePath(w.toFloat(), h.toFloat())
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        canvas.drawPath(shadowPath, shadowPaint)
        canvas.drawPath(mainPath, mainPaint)
    }
}

curve with shadow

关于android - 贝塞尔曲线自定义 View 的阴影效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48977846/

相关文章:

Android-更改 fragment 时将 ImageView 中的图像保留在 fragment 上

android - 当我在jetpack-compose中的canvas中使用drawText并设置textStyle时,位置偏离中心

Android在自定义 View 上仅在一侧绘制矩形

java - Android-获取customListview中第一行的值(共享首选项)

android - URL 解码器不工作

android - FragmentPagerAdapter getItem() 的返回值超过了应有的值

java - 找不到符号方法 setAnimationListener

java - 在另一个 View 上绘制外部 Canvas

android - 在自定义 View 中设置 textSize 会产生巨大的文本

android - 凹轮廓上的 Lollipop 高度