Android 自定义齿轮View

直接上图

 

//自定义齿轮View
public class GearWheelView extends View {
    float Base_R = dp2px(20);//dp   绘制齿轮基准半径
    Paint insiderRingPaint;//内部环形绘制画笔
    Paint outsiderRingPaint;//外部环形绘制画笔
    Paint gearPaint;//齿轮绘制画笔
    int gearColor = 0xccFFD08C;//齿轮颜色
    int gearOutCount = 8;//齿轮外部的齿合个数
    float gearOutBottomRatio = 0.8f;//齿合的底部占已分大小的比例
    float gearOutTopRatio = 0.4f;//齿合的顶部占已分大小的比例
    float insideRingWidthRatio = 1F;//内环的宽度比例
    float outsideRingWidthRatio = 1F;//外环的宽度比例
    float gearWidthRatio = 0.8F;//外部齿合的高度比例
    Point gearCenter;//齿轮中心
    float startAngle = 0;//齿轮的开始角度
    int animCircleTime = 1000;//动画一周期时长
    boolean isClockWise = true;//是否为顺时针

    Context mContext;

    public GearWheelView(Context context) {
        super(context);
        initView(context);
    }

    public GearWheelView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        getAttr(attrs, context);
        initView(context);
    }

    public GearWheelView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        getAttr(attrs, context);
        initView(context);
    }


    private void getAttr(AttributeSet attrs, Context context) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.GearWheelView);
        Base_R = typedArray.getDimensionPixelOffset(R.styleable.GearWheelView_GearWheelViewBaseR, dp2px(20));
        animCircleTime = typedArray.getInt(R.styleable.GearWheelView_GearWheelViewCycleTime, animCircleTime);
        isClockWise = typedArray.getBoolean(R.styleable.GearWheelView_GearWheelViewClockWise, true);
        typedArray.recycle();
    }

    private void initView(Context context) {
        mContext = context;
        gearPaint = new Paint();
        gearPaint.setAntiAlias(true);
        gearPaint.setDither(true);
        gearPaint.setStyle(Paint.Style.FILL);
        gearPaint.setColor(gearColor);
        gearPaint.setStrokeJoin(Paint.Join.ROUND);

        insiderRingPaint = new Paint();
        insiderRingPaint.setAntiAlias(true);
        insiderRingPaint.setDither(true);
        insiderRingPaint.setStrokeWidth(insideRingWidthRatio*Base_R);
        insiderRingPaint.setStyle(Paint.Style.STROKE);
        insiderRingPaint.setColor(gearColor);

        outsiderRingPaint = new Paint();
        outsiderRingPaint.setAntiAlias(true);
        outsiderRingPaint.setDither(true);
        outsiderRingPaint.setStrokeWidth(outsideRingWidthRatio*Base_R);
        outsiderRingPaint.setStyle(Paint.Style.STROKE);
        outsiderRingPaint.setColor(gearColor);

        startAnim();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawInsideRing(canvas);
        drawOutsideRing(canvas);
        drawGear(canvas);
    }


    private void startAnim() {
        ValueAnimator animator = ValueAnimator.ofFloat(0, isClockWise?360:-360);
        animator.setDuration(animCircleTime);
        animator.setRepeatCount(Integer.MAX_VALUE);//表示无限
        animator.setInterpolator(new LinearInterpolator());
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                startAngle = (float) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        animator.start();
    }


    //画内环
    private void drawInsideRing(Canvas canvas) {
        canvas.drawCircle(gearCenter.x, gearCenter.y, 3 * Base_R / 2, insiderRingPaint);
    }

    //画外环
    private void drawOutsideRing(Canvas canvas) {
        canvas.drawCircle(gearCenter.x, gearCenter.y, 3 * Base_R, outsiderRingPaint);
    }

    //画外部齿合
    private void drawGear(Canvas canvas) {
        Path path = initGearPath();
        canvas.drawPath(path, gearPaint);
    }

    private Path initGearPath() {
        float insideR = (3 * Base_R + outsideRingWidthRatio * Base_R / 2);
        float outsideR = (insideR + Base_R * gearWidthRatio);

        Path path = new Path();
        Path insidePath = new Path();
        Path outPath = new Path();
        RectF insideRectF = new RectF(gearCenter.x - insideR, gearCenter.y - insideR, gearCenter.x + insideR, gearCenter.y + insideR);
        insidePath.addArc(insideRectF, startAngle, 359.9F);

        RectF outSideRectF = new RectF(gearCenter.x - outsideR, gearCenter.y - outsideR, gearCenter.x + outsideR, gearCenter.y + outsideR);
        outPath.addArc(outSideRectF, startAngle, 359.9F);

        PathMeasure insidePathMeasure = new PathMeasure(insidePath, true);
        PathMeasure outsidePathMeasure = new PathMeasure(outPath, true);
        float insideItemLength = insidePathMeasure.getLength() / gearOutCount;
        float outsideItemLength = outsidePathMeasure.getLength() / gearOutCount;
        float insideD = (1 - gearOutBottomRatio) / 2;//获取内部差值
        float outsideD = (1 - gearOutTopRatio) / 2;//获取外部差值

        for (int i = 0; i < gearOutCount; i++) {
            Path itemPath = new Path();
            float[] pos = new float[2];
            insidePathMeasure.getPosTan(i * insideItemLength + insideD * insideItemLength, pos, null);//获取点信息
            itemPath.moveTo(pos[0], pos[1]);
            outsidePathMeasure.getPosTan(i * outsideItemLength + outsideD * outsideItemLength, pos, null);//获取点信息
            itemPath.lineTo(pos[0], pos[1]);

            outsidePathMeasure.getPosTan((i + 1) * outsideItemLength - outsideD * outsideItemLength, pos, null);//获取点信息
            itemPath.lineTo(pos[0], pos[1]);

            insidePathMeasure.getPosTan((i + 1) * insideItemLength - insideD * insideItemLength, pos, null);//获取点信息
            itemPath.lineTo(pos[0], pos[1]);
            itemPath.close();
            path.addPath(itemPath);
        }
        return path;
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec),
                resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec));
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        gearCenter = new Point(w / 2, h / 2);
    }

    public static int dp2px(float dpValue) {
        return (int) (0.5f + dpValue * Resources.getSystem().getDisplayMetrics().density);
    }
}

 

仅供参考学习

项目地址:https://github.com/993739033/GearWheelView

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值