8. 旋转风车
这个时候就要用到自定义View了,这个工具类的代码也并不是我自己写的,而是网络上找的,
① 样式
在模块的res文件夹下的values文件下新建一个styles.xml
里面的代码如下:
<?xml version="1.0" encoding="utf-8"?> <resources> <!--白色风车--> <declare-styleable name="WhiteWindmills"> <attr name="windColor" format="reference|color" /> </declare-styleable> </resources>
② 自定义View
然后就是自定义VIew了,
在模块的com.llw.mvplibrary下面创建一个view的包,包下创建一个名为WhiteWindmills的类。
代码如下:
package com.llw.mvplibrary.view; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.view.View; import androidx.annotation.Nullable; import com.llw.mvplibrary.R; import java.lang.ref.WeakReference; /** * 白色风车 */ public class WhiteWindmills extends View { /** * 叶片的长度 */ private float mBladeRadius; /** * 风车叶片旋转中心x */ private int mCenterY; /** * 风车叶片旋转中心y */ private int mCenterX; /** * 风车旋转中心点圆的半径 */ private float mPivotRadius; private Paint mPaint = new Paint(); /** * 风车旋转时叶片偏移的角度 */ private int mOffsetAngle; private Path mPath = new Path(); /** * 风车支柱顶部和底部为了画椭圆的矩形 */ private RectF mRect = new RectF(); /** * 控件的宽 */ private int mWid; /** * 控件高 */ private int mHei; /** * 控件颜色 */ private int mColor; private MsgHandler mHandler = new MsgHandler(this); public WhiteWindmills(Context context) { this(context, null); } public WhiteWindmills(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public WhiteWindmills(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.WhiteWindmills); if (array != null) { mColor = array.getColor(R.styleable.WhiteWindmills_windColor, Color.WHITE); array.recycle(); } //抗锯齿 mPaint.setAntiAlias(true); mPaint.setColor(mColor); } @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; } @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); } /** * 开始旋转 */ public void startRotate() { stop(); mHandler.sendEmptyMessageDelayed(0, 10); } /** * 停止旋转 */ public void stop() { mHandler.removeMessages(0); } static class MsgHandler extends Handler { private WeakReference<WhiteWindmills> mView; MsgHandler(WhiteWindmills view) { mView = new WeakReference<WhiteWindmills>(view); } @Override public void handleMessage(Message msg) { WhiteWindmills 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(); } }
这个部分完成之后,修改布局,将这一块加进去。
③ 使用与运行显示
这部分代码如下:
<!--风力展示--> <LinearLayout android:orientation="horizontal" android:padding="20dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <RelativeLayout android:id="@+id/rl_wind" android:layout_width="130dp" android:layout_height="120dp"> <!--大风车--> <com.llw.mvplibrary.view.WhiteWindmills android:id="@+id/ww_big" android:layout_width="100dp" android:layout_height="120dp" /> <!--小风车--> <com.llw.mvplibrary.view.WhiteWindmills android:id="@+id/ww_small" android:layout_width="50dp" android:layout_height="60dp" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" /> </RelativeLayout> <LinearLayout android:gravity="center" android:orientation="vertical" android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent"> <!--风向--> <TextView android:id="@+id/tv_wind_direction" android:textColor="#FFF" android:textSize="@dimen/sp_14" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <!--风力--> <TextView android:layout_marginTop="20dp" android:id="@+id/tv_wind_power" android:textColor="#FFF" android:textSize="@dimen/sp_14" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> </LinearLayout>
代码中:
风力的数据其实在天气数据的返回值就有了,就是第一个接口,接下来修改代码
代码如下:
tvWindDirection.setText("风向 " + response.body().getHeWeather6().get(0).getNow().getWind_dir());//风向 tvWindPower.setText("风力 " + response.body().getHeWeather6().get(0).getNow().getWind_sc() + "级");//风力 wwBig.startRotate();//大风车开始转动 wwSmall.startRotate();//小风车开始转动
记得在页面销毁的时候停止这个风车:
/** * 页面销毁时 */ @Override public void onDestroy() { wwBig.stop();//停止大风车 wwSmall.stop();//停止小风车 super.onDestroy(); }
运行一下:
下一篇将会讲述切换城市