王學崗高級UI7——————PathMeasur的使用(上)

PathMeasure
概念:路徑測量,一個用來測量path的工具類
常用API:Path長度測量,path跳轉,path片段獲取

效果一:

package com.example.testpathmeasure;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;

/**
 * @author writing
 * @time 2019/12/23 13:51
 * @note
 */
public class TestView extends View {

    private Paint deafultPaint;
    private Paint paint;
    private int viewWidth;
    private int viewHeight;

    public TestView(Context context) {
        super(context);
        init();

    }

    public TestView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();

    }

    public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();

    }


    public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();

    }

    private void init() {
        deafultPaint = new Paint();
        deafultPaint.setColor(Color.RED);
        deafultPaint.setStrokeWidth(10);
        deafultPaint.setStyle(Paint.Style.STROKE);

        paint = new Paint();
        paint.setColor(Color.DKGRAY);
        paint.setStrokeWidth(3);
        paint.setStyle(Paint.Style.STROKE);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        viewWidth = w;
        viewHeight = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //平移座標系
        canvas.translate(viewWidth / 2, viewHeight / 2);
        //畫座標線
        canvas.drawLine(-canvas.getWidth(), 0, canvas.getWidth(), 0, paint);
        canvas.drawLine(0, -canvas.getHeight(), 0, canvas.getHeight(), paint);
        testForceClosed(canvas);
    }

    private void testForceClosed(Canvas canvas) {
        Path path = new Path();
        path.lineTo(0, 200);
        path.lineTo(200, 200);
        path.lineTo(200, 0);
        //如果path是閉合狀態,那麼無論PathMeasure中的參數是true還是false,都是閉合狀態。
        //如果Path是非閉合狀態,那麼無論PathMeasure中的參數是true,則是閉合狀態,false則是非閉合狀態。
        PathMeasure pathMeasure1 = new PathMeasure(path, false);
        PathMeasure pathMeasure2 = new PathMeasure(path, true);
        Log.i("zhang_xin", "length of false:" + pathMeasure1.getLength());
        Log.i("zhang_xin", "length or true:" + pathMeasure2.getLength());
        canvas.drawPath(path, deafultPaint);
    }
}

看下打印輸出

2019-12-23 14:40:28.234 21174-21174/? I/zhang_xin: length of false:600.0
2019-12-23 14:40:28.234 21174-21174/? I/zhang_xin: length or true:800.0

效果二:

package com.example.testpathmeasure;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;

/**
 * @author writing
 * @time 2019/12/23 13:51
 * @note
 */
public class TestView extends View {

    private Paint deafultPaint;
    private Paint paint;
    private int viewWidth;
    private int viewHeight;

    public TestView(Context context) {
        super(context);
        init();

    }

    public TestView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();

    }

    public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();

    }


    public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();

    }

    private void init() {
        deafultPaint = new Paint();
        deafultPaint.setColor(Color.RED);
        deafultPaint.setStrokeWidth(10);
        deafultPaint.setStyle(Paint.Style.STROKE);

        paint = new Paint();
        paint.setColor(Color.DKGRAY);
        paint.setStrokeWidth(3);
        paint.setStyle(Paint.Style.STROKE);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        viewWidth = w;
        viewHeight = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //平移座標系
        canvas.translate(viewWidth / 2, viewHeight / 2);
        //畫座標線
        canvas.drawLine(-canvas.getWidth(), 0, canvas.getWidth(), 0, paint);
        canvas.drawLine(0, -canvas.getHeight(), 0, canvas.getHeight(), paint);
 
        testNextContour(canvas);
    }

    private void testNextContour(Canvas canvas) {
        Path path0 = new Path();
        Path path1 = new Path();
        Path path2 = new Path();
        //添加小矩形
        path1.addRect(-100,-100,100,100, Path.Direction.CW);
        PathMeasure pathMeasure1 = new PathMeasure(path1,false);
        Log.i("zhang_xin","path1:"+pathMeasure1.getLength());
        path2.addRect(-200,-200,200,200, Path.Direction.CW);
        /**
         * 對path1與path2進行布爾運算
         * XOP保留path1與path2不共同的部分
         */
        path0.op(path1,path2,Path.Op.XOR);
        canvas.drawPath(path0,deafultPaint);
        PathMeasure pathMeasure = new PathMeasure(path0,false);
        Log.i("zhang_xin","length of pathMeasure:"+pathMeasure.getLength());
    }

   
}

打印輸出

2019-12-23 15:24:54.646 26441-26441/com.example.testpathmeasure I/zhang_xin: path1:800.0
2019-12-23 15:24:54.646 26441-26441/com.example.testpathmeasure I/zhang_xin: length of pathMeasure:1600.0

在這裏插入圖片描述
繼續完善我們的代碼

package com.example.testpathmeasure;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;

/**
 * @author writing
 * @time 2019/12/23 13:51
 * @note
 */
public class TestView extends View {

    private Paint deafultPaint;
    private Paint paint;
    private int viewWidth;
    private int viewHeight;

    public TestView(Context context) {
        super(context);
        init();

    }

    public TestView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();

    }

    public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();

    }


    public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();

    }

    private void init() {
        deafultPaint = new Paint();
        deafultPaint.setColor(Color.RED);
        deafultPaint.setStrokeWidth(10);
        deafultPaint.setStyle(Paint.Style.STROKE);

        paint = new Paint();
        paint.setColor(Color.DKGRAY);
        paint.setStrokeWidth(3);
        paint.setStyle(Paint.Style.STROKE);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        viewWidth = w;
        viewHeight = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //平移座標系
        canvas.translate(viewWidth / 2, viewHeight / 2);
        //畫座標線
        canvas.drawLine(-canvas.getWidth(), 0, canvas.getWidth(), 0, paint);
        canvas.drawLine(0, -canvas.getHeight(), 0, canvas.getHeight(), paint);

        testNextContour(canvas);
    }

    private void testNextContour(Canvas canvas) {
        Path path0 = new Path();
        Path path1 = new Path();
        Path path2 = new Path();
        //添加小矩形
        path1.addRect(-100,-100,100,100, Path.Direction.CW);
        PathMeasure pathMeasure1 = new PathMeasure(path1,false);
        Log.i("zhang_xin","path1:"+pathMeasure1.getLength());
        path2.addRect(-200,-200,200,200, Path.Direction.CW);
        Log.i("zhang_xin","path2:"+pathMeasure1.getLength());
        /**
         * 對path1與path2進行布爾運算
         * XOP保留path1與path2不共同的部分
         */
        path0.op(path1,path2,Path.Op.XOR);
        canvas.drawPath(path0,deafultPaint);
        PathMeasure pathMeasure = new PathMeasure(path0,false);
        Log.i("zhang_xin","length of pathMeasure:"+pathMeasure.getLength());

        float[] tan = new float[2];
        float[] pos = new float[2];
        /**
         * diatance 指定Path路徑上的長度
         * 兩個長度爲2的浮點數組,這個數組是用來接收數據
         * tan 當前位置的正切點的XY
         * pos 當前Path路徑點的XY
         */
        pathMeasure.getPosTan(50f,pos,tan);
        canvas.drawLine(tan[0],tan[1],pos[0],pos[1],paint);
        Log.i("zhang_xin","tan[0]:"+tan[0]+",tan[1]:"+tan[1]+",pos[0]:"+pos[0]+",pos[1]:"+pos[1]);
        //獲取path的長度
        float len1 = pathMeasure.getLength();
        //跳轉到下一個路徑,由大矩形跳轉到小矩形,大矩形與小矩形通過path.op()連接在一起
        pathMeasure.nextContour();
        pathMeasure.getPosTan(50f,pos,tan);
        Log.i("zhang_xin","tan[0]:"+tan[0]+",tan[1]:"+tan[1]+",pos[0]:"+pos[0]+",pos[1]:"+pos[1]);
        canvas.drawLine(tan[0],tan[1],pos[0],pos[1],deafultPaint);
        float len2 = pathMeasure.getLength();
        Log.i("zhang_xin","len1:"+len1);
        Log.i("zhang_xin","len2:"+len2);
    }


}

看下打印輸出

2019-12-23 16:45:57.299 32583-32583/com.example.testpathmeasure I/zhang_xin: path1:800.0
2019-12-23 16:45:57.300 32583-32583/com.example.testpathmeasure I/zhang_xin: path2:1600.0
2019-12-23 16:45:57.301 32583-32583/com.example.testpathmeasure I/zhang_xin: length of pathMeasure:1600.0
2019-12-23 16:45:57.302 32583-32583/com.example.testpathmeasure I/zhang_xin: tan[0]:-1.0,tan[1]:0.0,pos[0]:150.0,pos[1]:-200.0
2019-12-23 16:45:57.302 32583-32583/com.example.testpathmeasure I/zhang_xin: tan[0]:-1.0,tan[1]:0.0,pos[0]:50.0,pos[1]:-100.0
2019-12-23 16:45:57.302 32583-32583/com.example.testpathmeasure I/zhang_xin: len1:1600.0
2019-12-23 16:45:57.303 32583-32583/com.example.testpathmeasure I/zhang_xin: len2:800.0

在這裏插入圖片描述

效果三

package com.example.testpathmeasure;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;

/**
 * @author writing
 * @time 2019/12/23 13:51
 * @note
 */
public class TestView extends View {

    private Paint deafultPaint;
    private Paint paint;
    private int viewWidth;
    private int viewHeight;

    public TestView(Context context) {
        super(context);
        init();

    }

    public TestView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();

    }

    public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();

    }


    public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();

    }

    private void init() {
        deafultPaint = new Paint();
        deafultPaint.setColor(Color.RED);
        deafultPaint.setStrokeWidth(10);
        deafultPaint.setStyle(Paint.Style.STROKE);

        paint = new Paint();
        paint.setColor(Color.DKGRAY);
        paint.setStrokeWidth(3);
        paint.setStyle(Paint.Style.STROKE);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        viewWidth = w;
        viewHeight = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //平移座標系
        canvas.translate(viewWidth / 2, viewHeight / 2);
        //畫座標線
        canvas.drawLine(-canvas.getWidth(), 0, canvas.getWidth(), 0, paint);
        canvas.drawLine(0, -canvas.getHeight(), 0, canvas.getHeight(), paint);

        testGetSegment(canvas);
    }

    private void testGetSegment(Canvas canvas) {
        Path path = new Path();
        //添加一個順時針的矩形
        path.addRect(-200,-200,200,200, Path.Direction.CW);
        Path dst = new Path();
        //Path 與 PathMeasure關聯
        PathMeasure pathMeasure = new PathMeasure();
        pathMeasure.setPath(path,true);
        //截取一部分保存到dst中,並使用moveTo保持截取到的Path第一個點的位置不變
        pathMeasure.getSegment(200,600,dst,true);
        canvas.drawPath(path,paint);
        canvas.drawPath(dst,deafultPaint);
    }


}

在這裏插入圖片描述

效果四

看下true與false的區別

package com.example.testpathmeasure;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;

/**
 * @author writing
 * @time 2019/12/23 13:51
 * @note
 */
public class TestView extends View {

    private Paint deafultPaint;
    private Paint paint;
    private int viewWidth;
    private int viewHeight;

    public TestView(Context context) {
        super(context);
        init();

    }

    public TestView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();

    }

    public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();

    }


    public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();

    }

    private void init() {
        deafultPaint = new Paint();
        deafultPaint.setColor(Color.RED);
        deafultPaint.setStrokeWidth(10);
        deafultPaint.setStyle(Paint.Style.STROKE);

        paint = new Paint();
        paint.setColor(Color.DKGRAY);
        paint.setStrokeWidth(3);
        paint.setStyle(Paint.Style.STROKE);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        viewWidth = w;
        viewHeight = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //平移座標系
        canvas.translate(viewWidth / 2, viewHeight / 2);
        //畫座標線
        canvas.drawLine(-canvas.getWidth(), 0, canvas.getWidth(), 0, paint);
        canvas.drawLine(0, -canvas.getHeight(), 0, canvas.getHeight(), paint);
        testGetSegmentMoveTo(canvas);
    }

    private void testGetSegmentMoveTo(Canvas canvas) {
        Path path = new Path();
        path.addRect(-200,-200,200,200, Path.Direction.CW);
        Path dst = new Path();
        dst.lineTo(300,300);
        
        PathMeasure pathMeasure = new PathMeasure(path,false);
        //tru與fasle會產生兩種不同的效果
        pathMeasure.getSegment(200,600,dst,true/false);
        canvas.drawPath(path,paint);
        canvas.drawPath(dst,deafultPaint);
    }
}

爲true的時候
在這裏插入圖片描述
爲false的時候
在這裏插入圖片描述

對PathMeasure中getPosTan不理解的可以看這篇文章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章