Android artboard半透明笔刷手写叠加效果

电脑杂谈  发布时间:2020-05-11 11:14:59  来源:网络整理

画图板 透明_透明pc板加工_白色透明pc板

本文来自谢荣华的博客

首先看效果图. 尽管功能很简单,但在实施时,谷歌和百度很久没有找到解决方案. 许问了这个问题,但没有一个人回答,非常沮丧,在此处记录以与您分享.

叠加效果

首先按照常规方法制作一个简单的绘图板:

白色透明pc板_画图板 透明_透明pc板加工

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-255
mPaint.setAlpha(80);

看看效果:

透明pc板加工_画图板 透明_白色透明pc板

颜色渐变

嗯,为什么每个部分都有颜色渐变?

在这里您需要了解Paint类中一个非常重要的方法setXfermode(Xfermode xfermode). 参数Xfermode具有三个子类: 避免Xfermode,PixelXorXfermode和PorterDuffXfermode. API 16中放弃了前两个类,重点放在PorterDuffXfermode类上,PorterDuffXfermode类主要用于图形合成期间的图像过渡模式计算. 共有18种转换模式. 本文重点介绍其中两个SRC_OVER和SRC.

如果未调用setXfermode方法,则默认情况下Paint使用SRC_OVER模式,即首先绘制第一个笔画,绘制第二个笔画时,第二个笔画与第一个笔画重合的部分将是叠加,颜色就会越来越深.

这解释了为什么在上述效果中会有一段颜色渐变笔迹,因为半透明笔迹是叠加的画图板 透明,所以现在我们将模式更改为SRC,即重叠部分仅显示第二笔画画图板 透明,请参见效果:

画图板 透明_白色透明pc板_透明pc板加工

没有叠加效果

出现了透明效果,但是存在一个问题,即每个笔迹重叠的部分没有使叠加颜色变暗的效果. 继续往下看.

修改以下代码:

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;
    }
}

白色透明pc板_画图板 透明_透明pc板加工

在未设置“绘制图像”模式的情况下,修改后的代码默认为叠加状态. 在ACTION_MOVE期间,手写内容不是实时绘制在缓存画布上,而是暂时绘制在实际画布上. 当ACTION_UP时,当前笔画一次将笔迹绘制到缓存画布上,然后再绘制到实际画布上,以便笔画的笔触将产生叠加的笔迹效果,请参见最终效果:

叠加效果

这里介绍了半透明笔刷的手写叠加效果. 如果有错误或遗漏,可以给我留言,谢谢!

该代码已上传到GitHub. 欢迎星与叉!

GitHub地址:

此演示的APK下载地址:


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/ruanjian/article-206262-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...