Android自定义view渐变圆形动画

本文实例为大家分享了Android自定义view渐变圆形动画的具体代码,供大家参考,具体内容如下

直接上效果图

自定义属性

attrs.xml文件

<resources>
  <declare-styleable name="ProgressRing">
    <!--进度起始色-->
    <attr name="pr_progress_start_color" format="color" />
    <!--进度结束色-->
    <attr name="pr_progress_end_color" format="color" />
    <!--背景起始色-->
    <attr name="pr_bg_start_color" format="color" />
    <!--背景中间色-->
    <attr name="pr_bg_mid_color" format="color" />
    <!--背景结束色-->
    <attr name="pr_bg_end_color" format="color" />
    <!--进度值 介于0-100-->
    <attr name="pr_progress" format="integer" />
    <!--进度宽度-->
    <attr name="pr_progress_width" format="dimension" />
    <!--起始角度-->
    <attr name="pr_start_angle" format="integer" />
    <!--扫过的角度-->
    <attr name="pr_sweep_angle" format="integer" />
    <!--是否显示动画-->
    <attr name="pr_show_anim" format="boolean" />
  </declare-styleable>

</resources>

创建一个类 ProgressRing继承自 view

public class ProgressRing extends View {

  private int progressStartColor;
  private int progressEndColor;
  private int bgStartColor;
  private int bgMidColor;
  private int bgEndColor;
  private int progress;
  private float progressWidth;
  private int startAngle;
  private int sweepAngle;
  private boolean showAnim;

  private int mMeasureHeight;
  private int mMeasureWidth;

  private Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
  private Paint progressPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);

  private RectF pRectF;

  private float unitAngle;

  private int curProgress = 0;

  public ProgressRing(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ProgressRing);
    progressStartColor = ta.getColor(R.styleable.ProgressRing_pr_progress_start_color, Color.YELLOW);
    progressEndColor = ta.getColor(R.styleable.ProgressRing_pr_progress_end_color, progressStartColor);
    bgStartColor = ta.getColor(R.styleable.ProgressRing_pr_bg_start_color, Color.LTGRAY);
    bgMidColor = ta.getColor(R.styleable.ProgressRing_pr_bg_mid_color, bgStartColor);
    bgEndColor = ta.getColor(R.styleable.ProgressRing_pr_bg_end_color, bgStartColor);
    progress = ta.getInt(R.styleable.ProgressRing_pr_progress, 0);
    progressWidth = ta.getDimension(R.styleable.ProgressRing_pr_progress_width, 8f);
    startAngle = ta.getInt(R.styleable.ProgressRing_pr_start_angle, 150);
    sweepAngle = ta.getInt(R.styleable.ProgressRing_pr_sweep_angle, 240);
    showAnim = ta.getBoolean(R.styleable.ProgressRing_pr_show_anim, true);
    ta.recycle();

    unitAngle = (float) (sweepAngle / 100.0);

    bgPaint.setStyle(Paint.Style.STROKE);
    bgPaint.setStrokeCap(Paint.Cap.ROUND);
    bgPaint.setStrokeWidth(progressWidth);

    progressPaint.setStyle(Paint.Style.STROKE);
    progressPaint.setStrokeCap(Paint.Cap.ROUND);
    progressPaint.setStrokeWidth(progressWidth);

  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    /*for (int i = 0, end = (int) (progress * unitAngle); i <= end; i++) {
      progressPaint.setColor(getGradient(i / (float) end, progressStartColor, progressEndColor));
      canvas.drawArc(pRectF,
          startAngle + i,
          1,
          false,
          progressPaint);
    }*/
    if (!showAnim) {
      curProgress = progress;
    }

    drawBg(canvas);
    drawProgress(canvas);

    if (curProgress < progress) {
      curProgress++;
      postInvalidate();
    }
  }

  // 只需要画进度之外的背景即可
  private void drawBg(Canvas canvas) {
    float halfSweep = sweepAngle / 2;
    for (int i = sweepAngle, st = (int) (curProgress * unitAngle); i > st; --i) {
      if (i - halfSweep > 0) {
        bgPaint.setColor(getGradient((i - halfSweep) / halfSweep, bgMidColor, bgEndColor));
      } else {
        bgPaint.setColor(getGradient((halfSweep - i) / halfSweep, bgMidColor, bgStartColor));
      }
      canvas.drawArc(pRectF,
          startAngle + i,
          1,
          false,
          bgPaint);
    }
  }

  private void drawProgress(Canvas canvas) {
    for (int i = 0, end = (int) (curProgress * unitAngle); i <= end; i++) {
      progressPaint.setColor(getGradient(i / (float) end, progressStartColor, progressEndColor));
      canvas.drawArc(pRectF,
          startAngle + i,
          1,
          false,
          progressPaint);
    }
  }

  public void setProgress(@IntRange(from = 0, to = 100) int progress) {
    this.progress = progress;
    invalidate();
  }

  public int getProgress() {
    return progress;
  }

  public int getGradient(float fraction, int startColor, int endColor) {
    if (fraction > 1) fraction = 1;
    int alphaStart = Color.alpha(startColor);
    int redStart = Color.red(startColor);
    int blueStart = Color.blue(startColor);
    int greenStart = Color.green(startColor);
    int alphaEnd = Color.alpha(endColor);
    int redEnd = Color.red(endColor);
    int blueEnd = Color.blue(endColor);
    int greenEnd = Color.green(endColor);
    int alphaDifference = alphaEnd - alphaStart;
    int redDifference = redEnd - redStart;
    int blueDifference = blueEnd - blueStart;
    int greenDifference = greenEnd - greenStart;
    int alphaCurrent = (int) (alphaStart + fraction * alphaDifference);
    int redCurrent = (int) (redStart + fraction * redDifference);
    int blueCurrent = (int) (blueStart + fraction * blueDifference);
    int greenCurrent = (int) (greenStart + fraction * greenDifference);
    return Color.argb(alphaCurrent, redCurrent, greenCurrent, blueCurrent);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    mMeasureWidth = getMeasuredWidth();
    mMeasureHeight = getMeasuredHeight();
    if (pRectF == null) {
      float halfProgressWidth = progressWidth / 2;
      pRectF = new RectF(halfProgressWidth + getPaddingLeft(),
          halfProgressWidth + getPaddingTop(),
          mMeasureWidth - halfProgressWidth - getPaddingRight(),
          mMeasureHeight - halfProgressWidth - getPaddingBottom());
    }

  }
}

xml布局

<myCircle.ProgressRing
  android:layout_width="320dp"
  android:layout_height="320dp"
  android:layout_gravity="center_horizontal"
  app:pr_bg_end_color="#00ffffff"
  app:pr_bg_mid_color="#CCCCCC"
  app:pr_bg_start_color="#00ffffff"
  app:pr_progress="70"
  app:pr_progress_end_color="#F78930"
  app:pr_progress_start_color="#00ffffff"
  app:pr_progress_width="40dp" />

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

(0)

相关推荐

  • Android开发实现自动切换文字TextSwitcher功能示例

    本文实例讲述了Android开发实现自动切换文字TextSwitcher功能.分享给大家供大家参考,具体如下: 介绍: 1.TextSwitcher是ViewSwicher的一个子类,继承了ViewSwicher的所有方法 2.与ViewSwitcher的另一个子类类似,TextSwitcher也有 3.ImageSwitcher不同的是:TextSwitcher的ViewFactory方法的 makeVieW() 必须放回一个TextXiew组件. 具体效果: 放射思维: 如果将其和轮播图(h

  • Android使用Service实现IPC通信的2种方式

    借助AIDL实现IPC通信 一.代码实操---与远端进程的Service绑定 上面的代码都是在当前进程内跟Service通信,现在我们来实现一下,不同进程内Service如何绑定. AIDL:Android Interface Definition Language,即Android接口定义语言. Service跨进程传递数据需要借助aidl,主要步骤是这样的: 编写aidl文件,AS自动生成的java类实现IPC通信的代理 继承自己的aidl类,实现里面的方法 在onBind()中返回我们的实

  • Android开发实现的文本折叠点击展开功能示例

    本文实例讲述了Android开发实现的文本折叠点击展开功能.分享给大家供大家参考,具体如下: 信息栏,景点介绍,购物信息,进场会使用到文本折叠的方法 实现非常简单,这里就不哆嗦了 效果如下: Demo:https://github.com/LonglyWolf/NavigationSystemHLJU 这里用到了三方类库,在app/gradle添加依赖如下: //文本过长 点击展开全部 implementation 'com.ms-square:expandableTextView:0.1.4'

  • Android开发之计算器GridLayout布局实现方法示例

    本文实例讲述了Android开发之计算器GridLayout布局实现方法.分享给大家供大家参考,具体如下: 运行效果: Demo 下载地址:https://github.com/LonglyWolf/Calculator 或者点击此处本站下载. 按钮布局实现: 一个Linearlayout 嵌套三个TextView 最下方的显示当前计算式.上面为先前的计算式. Gridview 网格布局排布按钮 <?xml version="1.0" encoding="utf-8&q

  • Android开发之图片压缩实现方法分析

    本文实例讲述了Android开发之图片压缩实现方法.分享给大家供大家参考,具体如下: 由于Android本身的机制限定 由于系统对每个应用内存分配规则的限制,如果加载过大图片很有可能会导致OOM 即闪退或者卡屏现象 但是手机上拇指大小的图片,超清是完全没有必要的 这是我们就需要对 对片进行压缩处理: 大多数人采用先生成bitmap对象,反复压缩bitmap至100k一下的方法,对图片进行反复压缩,但如果是超级大图,bitmap生成本身就已经会导致OOM,所以我们应先对bitmap进行设置: pu

  • Android开发使用ProgressBar实现进度条功能示例

    本文实例讲述了Android开发使用ProgressBar实现进度条功能.分享给大家供大家参考,具体如下: 进度条ProgressBar的使用主要有两种方向; 1.使用官方默认样式 2.使用自定义样式 先看效果: 详细代码实现文末给出 关于系统自带样式: 在 style="@android:style 中有许多系统自带样式,大家可以更具自身喜好选择. 如果不选择 style 系统会默认使用上图中红色的样式. 关于自定义样式: 这里我们最好看看源码 很容易理解 主要分为三个部分:当前进度.缓冲进度

  • Android开发之SeekBar基本使用及各种美观样式示例

    本文实例讲述了Android开发之SeekBar基本使用及各种美观样式.分享给大家供大家参考,具体如下: 改变控件透明度只需通过 .setAlpha()方法实现 有多种改变思路: 1.改变图片透明度 2.改变背景透明度地点 setBackground() 等等 这里举个例子: 思路拓展:只要将透明度的动态修改跟手势向结合 就能实现toolbar等洞见在拖动是隐藏 以下是更SeekBar相结合的实现代码 seekbar的position属性设置在 0~255 之间 正好与0~255 的透明度相对应

  • android和服务器的URLEncodedUtils乱码编码问题的解决方案

    在android开发中我们常常遇到与到乱码问题,遇到乱码问题首先我们要先检查两端编码格式是否一致! 一般我们提交数据用get 和post方法,这两种方法在上传中有con.setRequestProperty("Charset", "UTF-8"); 和httppost.setEntity(new UrlEncodedFormEntity(数据,"UTF-8"));这两中方式来确定编码方式服务器端有request.setCharacterEncod

  • Android开发之ImageSwitcher相册功能实例分析

    本文实例讲述了Android开发之ImageSwitcher相册功能.分享给大家供大家参考,具体如下: 简介: 1.ImageSwitcher是viewSwitcher的子类,所以ImageSwitcher继承了ViewSwitcher素有的特性 2.作为ViewSwitcher的子类,它比ViewSwitcher使用更加方便,主要体现在:①. 重写了setNext() ②. 重写了showPrevious()方法.所以其实用起来,要比ViewSwitcher更为方便. 3.中重要的是:Imag

  • Android开发之自定义星星评分控件RatingBar用法示例

    本文实例讲述了Android开发之自定义星星评分控件RatingBar用法.分享给大家供大家参考,具体如下: 星级评分条RatingBar类似于SeekBar.ProgressBar'等等都可以自定义样式 它的主要用途就比如淘宝.景点 满意度等 这里给出两种自定义效果 如图所示 第一种是通过RatingBar获得分数 第二个是通过RatingBar动态调节控件属性(透明度) 由于RatngBar使用简单 自定义样式方法和 https://www.jb51.net/article/158338.h

随机推荐