Android自定义View叶子旋转完整版(六)

Android自定义View叶子旋转完整版(六),第1张

概述上一篇实现多叶子飘动旋转,今天完成最后的功能。1、添加右侧旋转枫叶2、添加滑动条效果,显示百分比

上一篇实现多叶子飘动旋转,今天完成最后的功能。

1、添加右侧旋转枫叶

2、添加滑动条效果,显示百分比

3、修复叶子飘出边框问题

1、添加右侧旋转叶子

Bitmap turnBitmap = ((BitmapDrawable) mResources.getDrawable(R.drawable.fengshan,null)).getBitmap(); int turnLeafAngle = 0; private voID setTurnLeaf(Canvas canvas) {  Matrix matrix = new Matrix();  turnLeafAngle = turnLeafAngle + 3;  matrix.postTranslate((wIDth - rightCircleWIDth/2 - turnBitmap.getWIDth()/2),(height - rightCircleWIDth/2 - turnBitmap.getHeight()/2));  matrix.postRotate(turnLeafAngle,wIDth - rightCircleWIDth/2 - turnBitmap.getWIDth()/2 + turnBitmap.getWIDth()/2,height - rightCircleWIDth/2 - turnBitmap.getHeight()/2 + turnBitmap.getHeight()/2);  canvas.drawBitmap(turnBitmap,matrix,new Paint()); }

代码很明确,首先通过Matrix.postTranslate(float dx,float dy)把turnBitMap定位到最右侧圆圈

再通过Matrix.postRotate(float degress,float dx,float dy);设置旋转角度,每次角度+3°

其中degress为旋转角度,(dx,dy)为旋转中心点坐标

2、添加滑动效果

原理就是覆盖一层不同颜色的图层。根据当前百分比,分别画一个半圆,画一个正方形

a、定义一个圆形Rectf(为什么不是半圆?因为画圆弧的其实角度从水平线右侧开始)

progressArcRectf = new RectF(0,height,height);

b、定义一个长方形Rectf,长方形x坐标起点即时圆形半径

progressRectf = new RectF(height/2,  0,wIDth,height);

c、画出圆弧Canvas.drawArc(Rectf rectf,float startAngle,float sweepAngle,boolean useCenter,Paint paint)

startAngle:起始角度,默认从右侧水平线开始

sweepAngle:为旋转的角度,顺时针旋转

useCenter:true只画出弧线,false则画出圆心到弧线的区域

//画滑动后的背景条int currentProgressWIDht = currentProgress * (wIDth - borderWIDth)/100;if(currentProgressWIDht < leftCircleWIDth/2) {  //angle取值范围0~90  int angle = 90 * currentProgressWIDht / (leftCircleWIDth/2);  // 起始的位置  int startAngle = 180 - angle;  // 扫过的角度  int sweepAngle = 2 * angle;  canvas.drawArc(progressArcRectf,startAngle,sweepAngle,false,progressBgPaint);}else {  //画左边半圆形滑过部分  canvas.drawArc(progressArcRectf,90,180,progressBgPaint);  progressRectf.left = borderWIDth + leftCircleWIDth/2;  progressRectf.right = borderWIDth + currentProgressWIDht;  //画中间滑过部分  canvas.drawRect(progressRectf,progressBgPaint); }

给LeafVIEw.java添加一个

 public voID setCurrentProgress(int currentProgress) {  this.currentProgress = currentProgress; }

3、修复叶子飘动范围

这个简单,就是设置叶子的rect坐标起点+边框距离

赋上所有代码

1、activity_leaf.xml

<?xml version="1.0" enCoding="utf-8"?><relativeLayout xmlns:androID="http://schemas.androID.com/apk/res/androID" androID:ID="@+ID/content_leaf" androID:layout_wIDth="match_parent" androID:layout_height="match_parent">  <relativeLayout   androID:layout_wIDth="226dp"   androID:layout_height="45dp">    <com.zjcpo.t170313_countdowntimer.LeafVIEw     androID:ID="@+ID/leafVIEw"     androID:layout_wIDth="226dp"     androID:layout_height="45dp"     androID:layout_centerHorizontal="true"     />  </relativeLayout></relativeLayout>

2、LeafVIEw.java

import androID.content.Context;import androID.content.res.Resources;import androID.graphics.Bitmap;import androID.graphics.Canvas;import androID.graphics.color;import androID.graphics.Matrix;import androID.graphics.Paint;import androID.graphics.Rect;import androID.graphics.RectF;import androID.graphics.drawable.BitmapDrawable;import androID.util.AttributeSet;import androID.util.Log;import androID.vIEw.VIEw;import java.util.linkedList;import java.util.List;import java.util.Random;import java.util.jar.Attributes;/** * Created by jIEmiao.zhang on 2017-3-15. */public class LeafVIEw extends VIEw { private String TAG = "--------LeafVIEw"; private Resources mResources; //背景图、叶子 private Bitmap mLeafBitmap,bgBitmap,turnBitmap; //整个控件的宽度和高度 private int wIDth,height; //最外层边框宽度 private int borderWIDth; //右侧圆形直径 private int rightCircleWIDth; //左侧圆形直径 private int leftCircleWIDth; private Paint bgPaint; private RectF bgRect; private Rect bgDestRect; //进度条实时背景 private Paint progressBgPaint; //进度条左侧半圆,进度条中间长方形部分Rect private RectF progressArcRectf,progressRectf; //当前百分比0~100 private int currentProgress = 0; //存放叶子lsit private List<Leaf> leafList; //叶子的宽和高 private int mLeafWIDth,mLeafheight; //叶子滑动一周的时间5秒 private final static long cycleTime = 5000; //叶子数量 private final static int leafNumber = 6; public LeafVIEw(Context context,AttributeSet attrs) {  super(context,attrs);  mResources = getResources();  mLeafBitmap = ((BitmapDrawable) mResources.getDrawable(R.drawable.leaf,null)).getBitmap();  mLeafWIDth = mLeafBitmap.getWIDth();  mLeafheight = mLeafBitmap.getHeight();  turnBitmap = ((BitmapDrawable) mResources.getDrawable(R.drawable.fengshan,null)).getBitmap();  bgBitmap = ((BitmapDrawable) mResources.getDrawable(R.drawable.leaf_kuang,null)).getBitmap();  bgPaint = new Paint();  bgPaint.setcolor(mResources.getcolor(R.color.bg_color));  //进度条实时背景  progressBgPaint = new Paint();  progressBgPaint.setcolor(mResources.getcolor(R.color.progress_bg_color));  //获取所有叶子的信息,放入List  leafList = getLeafs(leafNumber); } @OverrIDe protected voID onSizeChanged(int w,int h,int olDW,int oldh) {  super.onSizeChanged(w,h,olDW,oldh);  wIDth = w;  height = h;  borderWIDth = height * 10/64;  rightCircleWIDth = wIDth * 62/303;  leftCircleWIDth = height - 2 * borderWIDth;  bgDestRect = new Rect(0,height);  bgRect = new RectF(0,height);  progressArcRectf = new RectF(borderWIDth,borderWIDth,height - borderWIDth,height - borderWIDth);  progressRectf = new RectF(borderWIDth+(height-2*borderWIDth)/2,wIDth-rightCircleWIDth/2,height-borderWIDth);  Log.i("leftmarginWIDth",(borderWIDth + leftCircleWIDth/2) + ""); } @OverrIDe protected voID onDraw(Canvas canvas) {  super.onDraw(canvas);  //画背景颜色到画布  canvas.drawRect(bgRect,bgPaint);  if(currentProgress <= 100) {   //画叶子   int size = leafList.size();   for (int i=0; i<size; i++) {    Leaf leaf = leafList.get(i);    //获取叶子坐标    getLocation(leaf);    //获取叶子旋转角度    getRotate(leaf);    canvas.save();    Matrix matrix = new Matrix();    //设置滑动    matrix.postTranslate(leaf.x,leaf.y);    //设置旋转    matrix.postRotate(leaf.rotateAngle,leaf.x + mLeafWIDth / 2,leaf.y + mLeafheight / 2);    //添加叶子到画布    canvas.drawBitmap(mLeafBitmap,new Paint());    canvas.restore();    //画滑动后的背景条    int currentProgressWIDht = currentProgress * (wIDth - borderWIDth - rightCircleWIDth/2)/100;    if(currentProgressWIDht < leftCircleWIDth/2) {     //angle取值范围0~90     int angle = 90 * currentProgressWIDht / (leftCircleWIDth/2);     Log.i(TAG,"angle :" + angle);     // 起始的位置     int startAngle = 180 - angle;     // 扫过的角度     int sweepAngle = 2 * angle;     canvas.drawArc(progressArcRectf,progressBgPaint);    }else {     //画左边半圆形滑过部分     canvas.drawArc(progressArcRectf,progressBgPaint);     progressRectf.left = borderWIDth + leftCircleWIDth/2;     progressRectf.right = borderWIDth + currentProgressWIDht;     //画中间滑过部分     canvas.drawRect(progressRectf,progressBgPaint);    }   }   //调用onDraw()重复滑动   if(currentProgress < 100) {    postInvalIDate();   }  }  //画背景图片到画布  canvas.drawBitmap(bgBitmap,null,bgDestRect,null);  //画右边选择风叶  setTurnLeaf(canvas);  //画百分比  setText(canvas); } int turnLeafAngle = 0; private voID setTurnLeaf(Canvas canvas) {  Matrix matrix = new Matrix();  turnLeafAngle = turnLeafAngle + 3;  matrix.postTranslate((wIDth - rightCircleWIDth/2 - turnBitmap.getWIDth()/2),new Paint()); } //显示百分比数字,大于3%开始显示,到50%停止滑动 private voID setText(Canvas canvas) {  Paint paintText = new Paint();  paintText.setcolor(color.WHITE);  paintText.setTextSize(30);  int textx = currentProgress * wIDth / 100;  textx = currentProgress < 50 ? (currentProgress * wIDth / 100) : (wIDth/2);  if(currentProgress > 3) {   canvas.drawText(currentProgress + "%",textx,height/2 + 10,paintText);  } } //获取每片叶子在XY轴上的滑动值 private voID getLocation(Leaf leaf) {  float betweenTime = leaf.startTime - System.currentTimeMillis();  //周期结束再加一个cycleTime  if(betweenTime < 0) {   leaf.startTime = System.currentTimeMillis() + cycleTime + new Random().nextInt((int) (cycleTime));   betweenTime = cycleTime;  }  //通过时间差计算出叶子的坐标  float fraction = (float) betweenTime / cycleTime;  float x = (int)(wIDth * fraction);  //防止叶子飘出边框  leaf.x = x < borderWIDth ? borderWIDth : x;  float w = (float) ((float) 2 * Math.PI / wIDth);  int y = (int) (18 * Math.sin(w * x)) + (height-mLeafheight)/2;  //防止叶子飘出边框  y = y > (height - borderWIDth) ? (height - borderWIDth) : y;  y = y < borderWIDth ? borderWIDth : y;  leaf.y = y; } //获取每片叶子的旋转角度 private voID getRotate(Leaf leaf) {  float scale = ((leaf.startTime - System.currentTimeMillis())%cycleTime)/ (float)cycleTime;  int rotate = (int)(scale * 360);  leaf.rotateAngle = rotate; } private class Leaf {  // 叶子的坐标  float x,y;  // 旋转角度  int rotateAngle;  // 起始时间(ms)  long startTime; } private List<Leaf> getLeafs(int leafSize) {  List<Leaf> List = new linkedList<Leaf>();  for (int i=0; i<leafSize; i++) {   List.add(getLeaf());  }  return List; } //使叶子初始时间有间隔 int addTime; private Leaf getLeaf() {  Random random = new Random();  Leaf leaf = new Leaf();  leaf.rotateAngle = random.nextInt(360);  addTime += random.nextInt((int) (cycleTime));  leaf.startTime = System.currentTimeMillis() + cycleTime + addTime;  return leaf; } public voID setCurrentProgress(int currentProgress) {  this.currentProgress = currentProgress; }}3、LeafActivity.javapublic class LeafActivity extends Activity { private LeafVIEw leafVIEw; private int mProgress = 0; Handler mHandler = new Handler() {  public voID handleMessage(Message msg) {   if (mProgress < 40) {    mProgress += 1;    // 随机800ms以内刷新一次    mHandler.sendEmptyMessageDelayed(1,new Random().nextInt(800));    leafVIEw.setCurrentProgress(mProgress);   } else {    mProgress += 1;    // 随机1200ms以内刷新一次    mHandler.sendEmptyMessageDelayed(1,new Random().nextInt(100));    leafVIEw.setCurrentProgress(mProgress);   }  }; }; @OverrIDe protected voID onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentVIEw(R.layout.activity_leaf);  leafVIEw = (LeafVIEw) findVIEwByID(R.ID.leafVIEw);  mHandler.sendEmptyMessageDelayed(1,3000); }}

最后再看下效果

总结

看过前5篇的很好理解,用到的技术点之前都讲到了。这篇主要就是几个百分比函数的计算。

比如设置半圆时弧度如何计算,圆弧对应的百分比,滑动区域长方形的起点坐标计算,去掉边框后的坐标计算

画半圆必须要有一个完整圆形Rect,因为drawArc()从右侧半径水平起始角度,顺时针。然功能要求我们从左侧圆形开始画,所以要通过一个算法,假如当前百分比为4%,需要画30°的圆弧,那么起始角度为165°=180°-15°,画出角度30%

通过matrix.postRotate()实现旋转功能时,必须加上当前vIEw的坐标及二分之一长宽

需要图片等信息的可以从下面的Github地址下载,不过原文比较复杂

参考 https://github.com/Ajian-studio/GALeafLoading

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的Android自定义View叶子旋转完整版(六)全部内容,希望文章能够帮你解决Android自定义View叶子旋转完整版(六)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1146549.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存