微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Android自定义环形LoadingView效果

这篇文章主要为大家详细介绍了Android自定义环形LoadingView效果方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

最近项目有要用到环形的进度条,Github上有一个类似的DashedCircularProgress控件,但是他画的进度是通过设置画笔的虚线效果来实现间隔的:progresspaint.setPathEffect(new DashPathEffect(new float[]{dashWith, dashSpace}, dashSpace));如果内层还有一层圆环,在动态设置时,内层和外层有细微的偏差.于是我在原有基础上改了一个,实现了我要的效果(设置进度时可以选择加动画或者不加动画):

控件实现:

这个控件继承RelativeLayout,在onDraw时做了两件事:

1、先画出底部的黑色环形;
2、按照当时的进度值画出对应比例的外层绿色环形.

对外提供一个接口,回调当前进度值:

public interface OnValuechangelistener {
  void onValueChange(float value);
}

核心绘制类:

InternalCirclePainterImp2,绘制内层的黑色的环形:

/**
 * @author Chuck
 */
public class InternalCirclePainterImp2 implements InternalCirclePainter {

  private RectF internalCircle;//画出圆弧时,圆弧的外切矩形
  private Paint internalCirclePaint;
  private int color;
  private float startAngle = 270f;
  int arcQuantity=100;//等分(圆弧加间隔),比如arcQuantity=100时,表示将有100个圆弧,和100个空白间隔
  float ratio=0.5f;//每段圆弧与圆弧加间隔之和的比例,ratio=0.5表示每个圆弧与相邻的间隔弧度比是1:1
  private int width;
  private int height;
  private int internalstrokeWidth = 48;//圆环宽度

  public InternalCirclePainterImp2(int color, int progressstrokeWidth, int arcQuantity,float ratio) {
    this.color = color;
    this.internalstrokeWidth = progressstrokeWidth;
    this.arcQuantity = arcQuantity;
    if(ratio>0&&ratio<1){
      this.ratio = ratio;
    }

    init();
  }

  private void init() {
    initExternalCirclePainter();
  }

  private void initExternalCirclePainter() {
    internalCirclePaint = new Paint();
    internalCirclePaint.setAntiAlias(true);
    internalCirclePaint.setstrokeWidth(internalstrokeWidth);
    internalCirclePaint.setColor(color);
    internalCirclePaint.setStyle(Paint.Style.stroke);

  }

  //圆弧外切矩形
  private void initExternalCircle() {
    internalCircle = new RectF();
    float padding = internalstrokeWidth * 0.5f;
    internalCircle.set(padding, padding , width - padding, height - padding);
    initExternalCirclePainter();
  }


  @Override
  public void draw(Canvas canvas) {

    float eachAngle=360f/arcQuantity;

    float eachArcAngle=eachAngle*ratio;

    for(int i=0;i<arcQuantity*2;i++){
      if(i%2==0){//遇到偶数就画圆弧,基数则跳过
        canvas.drawArc(internalCircle, startAngle+eachAngle*i/2, eachArcAngle, false, internalCirclePaint);
      }
      else{
        continue;
      }
    }

  }

  public void setColor(int color) {
    this.color = color;
    internalCirclePaint.setColor(color);
  }

  @Override
  public int getColor() {
    return color;
  }

  @Override
  public void onSizeChanged(int height, int width) {
    this.width = width;
    this.height = height;
    initExternalCircle();
  }
}

ProgresspainterImp2,绘制内层的黑色的环形:

/**
 * @author Chuck
 */
public class ProgresspainterImp2 implements Progresspainter {

  private RectF progressCircle;
  private Paint progresspaint;
  private int color = Color.RED;
  private float startAngle = 270f;
  private int internalstrokeWidth = 48;
  private float min;
  private float max;
  private int width;
  private int height;

  private int currentPecent;//当前的百分比

  int arcQuantity=100;//等分(圆弧加间隔),比如arcQuantity=100时,表示将有100个圆弧,和100个空白间隔
  float ratio=0.5f;//每段圆弧与圆弧加间隔之和的比例,ratio=0.5表示每个圆弧与相邻的间隔弧度比是1:1

  public ProgresspainterImp2(int color, float min, float max, int progressstrokeWidth, int arcQuantity,float ratio) {
    this.color = color;
    this.min = min;
    this.max = max;
    this.internalstrokeWidth = progressstrokeWidth;
    this.arcQuantity = arcQuantity;
    this.ratio = ratio;
    init();
    Log.e(ProgresspainterImp,构造函数执行);
  }

  private void init() {
    initInternalCirclePainter();

  }

  private void initInternalCirclePainter() {
    progresspaint = new Paint();
    progresspaint.setAntiAlias(true);
    progresspaint.setstrokeWidth(internalstrokeWidth);
    progresspaint.setColor(color);
    progresspaint.setStyle(Paint.Style.stroke);

  }

  //初始化外切的那个矩形
  private void initInternalCircle() {
    progressCircle = new RectF();
    float padding = internalstrokeWidth * 0.5f;
    progressCircle.set(padding, padding , width - padding, height - padding);

    initInternalCirclePainter();
  }

  @Override
  public void draw(Canvas canvas) {

    float eachAngle=360f/arcQuantity;

    float eachArcAngle=eachAngle*ratio;

    int quantity=2*arcQuantity*currentPecent/100;
    for(int i=0;i<quantity;i++){
      if(i%2==0){//遇到偶数就画圆弧,基数则跳过
        canvas.drawArc(progressCircle, startAngle+eachAngle*i/2, eachArcAngle, false, progresspaint);
      }
      else{
        continue;
      }
    }
  }

  public float getMin() {
    return min;
  }

  public void setMin(float min) {
    this.min = min;
  }

  public float getMax() {
    return max;
  }

  public void setMax(float max) {
    this.max = max;
  }

  public void setValue(float value) {
    this.currentPecent = (int) (( 100f * value) / max);
  }

  @Override
  public void onSizeChanged(int height, int width) {
    Log.e(ProgresspainterImp,onSizeChanged执行);

    this.width = width;
    this.height = height;
    initInternalCircle();
  }

  public int getColor() {
    return color;
  }

  public void setColor(int color) {
    this.color = color;
    progresspaint.setColor(color);
  }
}

可以自定义属性:

<declare-styleable name=CircularLoadingView>
  <attr name=base_color format=color /> <!--内层圆环的颜色-->
  <attr name=progress_color format=color /><!--进度圆环的颜色-->
  <attr name=max format=float /><!--最小值-->
  <attr name=min format=float /><!--最大值-->
  <attr name=duration format=integer /><!--动画时长-->
  <attr name=progress_stroke_width format=integer /><!--圆环宽度-->

  <!--等分(圆弧加间隔),比如arcQuantity=100时,表示将有100个圆弧,和100个空白间隔-->
  <attr name=argQuantity format=integer />
  
  <!--每段圆弧与圆弧加间隔之和的比例,ratio=0.5表示每个圆弧与相邻的间隔弧度比是1:1-->
  <attr name=ratio format=float />
</declare-styleable>

调用:

main_activity.xml:

<?xml version=1.0 encoding=utf-8?>
<RelativeLayout
  xmlns:android=http://schemas.android.com/apk/res/android
  android:layout_width=match_parent
  android:layout_height=match_parent
  android:paddingBottom=@dimen/activity_vertical_margin
  android:paddingLeft=@dimen/activity_horizontal_margin
  android:paddingRight=@dimen/activity_horizontal_margin
  android:paddingTop=@dimen/activity_vertical_margin
  xmlns:custom=http://schemas.android.com/apk/res-auto
  android:background=#ffffff
  >

  <!--自定义控件,继承RelativeLayout-->
  <qdong.com.mylibrary.CircularLoadingView
    android:id=@+id/simple
    custom:base_color=@color/pager_bg
    custom:min=0
    custom:max=100
    custom:argQuantity=100
    custom:ratio=0.6
    custom:progress_color=@android:color/holo_green_light
    custom:progress_icon=@mipmap/ic_launcher
    custom:duration=1000
    custom:progress_stroke_width=28
    android:layout_centerInParent=true
    android:layout_width=200dp
    android:layout_height=200dp>

    <RelativeLayout
      android:layout_centerInParent=true
      android:layout_width=match_parent
      android:layout_height=match_parent>
      

        <TextView
          android:layout_centerInParent=true

          android:textSize=20sp
          android:layout_centerHorizontal=true
          android:id=@+id/number
          android:text=0
          android:gravity=center
          android:textColor=@color/pager_bg
          android:layout_width=wrap_content
          android:layout_height=wrap_content />

    </RelativeLayout>

  </qdong.com.mylibrary.CircularLoadingView>

  <Button
    android:layout_width=wrap_content
    android:layout_height=wrap_content
    android:text=Set_Value
    android:id=@+id/button
    android:layout_alignParentBottom=true
    android:layout_alignParentStart=true/>

  <Button
    android:layout_width=wrap_content
    android:layout_height=wrap_content
    android:text=Animation
    android:id=@+id/button3
    android:layout_alignTop=@+id/button
    android:layout_alignParentEnd=true/>
</RelativeLayout>

MainActivity:

findViewById(R.id.button).setonClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View view) {
    try {
      mDashedCircularProgress.setValue(66);//没有动画的,直接设置
    } catch (Exception e) {
      e.printstacktrace();
    }
  }
});
findViewById(R.id.button3).setonClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View view) {
    try {
      mDashedCircularProgress.setValue(0);//无动画,归零
      mDashedCircularProgress.setValueWithAnimation(100,2000);//带动画
    } catch (Exception e) {
      e.printstacktrace();
    }
  }
});

Github地址:https://github.com/506954774/AndroidCircularLoadingView

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。