自定义计步--圆弧

/**
 * Created by DylanAndroid on 2016/5/26.
 * 显示步数的圆弧
 */
public class StepArcView extends View {
    /**
     * 圆弧的宽度
     */
    private float borderWidth = 36f;
    /**
     * 画步数的数值的字体大小
     */
    private float numberTextSize = 0;
    /**
     * 步数
     */
    private String stepNumber = "0";
    /**
     * 开始绘制圆弧的角度
     */
    private float startAngle = 90;
    /**
     * 终点对应的角度和起始点对应的角度的夹角
     */
    private float angleLength = 360;
    /**
     * 所要绘制的当前步数的红色圆弧终点到起点的夹角
     */
    private float currentAngleLength = 0;
    /**
     * 动画时长
     */
    private int animationLength = 3000;

    public StepArcView(Context context) {
        super(context);


    }

    public StepArcView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public StepArcView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /**中心点的x坐标*/
        float centerX = (getWidth()) / 2;
        /**指定圆弧的外轮廓矩形区域*/
        RectF rectF = new RectF(0 + borderWidth, borderWidth, 2 * centerX - borderWidth, 2 * centerX - borderWidth);

        /**【第一步】绘制整体的黄色圆弧*/
        drawArcYellow(canvas, rectF);
        /**【第二步】绘制当前进度的红色圆弧*/
        drawArcRed(canvas, rectF);
        /**【第三步】绘制当前进度的红色数字*/
        drawTextNumber(canvas, centerX);
        /**【第四步】绘制"步数"的红色数字*/
        drawTextStepString(canvas, centerX);
    }

    /**
     * 1.绘制总步数的黄色圆弧
     *
     * @param canvas 画笔
     * @param rectF  参考的矩形
     */
    private void drawArcYellow(Canvas canvas, RectF rectF) {
        Paint paint = new Paint();
        /** 默认画笔颜色,黄色 */
        paint.setColor(Color.parseColor("#868686"));
        /** 结合处为圆弧*/
        paint.setStrokeJoin(Paint.Join.ROUND);
        /** 设置画笔的样式 Paint.Cap.Round ,Cap.SQUARE等分别为圆形、方形*/
        paint.setStrokeCap(Paint.Cap.ROUND);
        /** 设置画笔的填充样式 Paint.Style.FILL  :填充内部;Paint.Style.FILL_AND_STROKE  :填充内部和描边;  Paint.Style.STROKE  :仅描边*/
        paint.setStyle(Paint.Style.STROKE);
        /**抗锯齿功能*/
        paint.setAntiAlias(true);
        /**设置画笔宽度*/
        paint.setStrokeWidth(borderWidth);

        /**绘制圆弧的方法
         * drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//画弧,
         参数一是RectF对象,一个矩形区域椭圆形的界限用于定义在形状、大小、电弧,
         参数二是起始角(度)在电弧的开始,圆弧起始角度,单位为度。
         参数三圆弧扫过的角度,顺时针方向,单位为度,从右中间开始为零度。
         参数四是如果这是true(真)的话,在绘制圆弧时将圆心包括在内,通常用来绘制扇形;如果它是false(假)这将是一个弧线,
         参数五是Paint对象;
         */
        canvas.drawArc(rectF, startAngle, angleLength, false, paint);

    }

    /**
     * 2.绘制当前步数的红色圆弧
     */
    private void drawArcRed(Canvas canvas, RectF rectF) {
        Paint paintCurrent = new Paint();
        paintCurrent.setStrokeJoin(Paint.Join.ROUND);
        paintCurrent.setStrokeCap(Paint.Cap.ROUND);//圆角弧度
        paintCurrent.setStyle(Paint.Style.STROKE);//设置填充样式
        paintCurrent.setAntiAlias(true);//抗锯齿功能
        paintCurrent.setStrokeWidth(borderWidth);//设置画笔宽度
        paintCurrent.setColor(Color.parseColor("#119c29"));//设置画笔颜色
        canvas.drawArc(rectF, startAngle, currentAngleLength, false, paintCurrent);
    }

    /**
     * 3.圆环中心的步数
     */
    private void drawTextNumber(Canvas canvas, float centerX) {
        Paint vTextPaint = new Paint();
        vTextPaint.setTextAlign(Paint.Align.CENTER);
        vTextPaint.setAntiAlias(true);//抗锯齿功能
        vTextPaint.setTextSize(numberTextSize);
        Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL);
        vTextPaint.setTypeface(font);//字体风格
        vTextPaint.setColor(Color.parseColor("#119c29"));
        Rect bounds_Number = new Rect();
        vTextPaint.getTextBounds(stepNumber, 0, stepNumber.length(), bounds_Number);
        canvas.drawText(stepNumber, centerX, getHeight() / 2 + bounds_Number.height() / 2, vTextPaint);

    }

    /**
     * 4.圆环中心[步数]的文字
     */
    private void drawTextStepString(Canvas canvas, float centerX) {
        Paint vTextPaint = new Paint();
        vTextPaint.setTextSize(dipToPx(16));
        vTextPaint.setTextAlign(Paint.Align.CENTER);
        vTextPaint.setAntiAlias(true);//抗锯齿功能
        vTextPaint.setColor(Color.parseColor("#119c29"));
        String stepString = "步数";
        Rect bounds = new Rect();
        vTextPaint.getTextBounds(stepString, 0, stepString.length(), bounds);
        canvas.drawText(stepString, centerX, getHeight() / 2 + bounds.height() + getFontHeight(numberTextSize), vTextPaint);
    }

    /**
     * 获取当前步数的数字的高度
     *
     * @param fontSize 字体大小
     * @return 字体高度
     */
    public int getFontHeight(float fontSize) {
        Paint paint = new Paint();
        paint.setTextSize(fontSize);
        Rect bounds_Number = new Rect();
        paint.getTextBounds(stepNumber, 0, stepNumber.length(), bounds_Number);
        return bounds_Number.height();
    }

    /**
     * dip 转换成px
     *
     * @param dip
     * @return
     */

    private int dipToPx(float dip) {
        float density = getContext().getResources().getDisplayMetrics().density;
        return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1));
    }

    /**
     * 所走的步数进度
     *
     * @param totalStepNum  设置的步数
     * @param currentCounts 所走步数
     */
    public void setCurrentCount(int totalStepNum, int currentCounts) {
        stepNumber = currentCounts + "";
        setTextSize(currentCounts);
        /**如果当前走的步数超过总步数则圆弧还是270度,不能成为园*/
        if (currentCounts > totalStepNum) {
            currentCounts = totalStepNum;
        }
        /**所走步数占用总共步数的百分比*/
        float scale = (float) currentCounts / totalStepNum;
        /**换算成弧度最后要到达的角度的长度-->弧长*/
        float currentAngleLength = scale * angleLength;
        /**开始执行动画*/
        setAnimation(0, currentAngleLength, animationLength);
    }

    /**
     * 为进度设置动画
     * ValueAnimator是整个属性动画机制当中最核心的一个类,属性动画的运行机制是通过不断地对值进行操作来实现的,
     * 而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。
     * 它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,
     * 我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,
     * 那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。
     *
     * @param start   初始值
     * @param current 结束值
     * @param length  动画时长
     */
    private void setAnimation(float start, float current, int length) {
        ValueAnimator progressAnimator = ValueAnimator.ofFloat(start, current);
        progressAnimator.setDuration(length);
        progressAnimator.setTarget(currentAngleLength);
        progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                /**每次在初始值和结束值之间产生的一个平滑过渡的值,逐步去更新进度*/
                currentAngleLength = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        progressAnimator.start();
    }

    /**
     * 设置文本大小,防止步数特别大之后放不下,将字体大小动态设置
     *
     * @param num
     */
    public void setTextSize(int num) {
        String s = String.valueOf(num);
        int length = s.length();
        if (length <= 4) {
            numberTextSize = dipToPx(50);
        } else if (length > 4 && length <= 6) {
            numberTextSize = dipToPx(40);
        } else if (length > 6 && length <= 8) {
            numberTextSize = dipToPx(30);
        } else if (length > 8) {
            numberTextSize = dipToPx(25);
        }
    }

}
 
/**
 * SharedPreferences的一个工具类,调用setParam就能保存String, Integer, Boolean, Float,
 * Long类型的参数 同样调用getParam就能获取到保存在手机里面的数据
 * 
 * @author xiaanming
 */
public class SharedPreferencesUtils {
   private Context context;
   /**
    * 保存在手机里面的文件名
    */
   private String FILE_NAME = "share_date";

   // public static SharedPreferencesUtils getInstens(String fileName) {
   // FILE_NAME = fileName;
   // if (sharedPreferencesUtils == null) {
   // synchronized (SharedPreferencesUtils.class) {
   // if (sharedPreferencesUtils == null) {
   // sharedPreferencesUtils = new SharedPreferencesUtils();
   // }
   // }
   // }
   // return sharedPreferencesUtils;
   // }

   public SharedPreferencesUtils(String FILE_NAME) {
      this.FILE_NAME = FILE_NAME;

   }
   public SharedPreferencesUtils(Context context) {
   this.context=context;

   }
   /**
    * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
    * 
    * @param key
    * @param object
    */
   public void setParam(String key, Object object) {

      String type = object.getClass().getSimpleName();
      SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
            Context.MODE_MULTI_PROCESS);
      SharedPreferences.Editor editor = sp.edit();
      if ("String".equals(type)) {
         editor.putString(key,  object.toString());
      } else if ("Integer".equals(type)) {
         editor.putInt(key, (Integer) object);
      } else if ("Boolean".equals(type)) {
         editor.putBoolean(key, (Boolean) object);
      } else if ("Float".equals(type)) {
         editor.putFloat(key, (Float) object);
      } else if ("Long".equals(type)) {
         editor.putLong(key, (Long) object);
      }

      editor.commit();
   }

   /**
    * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
    * 
    * @param key
    * @param defaultObject
    * @return
    */
   public Object getParam(String key, Object defaultObject) {
      String type = defaultObject.getClass().getSimpleName();
      SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
            Context.MODE_PRIVATE);

      if ("String".equals(type)) {
         return sp.getString(key, (String) defaultObject);
      } else if ("Integer".equals(type)) {
         return sp.getInt(key, (Integer) defaultObject);
      } else if ("Boolean".equals(type)) {
         return sp.getBoolean(key, (Boolean) defaultObject);
      } else if ("Float".equals(type)) {
         return sp.getFloat(key, (Float) defaultObject);
      } else if ("Long".equals(type)) {
         return sp.getLong(key, (Long) defaultObject);
      }

      return null;
   }

   /**
    * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
    * 
    * @param key
    * @return
    */
   // Delete
   public void remove( String key) {
      SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
            Context.MODE_PRIVATE);
      SharedPreferences.Editor editor = sp.edit();
      editor.remove(key);
      editor.commit();
   }

   public void clear() {
      SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
            Context.MODE_PRIVATE);
      SharedPreferences.Editor editor = sp.edit();
      editor.clear();
      editor.commit();
   }
}

 
布局文件引用
<com.happydo.sport.widget.StepArcView
    android:id="@+id/cc"
    android:layout_width="@dimen/dp_180"
    android:layout_height="@dimen/dp_180"
    android:layout_centerHorizontal="true"
     />
在activity中使用
SharedPreferencesUtils sp = new SharedPreferencesUtils(getActivity());
String planWalk_QTY = (String) sp.getParam("planWalk_QTY", "500");//设置目标步数

 
StepArcView  cc.setCurrentCount(Integer.parseInt(planWalk_QTY), step);//显示步数

完成。
 

                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现圆弧进度条的自定义ProgressBar,可以使用Canvas和Paint来绘制。 首先,创建一个自定义的ProgressBar类,继承自ProgressBar类,并实现构造方法和onDraw方法: ``` public class CircleProgressBar extends ProgressBar { private Paint paint; // 画笔 private int roundColor; // 圆环颜色 private int progressColor; // 进度条颜色 private int textColor; // 文字颜色 private float textSize; // 文字大小 private float roundWidth; // 圆环宽度 private int max; // 最大进度 private boolean textIsDisplayable; // 是否显示进度文字 private int style; // 进度条样式 public static final int STROKE = 0; public static final int FILL = 1; public CircleProgressBar(Context context) { this(context, null); } public CircleProgressBar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CircleProgressBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // 获取自定义属性的值 TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressBar); roundColor = mTypedArray.getColor(R.styleable.CircleProgressBar_roundColor, Color.RED); progressColor = mTypedArray.getColor(R.styleable.CircleProgressBar_progressColor, Color.GREEN); textColor = mTypedArray.getColor(R.styleable.CircleProgressBar_textColor, Color.GREEN); textSize = mTypedArray.getDimension(R.styleable.CircleProgressBar_textSize, 15); roundWidth = mTypedArray.getDimension(R.styleable.CircleProgressBar_roundWidth, 5); max = mTypedArray.getInteger(R.styleable.CircleProgressBar_max, 100); textIsDisplayable = mTypedArray.getBoolean(R.styleable.CircleProgressBar_textIsDisplayable, true); style = mTypedArray.getInt(R.styleable.CircleProgressBar_style, 0); mTypedArray.recycle(); // 初始化画笔 paint = new Paint(); } @Override protected synchronized void onDraw(Canvas canvas) { super.onDraw(canvas); // 获取圆心坐标和半径 int centerX = getWidth() / 2; int centerY = getHeight() / 2; int radius = (int) (centerX - roundWidth / 2); // 绘制圆环 paint.setColor(roundColor); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(roundWidth); paint.setAntiAlias(true); canvas.drawCircle(centerX, centerY, radius, paint); // 绘制进度条 paint.setStrokeWidth(roundWidth); paint.setColor(progressColor); RectF oval = new RectF(centerX - radius, centerY - radius, centerX + radius, centerY + radius); switch (style) { case STROKE: paint.setStyle(Paint.Style.STROKE); canvas.drawArc(oval, 0, 360 * getProgress() / getMax(), false, paint); break; case FILL: paint.setStyle(Paint.Style.FILL_AND_STROKE); if (getProgress() != 0) canvas.drawArc(oval, 0, 360 * getProgress() / getMax(), true, paint); break; } // 绘制文字 paint.setStrokeWidth(0); paint.setColor(textColor); paint.setTextSize(textSize); paint.setTypeface(Typeface.DEFAULT_BOLD); int percent = (int) (((float) getProgress() / (float) getMax()) * 100); if (textIsDisplayable && percent >= 0) { String text = percent + "%"; float textWidth = paint.measureText(text); canvas.drawText(text, centerX - textWidth / 2, centerY + textSize / 2, paint); } } } ``` 在这个类中,我们定义了几个自定义属性,包括圆环颜色、进度条颜色、文字颜色、文字大小、圆环宽度、最大进度、是否显示进度文字、进度条样式等。在构造方法中,我们获取了这些属性的值,并初始化了画笔。在onDraw方法中,我们首先获取了圆心坐标和半径,然后使用画笔绘制了圆环和进度条,最后绘制了进度文字。 接下来,在布局文件中使用这个自定义ProgressBar: ``` <com.example.circleprogressbar.CircleProgressBar android:id="@+id/circle_progressbar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" app:roundColor="#cccccc" app:roundWidth="5dp" app:progressColor="#FF4081" app:textColor="#FF4081" app:textSize="20sp" app:textIsDisplayable="true" app:style="STROKE" /> ``` 最后,在Java代码中设置进度值即可: ``` CircleProgressBar circleProgressBar = findViewById(R.id.circle_progressbar); circleProgressBar.setProgress(50); // 设置进度为50% ``` 这样就完成了自定义圆弧进度条的实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值