自定义View之简单自定义圆形进度条

本文介绍了一种自定义圆形进度条的方法,通过定义背景颜色、进度颜色、半径及起始角度等属性,并实现了进度条的动态更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

达到的效果如下:
这里写图片描述

从上面的效果可以看出,主要有以下几个自定义属性:
1、背景颜色
2、进度扇形颜色
3、半径
4、起始角度
因此,在attrs.xml中定义如下属性:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <declare-styleable name="SimpleRoundProgressBar">
    <attr format="color" name="roundColor"/>
    <attr format="color" name="roundProgressColor"/>
    <attr format="dimension" name="circleRadius"/>
    <attr format="integer" name="startAngle"/>
  </declare-styleable>
</resources>

下面是SimpleRoundProgressBar代码,在onMeasure当中确定view的大小,在onDraw来进行绘制。

package com.easyliu.demo.customizeview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by easyliu on 2017/2/24.
 */

public class SimpleRoundProgressBar extends View {
  private Paint mPaint;//画笔
  private RectF mRectF;//扇形绘制的矩形范围
  private int mRoundColor;//圆环的颜色
  private int mRoundProgressColor; //进度条的颜色
  private float mRadius;//半径
  private int mWidth;  //宽度
  private int mHeight; //高度
  private int mCenterX; //中心X坐标
  private int mCenterY; //中心Y坐标
  private int mStartAngle; //初始角度
  private int mSweepAngle; //扫过的角度
  private static final int DEFAULT_INIT_ANGLE = 0;//默认的初始化角度
  private static final int DEFAULT_RADIUS = 10;//默认的半径

  public SimpleRoundProgressBar(Context context) {
    this(context, null);
  }

  public SimpleRoundProgressBar(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public SimpleRoundProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    mPaint = new Paint();
    mRectF = new RectF();
    TypedArray typedArray =
        context.obtainStyledAttributes(attrs, R.styleable.SimpleRoundProgressBar);
    mRoundColor = typedArray.getColor(R.styleable.SimpleRoundProgressBar_roundColor, Color.GRAY);
    mRoundProgressColor =
        typedArray.getColor(R.styleable.SimpleRoundProgressBar_roundProgressColor, Color.RED);
    mRadius =
        typedArray.getDimension(R.styleable.SimpleRoundProgressBar_circleRadius, DEFAULT_RADIUS);
    mStartAngle =
        typedArray.getInteger(R.styleable.SimpleRoundProgressBar_startAngle, DEFAULT_INIT_ANGLE);
    typedArray.recycle();
  }

  @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    //获取测量模式
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    //获取测量大小
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    //如果为确定值
    if (heightMode == MeasureSpec.EXACTLY) {
      mHeight = heightSize;
    } else {
      //如果为wrap_content,高度为半径大小乘以2,注意padding
      mHeight = (int) (mRadius * 2) + getPaddingTop() + getPaddingBottom();
    }

    //如果为确定值
    if (widthMode == MeasureSpec.EXACTLY) {
      mWidth = widthSize;
      mHeight=mWidth;//宽和高相等
    } else {
      //如果为wrap_content,宽度为半径大小乘以2,注意padding
      mWidth = (int) (mRadius * 2) + getPaddingLeft() + getPaddingRight();
    }

    //设置视图的大小
    setMeasuredDimension(mWidth, mHeight);
  }

  @Override protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    mPaint.setColor(mRoundColor);
    mPaint.setAntiAlias(true);
    mCenterX = mWidth / 2;
    mCenterY = mHeight / 2;
    //注意处理padding
    mRadius = (mWidth - getPaddingLeft() - getPaddingRight()) / 2;
    //画圆
    canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
    mPaint.setColor(mRoundProgressColor);
    //注意处理padding
    mRectF.left = getPaddingLeft();
    mRectF.right = mWidth - getPaddingRight();
    mRectF.top = getPaddingTop();
    mRectF.bottom = mHeight - getPaddingBottom();
    //画扇形
    canvas.drawArc(mRectF, (float) mStartAngle, mSweepAngle, true, mPaint);
  }

  public int getRoundColor() {
    return mRoundColor;
  }

  public void setRoundColor(int roundColor) {
    this.mRoundColor = roundColor;
  }

  /**
   * 得到初始角度
   */
  public synchronized int getStartAngle() {
    return mStartAngle;
  }

  /**
   * 设置初始角度
   */
  public synchronized void setStartAngle(int startAngle) {
    if (startAngle < -360) {
      throw new IllegalArgumentException("the angle can not less than -360");
    }
    if (startAngle > 360) {
      throw new IllegalArgumentException("the angle can not larger than 360");
    }
    this.mStartAngle = startAngle;
  }

  /**
   * 得到扫过的角度
   */
  public synchronized int getSweepAngle() {
    return mSweepAngle;
  }

  /**
   * 设置扫过的角度,相对于起始点
   *
   * @param sweepAngle 0~360
   */
  public synchronized void setSweepAngle(int sweepAngle) {
    if (sweepAngle < 0) {
      throw new IllegalArgumentException("the angle can not less than 0");
    }
    if (sweepAngle > 360) {
      throw new IllegalArgumentException("the angle can not larger than 360");
    }
    this.mSweepAngle = sweepAngle;
    postInvalidate();
  }
}

定义好了之后就可以使用了,首先是xml文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:easyliu="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.easyliu.demo.customizeview.RoundProgressBarActivity"
    >

  <com.easyliu.demo.customizeview.SimpleRoundProgressBar
      android:id="@+id/progress_demo"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerHorizontal="true"
      android:padding="10dp"
      easyliu:circleRadius="50dp"
      easyliu:roundColor="#5F000000"
      easyliu:roundProgressColor="#ff8d33"
      />

  <com.easyliu.demo.customizeview.SimpleRoundProgressBar
      android:id="@+id/progress_demo2"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerHorizontal="true"
      android:layout_below="@id/progress_demo"
      android:padding="10dp"
      easyliu:circleRadius="60dp"
      easyliu:roundColor="@color/colorPrimary"
      easyliu:roundProgressColor="@color/colorAccent"
      />

</RelativeLayout>

然后是Activity代码,在代码中使用定时器来定时更新进度即可。

package com.easyliu.demo.customizeview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.util.Timer;
import java.util.TimerTask;

public class RoundProgressBarActivity extends AppCompatActivity {
  private int mCurrentAngle = 0;
  private SimpleRoundProgressBar mRoundProgressBar1;
  private SimpleRoundProgressBar mRoundProgressBar2;

  @Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_progress_bar);
    initViews();
    Timer timer = new Timer();
    timer.schedule(new TimerTask() {
      @Override public void run() {
        mCurrentAngle++;
        mRoundProgressBar1.setSweepAngle(mCurrentAngle);
        mRoundProgressBar2.setSweepAngle(mCurrentAngle);
        if (mCurrentAngle >= 360) {
          mCurrentAngle = 0;
        }
      }
    }, 0, 20);
  }
  private void initViews(){
    mRoundProgressBar1 =
        (SimpleRoundProgressBar) findViewById(R.id.progress_demo);
    mRoundProgressBar1.setStartAngle(-90);
    mRoundProgressBar2= (SimpleRoundProgressBar) findViewById(R.id.progress_demo2);
    mRoundProgressBar2.setStartAngle(0);
  }
}

这样就完成了一个简单的圆形进度条的自定义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值