当前位置: 移动技术网 > IT编程>移动开发>Android > Android实现渐变圆环、圆形进度条效果

Android实现渐变圆环、圆形进度条效果

2019年08月02日  | 移动技术网IT编程  | 我要评论

永远的花样年华伴奏,qq炫舞房间设计图,福建泉州江豚搁浅

最近做了一个功能,里面涉及到了渐变圆形的需求。就是一个颜色可以渐变的圆环,最后实现的效果如下图:

左图是带渐变效果,右图是不带渐变效果。原理还是绘图,canvas可以绘制的对象有:弧线(arcs)、填充颜色(argb和color)、 bitmap、圆(circle和oval)、点(point)、线(line)、矩形(rect)、图片(picture)、圆角矩形 (roundrect)、文本(text)、顶点(vertices)、路径(path)。通过组合这些对象我们可以画出一些简单有趣的界面出来,但是光有这些功能还是不够的,如果我要画一个仪表盘(数字围绕显示在一个圆圈中)呢? 幸好android还提供了一些对canvas位置转换的方法:rorate、scale、translate、skew(扭曲)等,而且它允许你通过获得它的转换矩阵对象(getmatrix方法,不知道什么是转换矩阵?)  直接操作它。这些操作就像是虽然你的笔还是原来的地方画,但是画纸旋转或者移动了,所以你画的东西的方位就产生变化。为了方便一些转换操作,canvas 还提供了保存和回滚属性的方法(save和restore),比如你可以先保存目前画纸的位置(save),然后旋转90度,向下移动100像素后画一些图形,画完后调用restore方法返回到刚才保存的位置。

话不多说,上代码

核心类:

自定义控件 circleprogressbar

package com.jky.mobile_xmxt.view;
 
import android.content.context;
import android.graphics.canvas;
import android.graphics.color;
import android.graphics.paint;
import android.graphics.rectf;
import android.graphics.sweepgradient;
import android.util.attributeset;
import android.view.view;
import android.view.animation.animation;
import android.view.animation.transformation;
 
import com.jky.mobile_xmxt.r;
 
import java.text.decimalformat;
 
/**
 * 圆盘计步图表
 */
public class circleprogressbar extends view {
 
 private rectf mwheelrect = new rectf();
 private paint mdefaultwheelpaint;
 private paint mfinishwheelpaint;
 private paint mcenterwheelpaint;
 private paint mtitlepaint, msteppaint, mtargetpaint;
 private float mcirclestrokewidth;
 private float msweepangleper;
 private float mpercent;
 private int mstepnum, mcurrstepnum;
 private float pressextrastrokewidth;
 private baranimation manim;
 private int mmaxstepnum;// 默认最大步数
 private float mtitley, mstepy, mtargety;
 private decimalformat mdecimalformat = new decimalformat("#.0");// 格式为保留小数点后一位
 public static string goal_step;
 public static string percent;
 
 public circleprogressbar(context context) {
 super(context);
 init(null, 0);
 }
 
 public circleprogressbar(context context, attributeset attrs) {
 super(context, attrs);
 init(attrs, 0);
 }
 
 public circleprogressbar(context context, attributeset attrs, int defstyle) {
 super(context, attrs, defstyle);
 init(attrs, defstyle);
 }
 
 private void init(attributeset attrs, int defstyle) {
 
 mfinishwheelpaint = new paint();
 mfinishwheelpaint.setcolor(color.rgb(100, 113, 205));
 mfinishwheelpaint.setstyle(paint.style.stroke);// 空心
 mfinishwheelpaint.setstrokecap(paint.cap.round);// 圆角画笔
 mfinishwheelpaint.setantialias(true);// 去锯齿
 
 mcenterwheelpaint = new paint();
 mcenterwheelpaint.setcolor(color.rgb(243, 243, 243));
 mcenterwheelpaint.setstyle(paint.style.stroke);
 mcenterwheelpaint.setstrokecap(paint.cap.round);
 mcenterwheelpaint.setantialias(true);
 
 mdefaultwheelpaint = new paint();
 mdefaultwheelpaint.setcolor(color.rgb(127, 127, 127));
 mdefaultwheelpaint.setstyle(paint.style.stroke);
 mdefaultwheelpaint.setstrokecap(paint.cap.round);
 mdefaultwheelpaint.setantialias(true);
 
 mtitlepaint = new paint();
 mtitlepaint.setantialias(true);
 mtitlepaint.setcolor(color.white);
 
 msteppaint = new paint();
 msteppaint.setantialias(true);
 msteppaint.setcolor(color.white);
 
 mtargetpaint = new paint();
 mtargetpaint.setantialias(true);
 mtargetpaint.setcolor(color.white);
 manim = new baranimation();
 }
 
 @override
 protected void ondraw(canvas canvas) {
 canvas.drawarc(mwheelrect, 0, 359, false, mdefaultwheelpaint);
 canvas.drawarc(mwheelrect, 0, 359, false, mcenterwheelpaint);
 canvas.drawarc(mwheelrect, 90, msweepangleper, false, mfinishwheelpaint);
// canvas.drawtext("步数", mwheelrect.centerx() - (mtitlepaint.measuretext("步数") / 2), mtitley,
// mtitlepaint);
 canvas.drawtext(mcurrstepnum + "",
  mwheelrect.centerx() - (msteppaint.measuretext(string.valueof(mcurrstepnum)) / 2), mstepy,
  msteppaint);
 string description = "";
 float percent = getpercent();
 if(percent > 0.5){
  description ="严重污染";
 }else if(percent<0.5){
  description ="中等污染";
 }else{
  description ="普通污染";
 }
 
 canvas.drawtext(description , mwheelrect.centerx() -
  (mtargetpaint.measuretext(description) / 2), mtargety, mtargetpaint);
 sweepgradient sweepgradient = new sweepgradient(mwheelrect.centerx(), mwheelrect.centery(),
  new int[]{getresources().getcolor(r.color.color_environment_severe), getresources().getcolor(r.color.color_environment_serious),
   getresources().getcolor(r.color.color_environment_excellent),
   getresources().getcolor(r.color.color_environment_good), getresources().getcolor(r.color.color_environment_mild),
   getresources().getcolor(r.color.color_environment_moderate)}, null);
 mfinishwheelpaint.setshader(sweepgradient);
 }
 
 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
 int height = getdefaultsize(getsuggestedminimumheight(), heightmeasurespec);
 int width = getdefaultsize(getsuggestedminimumwidth(), widthmeasurespec);
 int min = math.min(width, height);// 获取view最短边的长度
 setmeasureddimension(min, min);// 强制改view为以最短边为长度的正方形
 mcirclestrokewidth = gettextscale(15, min);// 圆弧的宽度
 pressextrastrokewidth = gettextscale(10, min);// 圆弧离矩形的距离
 mwheelrect.set(mcirclestrokewidth + pressextrastrokewidth, mcirclestrokewidth + pressextrastrokewidth,
  min - mcirclestrokewidth - pressextrastrokewidth, min - mcirclestrokewidth - pressextrastrokewidth);// 设置矩形
 mtitlepaint.settextsize(gettextscale(60, min));
 msteppaint.settextsize(gettextscale(120, min));
 mtargetpaint.settextsize(gettextscale(40, min));
 mtitley = gettextscale(170, min);
 mstepy = gettextscale(300, min);
 mtargety = gettextscale(380, min);
 mfinishwheelpaint.setstrokewidth(mcirclestrokewidth);
 mcenterwheelpaint.setstrokewidth(mcirclestrokewidth);
 mdefaultwheelpaint.setstrokewidth(mcirclestrokewidth - gettextscale(2, min));
 mdefaultwheelpaint.setshadowlayer(gettextscale(10, min), 0, 0, color.rgb(127, 127, 127));// 设置阴影
 }
 
 /**
 * 进度条动画
 *
 * @author administrator
 */
 public class baranimation extends animation {
 
 /**
  * 每次系统调用这个方法时, 改变msweepangleper,mpercent,stepnumbernow的值,
  * 然后调用postinvalidate()不停的绘制view。
  */
 @override
 protected void applytransformation(float interpolatedtime, transformation t) {
// if (interpolatedtime < 1.0f) {
// mpercent = float.parsefloat(mdecimalformat.format(interpolatedtime * mstepnum * 100f / mmaxstepnum));// 将浮点值四舍五入保留一位小数
// msweepangleper = interpolatedtime * mstepnum * 360 / mmaxstepnum;
// mcurrstepnum = (int) (interpolatedtime * mstepnum);
// } else {
  mpercent = float.parsefloat(mdecimalformat.format(mstepnum * 100f / mmaxstepnum));// 将浮点值四舍五入保留一位小数
  if (mpercent > 100.0f) {
  mpercent = 100.0f;
  }
  percent = string.valueof(mpercent);
  msweepangleper = mstepnum * 360 / mmaxstepnum;
  mcurrstepnum = mstepnum;
// }
 
  requestlayout();
 }
 }
 
 public float getpercent() {
 return mpercent;
 }
 
 /**
 * 根据控件的大小改变绝对位置的比例
 *
 * @param n
 * @param m
 * @return
 */
 public float gettextscale(float n, float m) {
 return n / 500 * m;
 }
 
 /**
 * 更新步数和设置一圈动画时间
 *
 * @param stepcount
 * @param time
 */
 public void update(int stepcount, int time) {
 this.mstepnum = stepcount;
 manim.setduration(time);
 // setanimationtime(time);
 this.startanimation(manim);
 }
 
 /**
 * @param stepnum
 */
 public void setmaxstepnum(int stepnum) {
 mmaxstepnum = stepnum;
 goal_step = string.valueof(mmaxstepnum);
 }
 
 public void setcolor(int color) {
 mfinishwheelpaint.setcolor(color);
 msteppaint.setcolor(color);
 }
 
 /**
 * 设置动画时间
 *
 * @param time
 */
 public void setanimationtime(int time) {
 manim.setduration(time * mstepnum / mmaxstepnum);// 按照比例设置动画执行时间
 }
 
}

xml引用

<com.jky.mobile_xmxt.view.circleprogressbar
 android:id="@+id/color_progress_view"
 android:layout_width="match_parent"
 android:layout_height="0dp"
 android:layout_weight="6"
 />

activity调用方法

color_progress_view = (circleprogressbar)view.findviewbyid(r.id.color_progress_view);
color_progress_view.setmaxstepnum(500);
color_progress_view.update(470,1000);

由于和调用其他控件方法类似,姑且省去了很多其他业务逻辑代码,代码不是特别复杂,修改起来也很方便(修改颜色,总量及比例等),所以只粘贴核心相关的代码,希望可以帮助到大家。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网