Android绘制一条宽度逐渐变大的路径

来源:互联网 发布:sqlserver导出csv文件 编辑:程序博客网 时间:2024/05/17 22:13

1.介绍

  • 先看一下效果图

用过电脑版印象笔记演示功能的应该知道这个效果,现在想在手机上实现一下,当然这个是最终的目标,这篇只是介绍实现过程中的一步 —— 绘制一条宽度逐渐变大的路径

2.实现

2.1完成图

这里写图片描述

2.2思路

把一条路径分成很多段,每段path首尾相连,然后依次设置每一段path的宽度,把这些path存储在一个集合中,最后依次绘制出来。

这种方法实现的问题主要是如果截取的段太少,在拐角处显示不圆滑,锯齿严重,所以定义了DEFAULT_SEGMENT_LENGTH来控制截取长度,长度越小,锯齿度越小,拐角处越圆滑。对于这个问题,如有更好的思路,请告诉我。

2.3把一条path分成多段path的方法

这里要使用到PathMeasure,PathMeasure的getSegment方法就是获取一段path,

public boolean getSegment (float startD, float stopD, Path dst, boolean startWithMoveTo)

startD 表示从path某个长度位置开始
stopD 表示某个长度位置结束
dst 表示截取后的path
startWithMoveTo 表示这个截取的path开始位置是否移动到截取的开始位置,false的话,path开始点位置是(0,0),这里需要设置为true,不然达不到首尾相连的效果

对于path长度的获取,PathMeasure有相应的方法getLength();

2.4截取路径的方法实现

/**     * 截取path     * @param path     */    private void getPaths(Path path){        PathMeasure pm = new PathMeasure(path, false);        float length = pm.getLength();        int segmentSize = (int) Math.ceil(length / DEFAULT_SEGMENT_LENGTH);        Path ps = null;        PathSegment pe = null;        int nowSize = pathSegments.size();//集合中已经有的        if(nowSize == 0){            ps = new Path();            pm.getSegment(0, length, ps, true);            pe = new PathSegment(ps);            pe.setAlpha(255);            pe.setWidth(DEFAULT_WIDTH);            pathSegments.add(pe);        } else{            for (int i = nowSize; i < segmentSize; i++) {                ps = new Path();                pm.getSegment((i - 1) * DEFAULT_SEGMENT_LENGTH - 0.4f, Math.min(i * DEFAULT_SEGMENT_LENGTH, length), ps,  true);                pe = new PathSegment(ps);                pe.setAlpha(255);                pe.setWidth((float) Math.min(MAX_WIDTH, i * 0.3 + DEFAULT_WIDTH));                pathSegments.add(pe);            }        }    }

3.完整代码

public class TailView2 extends View{    private Paint paint;    private Path mFingerPath;    private float mOriginX;    private float mOriginY;    private List<PathSegment> pathSegments;    private class PathSegment{        Path path;        float width;        int alpha;        public PathSegment(Path path) {            this.path = path;        }        public Path getPath() {            return path;        }        public void setPath(Path path) {            this.path = path;        }        public float getWidth() {            return width;        }        public void setWidth(float width) {            this.width = width;        }        public int getAlpha() {            return alpha;        }        public void setAlpha(int alpha) {            this.alpha = alpha;        }    }    public TailView2(Context context) {        this(context, null, 0);    }    public TailView2(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public TailView2(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        paint = new Paint(Paint.ANTI_ALIAS_FLAG);        paint.setStyle(Paint.Style.STROKE);        paint.setColor(Color.RED);        //-------------------------------------------------        mFingerPath = new Path();        pathSegments = new ArrayList<>();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        for (PathSegment p: pathSegments) {            paint.setAlpha(p.getAlpha());            paint.setStrokeWidth(p.getWidth());            canvas.drawPath(p.getPath(), paint);        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        float x = event.getX();        float y = event.getY();        switch (event.getAction()){            case MotionEvent.ACTION_DOWN:                pathSegments.clear();                mOriginX = x;                mOriginY = y;                mFingerPath.reset();                mFingerPath.moveTo(mOriginX, mOriginY);                break;            case MotionEvent.ACTION_MOVE:                getPaths(mFingerPath);                mFingerPath.lineTo(x, y);                break;            case MotionEvent.ACTION_UP:                break;        }        invalidate();        return true;    }    /**     * 越小,线条锯齿度越小     */    private static final float DEFAULT_SEGMENT_LENGTH = 10F;    private static final float DEFAULT_WIDTH = 3F;    private static final float MAX_WIDTH = 45F;    /**     * 截取path     * @param path     */    private void getPaths(Path path){        PathMeasure pm = new PathMeasure(path, false);        float length = pm.getLength();        int segmentSize = (int) Math.ceil(length / DEFAULT_SEGMENT_LENGTH);        Path ps = null;        PathSegment pe = null;        int nowSize = pathSegments.size();//集合中已经有的        if(nowSize == 0){            ps = new Path();            pm.getSegment(0, length, ps, true);            pe = new PathSegment(ps);            pe.setAlpha(255);            pe.setWidth(DEFAULT_WIDTH);            pathSegments.add(pe);        } else{            for (int i = nowSize; i < segmentSize; i++) {                ps = new Path();                pm.getSegment((i - 1) * DEFAULT_SEGMENT_LENGTH - 0.4f, Math.min(i * DEFAULT_SEGMENT_LENGTH, length), ps,  true);                pe = new PathSegment(ps);                pe.setAlpha(255);                pe.setWidth((float) Math.min(MAX_WIDTH, i * 0.3 + DEFAULT_WIDTH));                pathSegments.add(pe);            }        }    }}
2 0
原创粉丝点击