Android 自定义TextView实现阴影效果(不占view空间)

之前写了Android 自定义圆角+阴影布局,虽然实现了阴影效果,但阴影需要考虑在布局内,无法实现像CardView那样阴影可以在布局外绘制。这篇为了解决阴影不能绘制在布局外的问题

实现布局外绘制阴影的思路

  1. 绘制view外部的阴影(其实就是扩大canvas绘制区域,让其超出view)
  2. 让view外部的阴影显示(父视图通过设置android:clipChildren="false",让view可以超出自身范围进行绘制)

 思路实现遇到的关键问题:如何绘制view外部阴影,又不影响view区域内的图像?

解决:

  1. 通过PorterDuffXfermode设置图像混合模式,裁剪掉阴影绘制区域在view区域内的图像 (实现后发现存在过度绘制问题)
  2. 使用canvas的clipPath(path,Region.Op),裁剪掉阴影绘制区域在view区域内的图像(虽然存在锯齿,但没有过度绘制问题)
  3. 将阴影区域绘制放于super.draw(canvas)之前,这样view将绘制在阴影区域之上,这样不用剪切阴影画笔填充区域了,同时可以设置阴影画笔颜色作为背景色,也没有锯齿问题

实现核心代码(第三种方案结合使用canvas的clipPath(path,Region.Op)):

    @Override
    public void draw(Canvas canvas) {
        ...
        //画阴影
        if (shadowElevation > 0) {
            Bitmap srcBmp = createShadowBitmap((int) (getWidth()+shadowElevation*2), (int) (getHeight()+shadowElevation*2));
            canvas.drawBitmap(srcBmp, shadow_x-shadowElevation, shadow_y-shadowElevation, clipShadowPaint);
        }   
    } 

    //添加阴影bitmap
    private Bitmap createShadowBitmap(int shadowWidth, int shadowHeight) {
        Bitmap output = Bitmap.createBitmap(shadowWidth, shadowHeight, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        shadowRect.set(shadowElevation-shadow_x,shadowElevation-shadow_y,shadowWidth-shadowElevation-shadow_x,shadowHeight-shadowElevation-shadow_y);

        shadowPaint.setColor(shadowColor);
        if (!isInEditMode()) {
            shadowPaint.setShadowLayer(shadowElevation, shadow_x, shadow_y, shadowColor);
        }
        shadowPath.reset();
        shadowPath.addRoundRect(shadowRect, radiusShadowArray, Path.Direction.CW);
        if (clipShadowPath) {
            //保留shadowPath路径以外区域
            canvas.clipPath(shadowPath, Region.Op.DIFFERENCE);
        }
        canvas.drawPath(shadowPath, shadowPaint);

        return output;
    }

 

效果图:

 源码:https://github.com/wudengwei/TextStrongView

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值