《Android自定义控件》WindMillView,仿华为天气风车效果

转载请标明出处:https://blog.csdn.net/m0_38074457/article/details/87890997

一、效果图

二、实现步骤

三、代码实现

1、attrs.xml中添加自定义控件的属性

    <declare-styleable name="WindMillView">
        <attr name="windColor" format="reference|color" />
    </declare-styleable>

2、控件的构造方法,initView方法中初始化控件的值

public WindMillView(Context context) {
        this(context, null);
    }

    public WindMillView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    private void initView(Context context, AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.WindMillView);
        if (array != null) {
            mColor = array.getColor(R.styleable.WindMillView_windColor, Color.WHITE);

            array.recycle();
        }
        //抗锯齿
        mPaint.setAntiAlias(true);
        mPaint.setColor(mColor);
    }

3、onMeasure来获取控件的宽高和旋转中心扇叶长度等的值

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int heiMeasure = MeasureSpec.getSize(heightMeasureSpec);
        int heiMode = MeasureSpec.getMode(heightMeasureSpec);
        int widMode = MeasureSpec.getMode(widthMeasureSpec);
        int widMeasure = MeasureSpec.getSize(widthMeasureSpec);

        mWid = widMeasure;
        mHei = heiMeasure;
        mCenterY = mWid / 2;
        mCenterX = mWid / 2;

        mPivotRadius = (float) mWid / (float) 40;
        mBladeRadius = mCenterY - 2 * mPivotRadius;

    }

4、onDraw来绘制转盘

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

        //画扇叶旋转的中心
        drawPivot(canvas);

        //画扇叶
        drawWindBlade(canvas);

        //画底部支柱
        drawPillar(canvas);
    }


    /**
     * 画风车支点
     *
     * @param canvas
     */
    private void drawPivot(Canvas canvas) {
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(mCenterX, mCenterY, mPivotRadius, mPaint);
    }

    /**
     * 画叶片
     *
     * @param canvas
     */
    private void drawWindBlade(Canvas canvas) {
        canvas.save();
        mPath.reset();
        //根据偏移量画初始时画布的位置
        canvas.rotate(mOffsetAngle, mCenterX, mCenterY);
        //画三角形扇叶
        mPath.moveTo(mCenterX, mCenterY - mPivotRadius);// 此点为多边形的起点
        mPath.lineTo(mCenterX, mCenterY - mPivotRadius - mBladeRadius);
        mPath.lineTo(mCenterX + mPivotRadius, mPivotRadius + mBladeRadius * (float) 2 / (float) 3);
        mPath.close(); // 使这些点构成封闭的多边形
        canvas.drawPath(mPath, mPaint);

        //旋转画布120度,画第二个扇叶
        canvas.rotate(120, mCenterX, mCenterY);
        canvas.drawPath(mPath, mPaint);

        //旋转画布120度,画第三个扇叶
        canvas.rotate(120, mCenterX, mCenterY);
        canvas.drawPath(mPath, mPaint);
        canvas.restore();
    }

    /**
     * 画支柱
     *
     * @param canvas
     */
    private void drawPillar(Canvas canvas) {
        mPath.reset();
        //画上下半圆之间的柱形
        mPath.moveTo(mCenterX - mPivotRadius / 2, mCenterY + mPivotRadius + mPivotRadius / 2);
        mPath.lineTo(mCenterX + mPivotRadius / 2, mCenterY + mPivotRadius + mPivotRadius / 2);
        mPath.lineTo(mCenterX + mPivotRadius, mHei - 2 * mPivotRadius);
        mPath.lineTo(mCenterX - mPivotRadius, mHei - 2 * mPivotRadius);
        mPath.close();

        //画顶部半圆
        mRect.set(mCenterX - mPivotRadius / 2, mCenterY + mPivotRadius, mCenterX + mPivotRadius / 2, mCenterY + 2 * mPivotRadius);
        mPath.addArc(mRect, 180, 180);
        //画底部半圆
        mRect.set(mCenterX - mPivotRadius, mHei - 3 * mPivotRadius, mCenterX + mPivotRadius, mHei - mPivotRadius);
        mPath.addArc(mRect, 0, 180);

        canvas.drawPath(mPath, mPaint);
    }

5、使用静态内部类MsgHandler来控制,startRotate来开启旋转,stop来关闭旋转

使用静态内部类MsgHandler继承Handler,弱引用控件,的作用是防止内存泄漏

 /**
     * 开始旋转
     */
    public void startRotate() {
        stop();
        mHandler.sendEmptyMessageDelayed(0, 10);
    }

    /**
     * 停止旋转
     */
    public void stop() {
        mHandler.removeMessages(0);
    }

    static class MsgHandler extends Handler {
        private WeakReference<WindMillView> mView;

        MsgHandler(WindMillView view) {
            mView = new WeakReference<WindMillView>(view);
        }

        @Override
        public void handleMessage(Message msg) {
            WindMillView view = mView.get();
            if (view != null) {
                view.handleMessage(msg);
            }
        }
    }

    private void handleMessage(Message msg) {
        if (mOffsetAngle >= 0 && mOffsetAngle < 360) {
            mOffsetAngle = mOffsetAngle + 1;
        } else {
            mOffsetAngle = 1;
        }
        invalidate();
        startRotate();
    }

三、项目中如何引用

步骤1.将JitPack存储库添加到构建文件中

项目的根build.gradle中添加以下代码:

allprojects {
	repositories {
		...
		maven { url 'https://jitpack.io' }
	}
}

步骤2.build.gradle添加依赖项

dependencies {
	        implementation 'com.github.hnsycsxhzcsh:WindMillView:v1.1'
	}

步骤3. 布局中引用控件(控件需要放在一个父布局中,父布局中放一个图片按钮)

<com.windmillview.WindMillView
            android:id="@+id/wm1"
            android:layout_width="100dp"
            android:layout_height="120dp"
            app:windColor="@color/white" />

步骤4. activity中调用控件的startRotate方法开启旋转

 

备注:

可以在github上下载我的项目:https://github.com/hnsycsxhzcsh/WindMillView,如果我的博客对你有帮助的话,欢迎博客点赞支持,并在github右上角star支持!

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值