美文网首页高级UI
Android高级UI——PathMeasure和Matrix

Android高级UI——PathMeasure和Matrix

作者: 谢俊烽 | 来源:发表于2019-11-03 12:21 被阅读0次

需求是做一个箭头转圈圈的动画

image
image.png

public class PathMeasureView extends View {
    private float currentValue = 0;     // 用于纪录当前的位置,取值范围[0,1]映射Path的整个长度
    private Bitmap mBitmap;             // 箭头图片
    private Matrix mMatrix;             // 矩阵,用于对图片进行一些操作
    private Paint mDeafultPaint;
    private int mViewWidth;
    private int mViewHeight;
    private Paint mPaint;

    public PathMeasureView(Context context) {
        super(context);
        init(context);
    }

    private void init(Context context) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 8;       // 缩放图片
        mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.arrow, options);
        mMatrix = new Matrix();

        mDeafultPaint = new Paint();
        mDeafultPaint.setColor(Color.RED);
        mDeafultPaint.setStrokeWidth(5);
        mDeafultPaint.setStyle(Paint.Style.STROKE);

        mPaint = new Paint();
        mPaint.setColor(Color.DKGRAY);
        mPaint.setStrokeWidth(2);
        mPaint.setStyle(Paint.Style.STROKE);
    }

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

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);
        // 平移坐标系
        canvas.translate(mViewWidth/2,mViewHeight/2);
        // 画坐标线
        canvas.drawLine(-canvas.getWidth(),0,canvas.getWidth(),0,mPaint);
        canvas.drawLine(0,-canvas.getHeight(),0,canvas.getHeight(),mPaint);

        Path path = new Path();                                 // 创建 Path
        /**
         * Path.Direction.CCW 逆时针
         * Path.Direction.CW 顺时针
         */
        path.addCircle(0, 0, 200, Path.Direction.CCW);           // 添加一个圆形
        PathMeasure measure = new PathMeasure(path, false);     // 创建 PathMeasure

//        currentValue += 0.005;                                  // 计算当前的位置在总长度上的比例[0,1]
//        if (currentValue >= 1) {
//            currentValue = 0;
//        }


        // 获取当前位置的坐标以及趋势的矩阵
        measure.getMatrix(measure.getLength() * currentValue, mMatrix,
        PathMeasure.TANGENT_MATRIX_FLAG | PathMeasure.POSITION_MATRIX_FLAG);
        // 将图片绘制中心调整到与当前点重合(偏移加旋转)
//        mMatrix.preTranslate(-mBitmap.getWidth() / 2, -mBitmap.getHeight() / 2);
        canvas.drawPath(path, mDeafultPaint);
        canvas.drawBitmap(mBitmap, mMatrix, mDeafultPaint);

        invalidate();
    }
}

画好坐标轴之后把图片加入到圆圈起点,发现图片选择旋转了90度


image.png
 mMatrix.preTranslate(-mBitmap.getWidth() / 2, 0);

使图片进行dx的反方向偏移,偏移量是图片宽一半。


19964945-03afaa49fa74d9a2.webp.jpg

里面的dx和dy是Matrix的方向,dy表示的是该点偏离圆心的方向,dx表示逆时针切线方向,以dx方向为x轴,dy方向为y轴绘制图片,这也就说明了为啥一开始图片就旋转了90度

 mMatrix.preTranslate(-mBitmap.getWidth() / 2, -mBitmap.getHeight() / 2);

再对dy进行偏移就把箭头移动到轨迹上面了。

path.addCircle(0, 0, 200, Path.Direction.CCW); 

其中如果将方向改为逆时针Path.Direction.CW,那么Matrix的dx和dy就是,在ccw的基础上改变方向,也就是dy是指向圆心的,dx是顺时针的切线方向,有兴趣的同学自己试一下。

        currentValue += 0.005;                                  // 计算当前的位置在总长度上的比例[0,1]
        if (currentValue >= 1) {
            currentValue = 0;
        }
        ...
        invalidate();//提示系统下一次刷新界面要重新调用一次onDrow

Android 每隔 16.6ms 会刷新一次屏幕,所以每隔16.6ms,currentValue就会增加一次,measure.getLength() * currentValue为一段圆弧的长度,箭头的位置为和起点的距离就是这段圆弧,圆弧不断变长,所以箭头位置就改变一次,
该部分代码就是不断的调整箭头的位置,也就是让箭头转动起来。

相关文章

网友评论

    本文标题:Android高级UI——PathMeasure和Matrix

    本文链接:https://www.haomeiwen.com/subject/wvbkbctx.html