您的位置:首页 > 移动开发 > Android开发

Android 自定义View——Path的使用

2015-09-17 18:59 531 查看
  Path, 轨迹,路径。Path可以沿着多个点绘制一条路径, 在Canvas中可以根据Path绘制不同的图形。

Path

我们在使用Path绘制路径,一般要使用到以下几个方法:

moveTo(float x, float y):

  移动到(x, y)坐标点。绘制路径时,路径的第一个点一般我们通过moveTo()来决定,否则默认为(0, 0)点。

lineTo(float x, float y):

  从当前点绘制直线到(x, y)点。这个与moveTo()不同,moveTo()是指跳转到(x, y)点,而不绘制连线。

close():

  将路径封闭。举例来说,我们绘制一个三角形,三角形的三个点是(0, 0,),(100, 0),(0, 100)我们使用lineTo将(0, 0,),(100, 0)连接,(100, 0),(0, 100)连接,这样还差(0, 0,),(0, 100)之间的连线,这时我们可以直接调用close()方法,这样就会直接将图形封闭构成三角形。

quadTo(float x1, float y1, float x2, float y2):

  绘制贝塞尔曲线,贝塞尔曲线是由三个点控制的:起始点,终止点,控制点。在该方法中,前两个参数是控制点的坐标,后两个参数是终止点坐标。

  

  Path中我们可以通过点来绘制路径也可以通过addXXX()方法来绘制,Path中给我们提供了很多这样的方法来添加不同的路径:

[thead]
[/thead]
方法用途
addArc(RectF oval, float startAngle, float sweepAngle)添加圆弧轨迹
addCircle(float x, float y, float radius, Path.Direction dir)添加圆形轨迹
addOval(float left, float top, float right, float bottom, Path.Direction dir)添加椭圆轨迹
addRect(float left, float top, float right, float bottom, Path.Direction dir)添加矩形轨迹
addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Path.Direction dir)添加椭圆角矩形轨迹
  

  以上方法与Canvas构建圆形,弧形,椭圆等图形方法的使用是差不多的,我们这里不再赘述。下面来几个小练习,练习下Path的使用。

Path的使用

绘制三角形

public class MyPathView extends View {
    private int width;//设置高
    private int height;//设置高

    private Path mPath;
    private Paint mPaint;
    public MyPathView(Context context) {
        super(context);
    }

    public MyPathView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 初始化path
        mPath = new Path();
        //初始化画笔
        mPaint = new Paint();
        mPaint.setAntiAlias(true); //抗锯齿
        mPaint.setColor(Color.LTGRAY);
        mPaint.setStrokeWidth(5);
        mPaint.setStyle(Paint.Style.STROKE);//非填充

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);//设置宽和高
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画三角形
        mPath.moveTo(100, 100);
        mPath.lineTo(0, 200);
        mPath.lineTo(200, 200);
        mPath.close();
        canvas.drawPath(mPath, mPaint);
    }
}




书写文字沿圆形轨迹

public class MyPathView extends View {
    private int width;//设置高
    private int height;//设置高

    private Path mPath;
    private Paint mPaintCircle;

    public MyPathView(Context context) {
        super(context);
    }

    public MyPathView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 初始化path
        mPath = new Path();
        //初始化画笔
        mPaint = new Paint();
        mPaint.setAntiAlias(true); //抗锯齿
        mPaint.setTextSize(30);
        mPaint.setColor(Color.BLACK);
        mPaint.setStrokeWidth(3);
        mPaint.setStyle(Paint.Style.STROKE);//非填充
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);//设置宽和高
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //画圆形
        mPath.addCircle(width/2, height/2, 300, Path.Direction.CW);
        mPath.close();
        canvas.drawPath(mPath, mPaint);
        canvas.drawTextOnPath("我要沿着这个圆写一些文字", mPath,0,0, mPaint );
    }
}





  

绘制贝塞尔曲线

public class MyPathView extends View {
    private int width;//设置高
    private int height;//设置高

    private Path mPath;
    private Paint mPaint;
    private Paint mPaintPoint;

    public MyPathView(Context context) {
        super(context);
    }

    public MyPathView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 初始化path
        mPath = new Path();
        //初始化画笔
        mPaint = new Paint();
        mPaint.setAntiAlias(true); //抗锯齿
        mPaint.setTextSize(30);
        mPaint.setColor(Color.BLACK);
        mPaint.setStrokeWidth(3);
        mPaint.setStyle(Paint.Style.STROKE);//非填充

        //初始化画点的画笔
        mPaintPoint = new Paint();
        mPaintPoint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaintPoint.setStrokeWidth(10);

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);//设置宽和高
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPath.moveTo(100, 100);//确定贝塞尔曲线的第一个点
        mPath.quadTo(50, 400, 500, 400);//前两个参数确定控制点, 后两个参数确定结束点
        //绘制出起始点,终止点,以及控制点
        canvas.drawPoint(100, 100, mPaintPoint);
        canvas.drawPoint(50,400, mPaintPoint);
        canvas.drawPoint(500, 400, mPaintPoint);
        canvas.drawPath(mPath,mPaint);
    }
}




  Path路径还可以绘制更多各式各样的路径,这里不再一一练习。下面绘制一个波动的Path曲线。

  

绘制波动的Path曲线

  绘制波动的曲线,要是画面动起来就需要不断地调用onDraw方法绘制界面。但是onDraw是UI主线程不断调用重绘界面的,因此我们需要使用到Handler,通过发送一个消息给Handler对象,让Handler对象在每一秒重绘一次MyPathView控件。这里重绘不能调用onDraw()方法额,而要调用的是invalidate()方法,invalidate()方法中调用了onDraw()方法。

public class MyPathView extends View {
    private int width;//设置高
    private int height;//设置高

    private Path mPath;
    private Paint mPaint;
    private Paint mPaintCircle;

    private int count = 0;
    private static final int NEED_INVALIDATE = 0X6666;
    //操作UI主线程
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case NEED_INVALIDATE:
                    //更新时间
                    count += 5;
                    if (count > 80) {
                        count = 0;
                    }
                    invalidate();
                    sendEmptyMessageDelayed(NEED_INVALIDATE, 50);
                    break;
            }
        }
    };

    public MyPathView(Context context) {
        super(context);
    }

    public MyPathView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 初始化path
        mPath = new Path();
        //初始化画笔
        mPaint = new Paint();
        mPaint.setAntiAlias(true); //抗锯齿
        mPaint.setTextSize(30);
        mPaint.setColor(Color.BLACK);
        mPaint.setStrokeWidth(3);
        mPaint.setStyle(Paint.Style.STROKE);//非填充

        //初始化画点的画笔
        mPaintCircle = new Paint();
        mPaintCircle.setAntiAlias(true);
        mPaintCircle.setColor(Color.GRAY);
        mPaintCircle.setStyle(Paint.Style.STROKE);
        mPaintCircle.setStrokeWidth(10);
        handler.sendEmptyMessageDelayed(NEED_INVALIDATE, 50);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(width, height);//设置宽和高
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //绘制波浪形曲线
        mPath.reset();
        mPath.moveTo(count, height / 2);
        for (int i = 0; i < 10; i++) {
            mPath.rQuadTo(20, 5, 40, 0);//rQuadTo()方法是以当前点为起始点,将其视为(0,0)点绘制。这里也就是将
            mPath.rQuadTo(20, -5, 40, 0);
        }
        canvas.drawPath(mPath, mPaint);
        canvas.drawCircle(width / 2, height / 2, 50, mPaintCircle);

    }
}


  我们首先通过循环得到了贝塞尔曲线,这里得到贝塞尔曲线是通过rQuadTo()方法,这个方法,是将当前的点视为原点(0, 0),通过相对原点来绘制的曲线。绘制好贝塞尔曲线后,我们通过使用Handler通过count不断地更新起始点move(count, width),使得曲线看起来是移动的。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: