Android Paint 抗锯齿画线模糊

Android Paint 抗锯齿画线模糊,第1张

Android Paint 抗锯齿画线模糊 背景

Android 开发过程中, 或多或少会遇到需要使用自定义控件的情况, 而Paint作为画笔, 在整个开发过程中有着至关重要的地位, 用好它, 能让自定义控件展示出你期望效果, 用不好… 或许会抱怨, 这平台/这工具/这类怎么设计得如此难用.

就如同本文将要阐述的问题, 希望能给遇到相似问题的朋友一点帮助, 若无碰到此类问题, 请自行略过.

问题

先看一张效果图 (图1):

两个网图, 同样设置的笔画宽度为1 setStrokeWidth(1), 左边的显示的大小是正常的, 右边则变成了2. 颜色也淡了.

下面这张图看起来会很明显,(一个方格为一个PIXEL) (图2):

而程序设计时, 所期望的效果是: (图3):

WHY

大概也猜到了, 这可能跟设置了抗锯齿有关, 没错, 确实的这样子

        Paint paint;
        Paint paintAnti;
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            //无抗锯齿
            paint = createPaint(false, Color.GREEN);
            //设置了抗锯齿
            paintAnti = createPaint(true, Color.RED);
        }
        Paint createPaint(boolean anti, int color){
            Paint paint = new Paint(anti ? Paint.ANTI_ALIAS_FLAG : 0);
            paint.setColor(color);
            paint.setStyle(Paint.Style.STROKE);
            //设置同样的宽度.
            paint.setStrokeWidth(1);
            return paint;
        }
    

创建画笔的唯一区别就是设置了Paint.ANTI_ALIAS_FLAG, 那么这个问题其实很好解决, 把抗锯齿关了就可以了.

确实是这样.


继续

同样上面的红网模糊的代码, 加入一个功能, 通过触摸更新红网的位置,

		//添加直线.
        void addLine(Path p, float fx, float fy, float tx, float ty){
            p.moveTo(fx + startX, fy + startY);
            p.lineTo(tx + startX, ty + startY);
        }
		//更新Path.
        void update(){
            pathAnti.reset();
            float left = 60;
            float right = 110;
            float top = 0;
            float bottom = 0;
            for(int i = 1; i < 10; i ++) {
                top = bottom = i * interval;
                addLine(pathAnti, left, top, right, bottom);
            }
            top = 0;
            bottom = 50;
            for(int i = 1; i < 10; i ++) {
                left = right = 60 + i * interval;
                addLine(pathAnti, left, top , right, bottom);
            }
        }

        float startX, startY;
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            startX = event.getX()/30f;
            startY = event.getY()/30f;
            update();
            postInvalidate();
            return true;
        }

通过不停的触摸不同的位置并观察红网的效果, 发现一个现象,
当startX/startY的值, 去掉整数后, 剩下的小数值, 越接近0.5, 则线越实, 越接近期望的效果.

最接近期望效果 图4

于是, addLine稍微修改下:

        void addLine(Path p, float fx, float fy, float tx, float ty){
        	//取整, 再加上0.5, 得到的结果永远是 x.5;
            fx = (int)(fx + startX) + 0.5f;
            tx = (int)(tx + startX) + 0.5f;
            fy = (int)(fy + startY) + 0.5f;
            ty = (int)(ty + startY) + 0.5f;
            p.moveTo(fx, fy);
            p.lineTo(tx, ty);
        }

不管如何更新坐标, 显示的效果都如下图: 图5

			DashPathEffect dpe = new DashPathEffect(new float[]{3, 4}, 0);
            paint.setPathEffect(dpe);
            paintAnti.setPathEffect(dpe);

画个虚线 图6

最后

有点遗憾问题并不能够完美解决. 要能够彻底弄清楚是何原理, 估计得花不少精力去研究系统源码, 暂时没这时间精力, 只能听之任之, 坐等精于此道的先行者指点谜津. 共勉!

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

原文地址: https://outofmemory.cn/zaji/5686416.html

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

发表评论

登录后才能评论

评论列表(0条)

保存