转载请标明出处:https://blog..net/m0_38074457/article/details/87890997,本文出自【陈少华的博客】
一、效果图
二、实现步骤
三、代码实现
1、attrs.xml中添加自定义控件的属性
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 mView;
MsgHandler(WindMillView view) {
mView = new WeakReference(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. 布局中引用控件(控件需要放在一个父布局中,父布局中放一个图片按钮)
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支持!