风车控件, 光圈控件

https://www.cnblogs.com/willhua/p/5763189.html

参考大神的思路, 动手改造加深理解

要点

  • 定义扇叶 (30, 60, 90 的直角三角形)
  • 找到内六边形顶点
  • 依次移动到顶点,进行旋转(参考第4幅图, 半透明是移动前的图形, 理解下面的计算)
    mPoints[0].x = curRadius / 2;
    mPoints[0].y = -curRadius * COS_30;

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <com.huawei.camera.canvas.MyTextView
        android:layout_width="100dp"
        android:layout_height="400dp" />

</LinearLayout>

 

代码参考:

package com.huawei.camera.canvas;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

public class MyTextView extends View {
    private static final String TAG = "MyTextView";
    private static final float ROTATE_ANGLE = 30;
    private static final int BACKGROUND_COLOR_ACTIVE = Color.parseColor("#FFFFFFFF");
    private static final float COS_30 = 0.866025f;
    private static final float MIN_RADIUS = 17.5f/COS_30;
    private static final float MAX_RADIUS = 67f/COS_30;
    private static final int SPACE = 3;
    private static final int BLADE_COLOR = Color.parseColor("#FF00FF00");
    private static final int VIRTUAL_BLADE_COLOR = Color.parseColor("#3300FF00");

    private int mCircleRadius;
    private int mWidth;
    private PointF[] mPoints = new PointF[6];
    private Bitmap mBlade;
    private Bitmap mVirtualBlade;
    private Bitmap mBmp;
    private Canvas mBmpCanvas;
    private Path mPath;
    private Paint mPaint;
    private int k = 0;
    public MyTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    class AnimationRotateRunnable implements Runnable {
        @Override
        public void run() {
            invalidate();
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Log.i(TAG, "onDraw: " + getHeight());
        mBmpCanvas = canvas;
        mBmpCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);//清理画布, 防止透明背景出现叠加
        mBmpCanvas.drawColor(BACKGROUND_COLOR_ACTIVE);
        mBmpCanvas.save();
        calculatePoints(0);
        mBmpCanvas.translate(mWidth / 2, mWidth / 2);
        mBmpCanvas.rotate(k % 360);
        //mBmpCanvas.clipPath(mPath);
        for (int i = 0; i < 6; i++) {
            mBmpCanvas.save();
            mBmpCanvas.translate(mPoints[i].x, mPoints[i].y);
            mBmpCanvas.rotate(-i * 60);
            mBmpCanvas.drawBitmap(mBlade, 0, 0, mPaint);
            mBmpCanvas.restore();
        }
        //postInvalidateDelayed(20);
        mBmpCanvas.restore();
        mBmpCanvas.drawLine(0f, mWidth, mWidth, mWidth, mPaint);

        //2nd
        mBmpCanvas.save();
        calculatePoints(0.3f);
        mBmpCanvas.translate(mWidth / 2, 3 * mWidth / 2);
        //mBmpCanvas.clipPath(mPath);
        for (int i = 0; i < 6; i++) {
            mBmpCanvas.save();
            mBmpCanvas.translate(mPoints[i].x, mPoints[i].y);
            mBmpCanvas.rotate(-i * 60);
            mBmpCanvas.drawBitmap(mBlade, 0, 0, mPaint);
            mBmpCanvas.restore();
        }
        mBmpCanvas.restore();
        mBmpCanvas.drawLine(0f, 2*mWidth, mWidth, 2*mWidth, mPaint);

        //3rd
        mBmpCanvas.save();
        calculatePoints(0.6f);
        mBmpCanvas.translate(mWidth / 2, 5 * mWidth / 2);
        //mBmpCanvas.clipPath(mPath);
        for (int i = 0; i < 6; i++) {
            mBmpCanvas.save();
            mBmpCanvas.translate(mPoints[i].x, mPoints[i].y);
            mBmpCanvas.rotate(-i * 60);
            mBmpCanvas.drawBitmap(mBlade, 0, 0, mPaint);
            mBmpCanvas.restore();
        }
        mBmpCanvas.restore();
        mBmpCanvas.drawLine(0f, 3*mWidth, mWidth, 3*mWidth, mPaint);

        //4th
        mBmpCanvas.save();
        calculatePoints(0.9f);
        mBmpCanvas.translate(mWidth / 2, 7 * mWidth / 2);
        //mBmpCanvas.clipPath(mPath);
        mBmpCanvas.drawBitmap(mVirtualBlade, 0, 0, mPaint);
        for (int i = 0; i < 6; i++) {
            mBmpCanvas.save();
            mBmpCanvas.translate(mPoints[i].x, mPoints[i].y);
            mBmpCanvas.rotate(-i * 60);
            mBmpCanvas.drawBitmap(mBlade, 0, 0, mPaint);
            mBmpCanvas.restore();
        }
        mBmpCanvas.restore();
        k += 1;
    }

    private void calculatePoints(float progress) {
        if (mCircleRadius - SPACE <= 0) {
            Log.e(TAG, "the size of view is too small and Space is too large");
            return;
        }
        float curRadius = MIN_RADIUS + progress * (MAX_RADIUS - MIN_RADIUS);
        mPoints[0].x = curRadius / 2;
        mPoints[0].y = -curRadius * COS_30;
        mPoints[1].x = -mPoints[0].x;
        mPoints[1].y = mPoints[0].y;
        mPoints[2].x = -curRadius;
        mPoints[2].y = 0;
        mPoints[3].x = mPoints[1].x;
        mPoints[3].y = -mPoints[1].y;
        mPoints[4].x = -mPoints[3].x;
        mPoints[4].y = mPoints[3].y;
        mPoints[5].x = curRadius;
        mPoints[5].y = 0;
    }

    private void init() {
        mWidth = 350;
        mCircleRadius = 80;
        mBmp = Bitmap.createBitmap(mWidth, mWidth, Bitmap.Config.ARGB_8888);
        mBmpCanvas = new Canvas(mBmp);
        mPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
        mPaint.setAntiAlias(true);
        for (int i = 0; i < 6; i++) {
            mPoints[i] = new PointF();
        }
        mPath = new Path();
        mPath.addCircle(0, 0, mCircleRadius, Path.Direction.CW);
        createBlade();
        createVirtualBlade();
    }

    private void createBlade() {
        mBlade = Bitmap.createBitmap(mCircleRadius,
                (int) (mCircleRadius * 2 * COS_30), Bitmap.Config.ARGB_8888);
        Path path = new Path();
        Canvas canvas = new Canvas(mBlade);
        path.moveTo(SPACE / 2 / COS_30, SPACE);
        path.lineTo(mBlade.getWidth(), mBlade.getHeight());
        path.lineTo(mBlade.getWidth(), SPACE);
        path.close();
        canvas.clipPath(path);
        canvas.drawColor(BLADE_COLOR);
    }

    private void createVirtualBlade() {
        mVirtualBlade = Bitmap.createBitmap(mCircleRadius,
                (int) (mCircleRadius * 2 * COS_30), Bitmap.Config.ARGB_8888);
        Path path = new Path();
        Canvas canvas = new Canvas(mVirtualBlade);
        path.moveTo(SPACE / 2 / COS_30, SPACE);
        path.lineTo(mVirtualBlade.getWidth(), mVirtualBlade.getHeight());
        path.lineTo(mVirtualBlade.getWidth(), SPACE);
        path.close();
        canvas.clipPath(path);
        canvas.drawColor(VIRTUAL_BLADE_COLOR);
    }
}
View Code

变成光圈控件:

只需要对canvas执行clipPath

posted @ 2018-08-13 16:50  疾风剑  阅读(209)  评论(0编辑  收藏  举报