Android画板 半透明画笔 笔迹叠加效果

Android画板 半透明画笔 笔迹叠加效果,第1张

概述转载请注明出处:https://blog.csdn.net/kong_gu_you_lan/article/details/105572617本文出自容华谢后的博客0.写在前面先看下效果图,功能虽然简单,但是实现的时候谷歌、百度了很久也没有找到解决方案,提这个问题的人不少,但是回答的人一个也没有,十分郁闷,在此记录,分享给各位

转载请注明出处:https://blog.csdn.net/kong_gu_you_lan/article/details/105572617

本文出自 容华谢后的博客

0.写在前面

先看下效果图,功能虽然简单,但是实现的时候谷歌、百度了很久也没有找到解决方案,提这个问题的人不少,但是回答的人一个也没有,十分郁闷,在此记录,分享给各位。

1.半透明画笔

先按照常规的方法实现一个简单的画板

public class SketchpadVIEw extends VIEw {    private Paint mPaint;    private Path mPath;    private float mLastX;    private float mLastY;    private Bitmap mBufferBitmap;    private Canvas mBufferCanvas;    public SketchpadVIEw(Context context) {        this(context, null);    }    public SketchpadVIEw(Context context, @Nullable AttributeSet attrs) {        this(context, attrs, 0);    }    public SketchpadVIEw(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    private voID init() {        // 抗锯齿、防抖动        mPaint = new Paint(Paint.ANTI_AliAS_FLAG | Paint.DITHER_FLAG);        // 画笔模式为描边        mPaint.setStyle(Paint.Style.stroke);        // 拐角为圆角        mPaint.setstrokeJoin(Paint.Join.ROUND);        // 两端为圆角        mPaint.setstrokeCap(Paint.Cap.ROUND);        // 画笔宽度        mPaint.setstrokeWIDth(50);        // 画笔颜色        mPaint.setcolor(getResources().getcolor(R.color.colorAccent));        // 画笔透明度,先设置颜色,再设置透明度0-255        mPaint.setAlpha(80);        // 笔迹路径        mPath = new Path();    }    @OverrIDe    protected voID onSizeChanged(int w, int h, int olDW, int oldh) {        super.onSizeChanged(w, h, olDW, oldh);        // 双缓存机制        mBufferBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444);        mBufferCanvas = new Canvas(mBufferBitmap);    }    @OverrIDe    protected voID onDraw(Canvas canvas) {        super.onDraw(canvas);        if (mBufferBitmap != null) {            canvas.drawBitmap(mBufferBitmap, 0, 0, null);        }    }    @Suppresslint("ClickableVIEwAccessibility")    @OverrIDe    public boolean ontouchEvent(MotionEvent event) {        float x = event.getX();        float y = event.getY();        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                mLastX = x;                mLastY = y;                mPath.moveto(x, y);                break;            case MotionEvent.ACTION_MOVE:                mPath.quadTo(mLastX, mLastY, (x + mLastX) / 2, (y + mLastY) / 2);                mBufferCanvas.drawPath(mPath, mPaint);                mLastX = x;                mLastY = y;                invalIDate();                break;            case MotionEvent.ACTION_UP:                mPath.reset();                invalIDate();                break;        }        return true;    }}

注意:在初始化画笔的时候,我们给画笔设置了80的透明度,透明度一定要在颜色之后设置,因为颜色中也存在透明通道,会覆盖已设置的透明度。

// 画笔颜色mPaint.setcolor(getResources().getcolor(R.color.colorAccent));// 画笔透明度,先设置颜色,再设置透明度0-255mPaint.setAlpha(80);

看下效果:

咦,为什么还一段一段的颜色渐变?

这里需要了解下Paint类中的一个很重要的方法setXfermode(Xfermode xfermode),参数Xfermode有三个子类:AvoIDXfermode、PixelXorXfermode和PorterDuffXfermode,前两个类在API 16被遗弃了,重点看下PorterDuffXfermode这个类,PorterDuffXfermode类主要用于图形合成时的图像过渡模式计算,共有18种过渡模式,本文重点看下其中的两种模式SRC_OVER、SRC。

如果没有调用setXfermode方法,Paint绘制默认采用的是SRC_OVER模式,即先绘制第一笔,绘制第二笔时,第二笔与第一笔重合的部分,会进行叠加,颜色会变得越来越深。

这就解释了为什么上面的效果中,会出现一段一段的的颜色渐变笔迹,是因为半透明的笔迹叠加了,现在我们将模式修改为SRC,即重合的部分只显示第二笔,看下效果:

透明效果出来了,但是存在一个问题,就是每段笔迹重合的部分,没有叠加颜色变深的效果,继续往下看。

2.笔迹叠加

修改下代码:

public class SketchpadVIEw extends VIEw {    private Paint mPaint;    private Path mPath;    private float mLastX;    private float mLastY;    private Bitmap mBufferBitmap;    private Canvas mBufferCanvas;    public SketchpadVIEw(Context context) {        this(context, null);    }    public SketchpadVIEw(Context context, @Nullable AttributeSet attrs) {        this(context, attrs, 0);    }    public SketchpadVIEw(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    private voID init() {        // 抗锯齿、防抖动        mPaint = new Paint(Paint.ANTI_AliAS_FLAG | Paint.DITHER_FLAG);        // 画笔模式为描边        mPaint.setStyle(Paint.Style.stroke);        // 拐角为圆角        mPaint.setstrokeJoin(Paint.Join.ROUND);        // 两端为圆角        mPaint.setstrokeCap(Paint.Cap.ROUND);        // 画笔宽度        mPaint.setstrokeWIDth(50);        // 画笔颜色        mPaint.setcolor(getResources().getcolor(R.color.colorAccent));        // 画笔透明度,先设置颜色,再设置透明度0-255        mPaint.setAlpha(80);        // 笔迹路径        mPath = new Path();    }    @OverrIDe    protected voID onSizeChanged(int w, int h, int olDW, int oldh) {        super.onSizeChanged(w, h, olDW, oldh);        // 双缓存机制        mBufferBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444);        mBufferCanvas = new Canvas(mBufferBitmap);    }    @OverrIDe    protected voID onDraw(Canvas canvas) {        super.onDraw(canvas);        if (mBufferBitmap != null) {            canvas.drawBitmap(mBufferBitmap, 0, 0, null);        }        // 修改1        // ACTION_MOVE时,将笔迹临时绘制在画布上        canvas.drawPath(mPath, mPaint);    }    @Suppresslint("ClickableVIEwAccessibility")    @OverrIDe    public boolean ontouchEvent(MotionEvent event) {        float x = event.getX();        float y = event.getY();        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                mLastX = x;                mLastY = y;                mPath.moveto(x, y);                break;            case MotionEvent.ACTION_MOVE:                mPath.quadTo(mLastX, mLastY, (x + mLastX) / 2, (y + mLastY) / 2);                // 修改2                // 将绘制方法移到ACTION_UP中                mLastX = x;                mLastY = y;                invalIDate();                break;            case MotionEvent.ACTION_UP:            	// 修改3                // ACTION_UP时,将当前一笔的笔迹,绘制到缓存画布上                mBufferCanvas.drawPath(mPath, mPaint);                mPath.reset();                invalIDate();                break;        }        return true;    }}

修改后的代码,没有设置Paint的图像模式,默认为叠加状态,在ACTION_MOVE时,没有将笔迹实时绘制在缓存画布上,而是临时绘制在实际画布上,ACTION_UP时再将当前一笔的笔迹一次性绘制到缓存画布,然后再绘制到实际画布中,这样一笔一笔下来,就会产生叠加的笔迹效果了,看下最终效果:

3.写在最后

到这里半透明画笔的笔迹叠加效果就介绍完了,如有错误或者遗漏的地方可以给我留言评论,谢谢!

代码已上传至GitHub,欢迎Star、Fork!

GitHub地址:https://github.com/alIDili/Demos/tree/master/TranslucentPaintDemo

本文Demo的Apk下载地址:https://github.com/alIDili/Demos/raw/master/TranslucentPaintDemo/TranslucentPaintDemo.apk

总结

以上是内存溢出为你收集整理的Android画板 半透明画笔 笔迹叠加效果全部内容,希望文章能够帮你解决Android画板 半透明画笔 笔迹叠加效果所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1062217.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存