欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义View圆形百分比控件(一)

程序员文章站 2023-11-21 10:50:10
做一个自定义view的小练习,效果如下 只需要画一个圆、一个圆弧、一个百分比文本,添加一个点击事件,传入百分比重绘 1、在res/values文件夹下新建attrs...

做一个自定义view的小练习,效果如下

Android自定义View圆形百分比控件(一)

只需要画一个圆、一个圆弧、一个百分比文本,添加一个点击事件,传入百分比重绘

1、在res/values文件夹下新建attrs.xml文件,编写自定义属性:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <declare-styleable name="circlepercentview" >
    <attr name="circlebg" format="color"/>
    <attr name="arccolor" format="color"/>
    <attr name="arcwidth" format="dimension"/>
    <attr name="percenttextcolor" format="color"/>
    <attr name="percenttextsize" format="dimension"/>
    <attr name="radius" format="dimension"/>
  </declare-styleable>
</resources>

2、新建circlepercentview继承view,重写构造方法:

public circlepercentview(context context) {
    this(context, null);
  }

  public circlepercentview(context context, attributeset attrs) {
    this(context, attrs, 0);
  }

  public circlepercentview(context context, attributeset attrs, int defstyleattr) {
    super(context, attrs, defstyleattr);
  }

3、在第三个构造方法中获取自定义属性的值:

    typedarray ta = context.obtainstyledattributes(attrs, r.styleable.circlepercentview, defstyleattr, 0);
    mcirclecolor = ta.getcolor(r.styleable.circlepercentview_circlebg, 0xff8e29fa);
    marccolor = ta.getcolor(r.styleable.circlepercentview_arccolor, 0xffffee00);
    marcwidth = ta.getdimensionpixelsize(r.styleable.circlepercentview_arcwidth, densityutils.dp2px(context, 16));
    mpercenttextcolor = ta.getcolor(r.styleable.circlepercentview_arccolor, 0xffffee00);
    mpercenttextsize = ta.getdimensionpixelsize(r.styleable.circlepercentview_percenttextsize, densityutils.sp2px(context, 16));
    mradius = ta.getdimensionpixelsize(r.styleable.circlepercentview_radius, densityutils.dp2px(context, 100));
    ta.recycle();

4、创建画图所使用的对象,如paint、rect、rectf:

    mcirclepaint = new paint(paint.anti_alias_flag);
    mcirclepaint.setstyle(paint.style.fill);
    mcirclepaint.setcolor(mcirclecolor);

    marcpaint = new paint(paint.anti_alias_flag);
    marcpaint.setstyle(paint.style.stroke);
    marcpaint.setstrokewidth(marcwidth);
    marcpaint.setcolor(marccolor);
    marcpaint.setstrokecap(paint.cap.round);//使圆弧两头圆滑

    mpercenttextpaint = new paint(paint.anti_alias_flag);
    mpercenttextpaint.setstyle(paint.style.stroke);
    mpercenttextpaint.setcolor(mpercenttextcolor);
    mpercenttextpaint.settextsize(mpercenttextsize);

    marcrectf = new rectf();//圆弧的外接矩形

    mtextbound = new rect();//文本的范围矩形

5、重写onmeasure()方法,计算自定义view的宽高:

 @override
  protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
    setmeasureddimension(measuredimension(widthmeasurespec), measuredimension(heightmeasurespec));
  }

  private int measuredimension(int measurespec) {
    int result;
    int specmode = measurespec.getmode(measurespec);
    int specsize = measurespec.getsize(measurespec);
    if (specmode == measurespec.exactly) {//精确地,代表宽高为定值或者match_parent时
      result = specsize;
    } else {
      result = 2 * mradius;
      if (specmode == measurespec.at_most) {//最大地,代表宽高为wrap_content时
        result = math.min(result, specsize);
      }
    }
    return result;
  }

6、重写ondraw()方法,绘制圆、圆弧和百分比文本,注意坐标的计算:

Android自定义View圆形百分比控件(一)

  @override
  protected void ondraw(canvas canvas) {
    //画圆
    canvas.drawcircle(getwidth() / 2, getheight() / 2, mradius, mcirclepaint);

    //画圆弧
    marcrectf.set(getwidth() / 2 - mradius + marcwidth / 2, getheight() / 2 - mradius + marcwidth / 2
        , getwidth() / 2 + mradius - marcwidth / 2, getheight() / 2 + mradius - marcwidth / 2);
    canvas.drawarc(marcrectf, 270, 360 * mcurpercent / 100, false, marcpaint);

    string text = mcurpercent + "%";
    //计算文本宽高
    mpercenttextpaint.gettextbounds(text, 0, string.valueof(text).length(), mtextbound);
    //画百分比文本
    canvas.drawtext(text, getwidth() / 2 - mtextbound.width() / 2
        , getheight() / 2 + mtextbound.height() / 2, mpercenttextpaint);
  }

7、给这个view设置点击事件,暴露一个动态设置百分比的方法:

  public void setcurpercent(float curpercent) {
    valueanimator anim = valueanimator.offloat(mcurpercent, curpercent);
    //动画时长由百分比大小决定
    anim.setduration((long) (math.abs(mcurpercent - curpercent) * 20));
    anim.addupdatelistener(new valueanimator.animatorupdatelistener() {
      @override
      public void onanimationupdate(valueanimator animation) {
        float value = (float) animation.getanimatedvalue();
        mcurpercent = (float) (math.round(value * 10)) / 10;//四舍五入保留到小数点后两位
        invalidate();//重绘,重走ondraw()方法,这也是不能再ondraw()中创建对象的原因
      }
    });
    anim.start();
  }

  public void setoncircleclicklistener(onclicklistener onclicklistener) {
    this.monclicklistener = onclicklistener;
  }

    //在构造方法中
    setonclicklistener(new onclicklistener() {
      @override
      public void onclick(view v) {
        if (monclicklistener != null) {
          monclicklistener.onclick(circlepercentview.this);
        }
      }
    });

8、在activity_main.xml布局文件中使用该view:

<!-- 使用自定义命名空间namespace,cpv是该控件名的首字母缩写,可以随意取 -->
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:cpv="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <!-- cpv后面的属性名对应attrs.xml文件中的自定义属性名 -->
  <com.monkey.customviewdemo.view.circlepercentview
    android:id="@+id/circlepercentview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    cpv:arccolor="#ffee00"
    cpv:arcwidth="@dimen/activity_horizontal_margin"
    cpv:circlebg="#8e29fa"
    cpv:percenttextcolor="#ffee00"
    cpv:percenttextsize="16sp"
    cpv:radius="100dp" />
</relativelayout>

9、在mainactivity.java中设置监听,传入百分比:

  mcirclepercentview = (circlepercentview) findviewbyid(r.id.circlepercentview);
  mcirclepercentview.setoncircleclicklistener(new view.onclicklistener() {
    @override
    public void onclick(view v) {
      float percent = (float) (math.random() * 99 + 1);
      mcirclepercentview.setcurpercent(percent);
    }
  });


代码下载地址:
https://github.com/monkeymushroom/circlepercentview/tree/master

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