Android应用开发Android 可滚动圆形进度条 滑块和进度在进度条上面跟着滚动
白羽 2019-03-15 来源 :网络 阅读 902 评论 0

摘要:本文将带你了解Android应用开发Android 可滚动圆形进度条 滑块和进度在进度条上面跟着滚动,希望本文对大家学Android有所帮助。

    本文将带你了解Android应用开发Android 可滚动圆形进度条 滑块和进度在进度条上面跟着滚动,希望本文对大家学Android有所帮助。



Android应用开发Android 可滚动圆形进度条 滑块和进度在进度条上面跟着滚动



   Android 可滚动圆形进度条 滑块和进度在进度条上面跟着滚动。package com.example.test;
   
   import android.content.Context;
   
   import android.content.res.TypedArray;
   
   import android.graphics.Canvas;
   
   import android.graphics.Color;
   
   import android.graphics.Matrix;
   
   import android.graphics.Paint;
   
   import android.graphics.PointF;
   
   import android.graphics.RectF;
   
   import android.graphics.drawable.Drawable;
   
   import android.util.AttributeSet;
   
   import android.view.MotionEvent;
   
   import android.view.View;
   
   public class MusicProgressBar extends View{
   
   /**
   
   * 画笔对象的引用
   
   */
   
   private Paint paint;
   
   /**
   
   * 圆环的颜色
   
   */
   
   private int roundColor;
   
   /**
   
   * 圆环进度的颜色
   
   */
   
   private int roundProgressColor;
   
   /**
   
   * 圆环的宽度
   
   */
   
   private float roundWidth;
   
   /**
   
   * 最大进度
   
   */
   
   private int max;
   
   /**
   
   * 当前进度
   
   */
   
   private int progress;
   
   /**
   
   * 中间进度百分比的字符串的颜色
   
   */
   
   private int textColor;
   
   /**
   
   * 中间进度百分比的字符串的字体
   
   */
   
   private float textSize;
   
   /**
   
   * 点的半径
   
   */
   
   private float pointRadius;
   
   /**
   
   * 空心点的宽度
   
   */
   
   private float pointWidth;
   
   private Drawable mThumb, mThumbPress;
   
   public MusicProgressBar(Context context) {
   
   this(context, null);
   
   }
   
   public MusicProgressBar(Context context, AttributeSet attrs) {
   
   this(context, attrs, 0);
   
   }
   
   public MusicProgressBar(Context context, AttributeSet attrs, int defStyle)  {
   
   super(context, attrs, defStyle);
   
   paint = new Paint();
   
   //TypedArray mTypedArray = context.obtainStyledAttributes(attrs,  R.styleable.RoundProgressBar);
   
   //获取自定义属性和默认值
   
   roundColor =Color.RED;//  mTypedArray.getColor(R.styleable.RoundProgressBar_roundColor,  Color.RED);
   
   roundProgressColor =Color.GREEN;// mTypedArray.getColor(R.styleable.RoundProgressBar_roundProgressColor,  Color.GREEN);
   
   roundWidth =3;//  mTypedArray.getDimension(R.styleable.RoundProgressBar_roundWidth, 3);
   
   textColor =Color.BLACK;//  mTypedArray.getColor(R.styleable.RoundProgressBar_textColor,  Color.GREEN);
   
   textSize =8;//  mTypedArray.getDimension(R.styleable.RoundProgressBar_textSize, 15);
   
   max =100;// mTypedArray.getInteger(R.styleable.RoundProgressBar_imageMax,  100);
   
   pointRadius =3;// mTypedArray.getDimension(R.styleable.RoundProgressBar_pointRadius,  3);
   
   pointWidth =2;//  mTypedArray.getDimension(R.styleable.RoundProgressBar_pointWidth, 2);
   
   // mTypedArray.recycle();
   
   // 加载拖动图标
   
   mThumb = getResources().getDrawable(R.drawable.ic_launcher);// 圆点图片
   
   int thumbHalfheight = mThumb.getIntrinsicHeight() / 2;
   
   int thumbHalfWidth = mThumb.getIntrinsicWidth() / 2;
   
   mThumb.setBounds(-thumbHalfWidth, -thumbHalfheight, thumbHalfWidth,  thumbHalfheight);
   
   mThumbPress = getResources().getDrawable(R.drawable.ic_launcher);//  圆点图片
   
   thumbHalfheight = mThumbPress.getIntrinsicHeight() / 2;
   
   thumbHalfWidth = mThumbPress.getIntrinsicWidth() / 2;
   
   mThumbPress.setBounds(-thumbHalfWidth, -thumbHalfheight, thumbHalfWidth,  thumbHalfheight);
   
   paddingOuterThumb = thumbHalfheight*2;
   
   }
   
   @Override
   
   public void onDraw(Canvas canvas) {
   
   /**
   
   * 画最外层的大圆环
   
   */
   
   paint.setColor(roundColor); //设置圆环的颜色
   
   paint.setStyle(Paint.Style.STROKE); //设置空心
   
   paint.setStrokeWidth(roundWidth); //设置圆环的宽度
   
   paint.setAntiAlias(true); //消除锯齿
   
   canvas.drawCircle(centerX, centerY, radius, paint); //画出圆环
   
   /**
   
   * 画文字
   
   */
   
   paint.setStrokeWidth(0);
   
   paint.setColor(textColor);
   
   paint.setTextSize(textSize);
   
   // paint.setTypeface(Typeface.DEFAULT); //设置字体
   
   String textTime = getTimeText(progress);
   
   float textWidth = paint.measureText(textTime); //测量字体宽度,我们需要根据字体的宽度设置在圆环中间
   
   // canvas.drawText(textTime, centerX - textWidth / 2, centerY + textSize/2,  paint);
   
   /**
   
   * 画圆弧 ,画圆环的进度
   
   */
   
   paint.setStrokeWidth(roundWidth); //设置圆环的宽度
   
   paint.setColor(roundProgressColor); //设置进度的颜色
   
   RectF oval = new RectF(centerX - radius, centerY - radius, centerX +  radius, centerY + radius); //用于定义的圆弧的形状和大小的界限
   
   paint.setStyle(Paint.Style.STROKE);
   
   canvas.drawArc(oval, 270, 360 * progress / max, false, paint);  //根据进度画圆弧
   
   // 画圆上的两个点
   
   paint.setStrokeWidth(pointWidth);
   
   PointF startPoint = ChartUtil.calcArcEndPointXY(centerX, centerY, radius,  0, 270);
   
   canvas.drawCircle(startPoint.x, startPoint.y, pointRadius, paint);
   
   //paint.setStyle(Paint.Style.FILL_AND_STROKE);
   
   PointF progressPoint = ChartUtil.calcArcEndPointXY(centerX, centerY,  radius, 360 * progress / max, 270);
   
   //canvas.drawCircle(progressPoint.x, progressPoint.y, pointRadius,  paint);
   
   // 画Thumb
   
   canvas.save();
   
   canvas.translate((float)(progressPoint.x+15*Math.sin(360 * progress /  max*0.0174533f)), (float)(progressPoint.y-15*Math.cos(360 * progress /  max*0.0174533f)));
   
   canvas.rotate(360 * progress / max);
   
   if (downOnArc) {
   
   mThumbPress.draw(canvas);
   
   } else {
   
   mThumb.draw(canvas);
   
   }
   
   canvas.restore();
   
   paint.setStrokeWidth(0);
   
   paint.setColor(textColor);
   
   paint.setTextSize(textSize);
   
   // paint.setTypeface(Typeface.DEFAULT); //设置字体
   
   // String textTime = getTimeText(progress);
   
   // float textWidth = paint.measureText(textTime);
   
   progress-=5;
   
   canvas.rotate(360*(progress+5) / max,  (float)(progressPoint.x+26f*Math.sin(360 * progress /  max*0.0174533f)),(float)(progressPoint.y-26f*Math.cos(360 * progress /  max*0.0174533f)));
   
   canvas.drawText(textTime,(float)(progressPoint.x+26f*Math.sin(360 *  progress / max*0.0174533f)),(float)(progressPoint.y-26f*Math.cos(360 *  progress / max*0.0174533f)), paint);
   
   canvas.rotate(-360*(progress+5) / max, progressPoint.x,  progressPoint.y);
   
   progress+=5;
   
   }
   
   private boolean downOnArc = false;
   
   @Override
   
   public boolean onTouchEvent(MotionEvent event) {
   
   int action = event.getAction();
   
   int x = (int) event.getX();
   
   int y = (int) event.getY();
   
   switch (action) {
   
   case MotionEvent.ACTION_DOWN:
   
   if (isTouchArc(x, y)) {
   
   downOnArc = true;
   
   updateArc(x, y);
   
   return true;
   
   }
   
   break;
   
   case MotionEvent.ACTION_MOVE:
   
   if (downOnArc) {
   
   updateArc(x, y);
   
   return true;
   
   }
   
   break;
   
   case MotionEvent.ACTION_UP:
   
   downOnArc = false;
   
   invalidate();
   
   if (changeListener != null) {
   
   changeListener.onProgressChangeEnd(max, progress);
   
   }
   
   break;
   
   }
   
   return super.onTouchEvent(event);
   
   }
   
   private int centerX, centerY;
   
   private int radius;
   
   private int paddingOuterThumb;
   
   @Override
   
   protected void onSizeChanged(int width, int height, int oldw, int oldh)  {
   
   centerX = width / 2;
   
   centerY = height / 2;
   
   int minCenter = Math.min(centerX, centerY);
   
   radius = (int) (minCenter - roundWidth/2 - paddingOuterThumb);  //圆环的半径
   
   minValidateTouchArcRadius = (int) (radius - paddingOuterThumb*1.5f);
   
   maxValidateTouchArcRadius = (int) (radius + paddingOuterThumb*1.5f);
   
   super.onSizeChanged(width, height, oldw, oldh);
   
   }
   
   // 根据点的位置,更新进度
   
   private void updateArc(int x, int y) {
   
   int cx = x - getWidth() / 2;
   
   int cy = y - getHeight() / 2;
   
   // 计算角度,得出(-1->1)之间的数据,等同于(-180°->180°)
   
   double angle = Math.atan2(cy, cx)/Math.PI;
   
   // 将角度转换成(0->2)之间的值,然后加上90°的偏移量
   
   angle = ((2 + angle)%2 + (90/180f))%2;
   
   // 用(0->2)之间的角度值乘以总进度,等于当前进度
   
   progress = (int) (angle * max/2);
   
   if (changeListener != null) {
   
   changeListener.onProgressChange(max, progress);
   
   }
   
   invalidate();
   
   }
   
   private int minValidateTouchArcRadius; // 最小有效点击半径
   
   private int maxValidateTouchArcRadius; // 最大有效点击半径
   
   // 判断是否按在圆边上
   
   private boolean isTouchArc(int x, int y) {
   
   double d = getTouchRadius(x, y);
   
   if (d >= minValidateTouchArcRadius && d <=  maxValidateTouchArcRadius) {
   
   return true;
   
   }
   
   return false;
   
   }
   
   // 计算某点到圆点的距离
   
   private double getTouchRadius(int x, int y) {
   
   int cx = x - getWidth() / 2;
   
   int cy = y - getHeight() / 2;
   
   return Math.hypot(cx, cy);
   
   }
   
   private String getTimeText(int progress) {
   
   int minute = progress / 60;
   
   int second = progress % 60;
   
   String result = (minute < 10 ? 0 : ) + minute + : + (second < 10 ? 0  : ) + second;
   
   return result;
   
   }
   
   public synchronized int getMax() {
   
   return max;
   
   }
   
   /**
   
   * 设置进度的最大值
   
   * @param max
   
   */
   
   public synchronized void setMax(int max) {
   
   if(max < 0){
   
   throw new IllegalArgumentException(max not less than 0);
   
   }
   
   this.max = max;
   
   }
   
   /**
   
   * 获取进度.需要同步
   
   * @return
   
   */
   
   public synchronized int getProgress() {
   
   return progress;
   
   }
   
   /**
   
   * 设置进度,此为线程安全控件,由于考虑多线的问题,需要同步
   
   * 刷新界面调用postInvalidate()能在非UI线程刷新
   
   * @param progress
   
   */
   
   public synchronized void setProgress(int progress) {
   
   if(progress < 0){
   
   throw new IllegalArgumentException(progress not less than 0);
   
   }
   
   if(progress > max){
   
   progress = max;
   
   }
   
   if(progress <= max){
   
   this.progress = progress;
   
   postInvalidate();
   
   }
   
   }
   
   public int getCricleColor() {
   
   return roundColor;
   
   }
   
   public void setCricleColor(int cricleColor) {
   
   this.roundColor = cricleColor;
   
   }
   
   public int getCricleProgressColor() {
   
   return roundProgressColor;
   
   }
   
   public void setCricleProgressColor(int cricleProgressColor) {
   
   this.roundProgressColor = cricleProgressColor;
   
   }
   
   public float getRoundWidth() {
   
   return roundWidth;
   
   }
   
   public void setRoundWidth(float roundWidth) {
   
   this.roundWidth = roundWidth;
   
   }
   
   public static class ChartUtil {
   
   /**
   
   * 依圆心坐标,半径,扇形角度,计算出扇形终射线与圆弧交叉点的xy坐标
   
   * @param cirX
   
   * @param cirY
   
   * @param radius
   
   * @param cirAngle
   
   * @return
   
   */
   
   public static PointF calcArcEndPointXY(float cirX, float cirY, float  radius, float cirAngle){
   
   float posX = 0.0f;
   
   float posY = 0.0f;
   
   //将角度转换为弧度
   
   float arcAngle = (float) (Math.PI * cirAngle / 180.0);
   
   if (cirAngle < 90)
   
   {
   
   posX = cirX + (float)(Math.cos(arcAngle)) * radius;
   
   posY = cirY + (float)(Math.sin(arcAngle)) * radius;
   
   }
   
   else if (cirAngle == 90)
   
   {
   
   posX = cirX;
   
   posY = cirY + radius;
   
   }
   
   else if (cirAngle > 90 && cirAngle < 180)
   
   {
   
   arcAngle = (float) (Math.PI * (180 - cirAngle) / 180.0);
   
   posX = cirX - (float)(Math.cos(arcAngle)) * radius;
   
   posY = cirY + (float)(Math.sin(arcAngle)) * radius;
   
   }
   
   else if (cirAngle == 180)
   
   {
   
   posX = cirX - radius;
   
   posY = cirY;
   
   }
   
   else if (cirAngle > 180 && cirAngle < 270)
   
   {
   
   arcAngle = (float) (Math.PI * (cirAngle - 180) / 180.0);
   
   posX = cirX - (float)(Math.cos(arcAngle)) * radius;
   
   posY = cirY - (float)(Math.sin(arcAngle)) * radius;
   
   }
   
   else if (cirAngle == 270)
   
   {
   
   posX = cirX;
   
   posY = cirY - radius;
   
   }
   
   else
   
   {
   
   arcAngle = (float) (Math.PI * (360 - cirAngle) / 180.0);
   
   posX = cirX + (float)(Math.cos(arcAngle)) * radius;
   
   posY = cirY - (float)(Math.sin(arcAngle)) * radius;
   
   }
   
   return new PointF(posX, posY);
   
   }
   
   public static PointF calcArcEndPointXY(float cirX, float cirY, float  radius, float cirAngle, float orginAngle){
   
   cirAngle = (orginAngle + cirAngle) % 360;
   
   return calcArcEndPointXY(cirX, cirY, radius, cirAngle);
   
   }
   
   }
   
   private OnProgressChangeListener changeListener;
   
   public void setChangeListener(OnProgressChangeListener changeListener)  {
   
   this.changeListener = changeListener;
   
   }
   
   public interface OnProgressChangeListener {
   
   void onProgressChange(int duration, int progress);
   
   void onProgressChangeEnd(int duration, int progress);
   
   }
   
   }
   
       

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道!

本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程