Android自定义Material进度条效果

首先看下效果图

布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="#ffffff"
  android:gravity="center"
  android:orientation="vertical"
  android:paddingBottom="@dimen/activity_vertical_margin"
  android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin" > 

  <com.example.mytest.view.CircleProgressBar
    android:id="@+id/progress1"
    android:layout_width="60dp"
    android:layout_height="60dp"
    app:mlpb_progress_color="#566da9"
    app:mlpb_progress_stoke_width="3dp" /> 

</LinearLayout>

声明属性

<declare-styleable name="CircleProgressBar">
    <attr name="mlpb_inner_radius" format="dimension"/>
    <attr name="mlpb_background_color" format="color"/>
    <attr name="mlpb_progress_color" format="color"/>
    <attr name="mlpb_progress_stoke_width" format="dimension"/>
    <attr name="mlpb_show_arrow" format="boolean"/>
    <attr name="mlpb_enable_circle_background" format="boolean"/>
    <attr name="mlpb_arrow_width" format="dimension"/>
    <attr name="mlpb_arrow_height" format="dimension"/> 

    <attr name="mlpb_progress" format="integer"/>
    <attr name="mlpb_max" format="integer"/> 

    <attr name="mlpb_progress_text_size" format="dimension"/>
    <attr name="mlpb_progress_text_color" format="color"/> 

    <!--<attr name="mlpb_progress_text_offset" format="dimension"/>--> 

    <attr name="mlpb_progress_text_visibility" format="enum">
      <enum name="visible" value="0"/>
      <enum name="invisible" value="1"/>
    </attr>
  </declare-styleable> 

自定义控件:

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 

package com.example.mytest.view; 

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.net.Uri;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.animation.Animation;
import android.widget.ImageView; 

import com.example.mytest.R; 

/**
 * Private class created to work around issues with AnimationListeners being
 * called before the animation is actually complete and support shadows on older
 * platforms.
 */
public class CircleProgressBar extends ImageView { 

  private static final int KEY_SHADOW_COLOR = 0x1E000000;
  private static final int FILL_SHADOW_COLOR = 0x3D000000;
  // PX
  private static final float X_OFFSET = 0f;
  private static final float Y_OFFSET = 1.75f;
  private static final float SHADOW_RADIUS = 3.5f;
  private static final int SHADOW_ELEVATION = 4; 

  private static final int DEFAULT_CIRCLE_BG_LIGHT = 0xFFFAFAFA;
  private static final int DEFAULT_CIRCLE_DIAMETER = 56;
  private static final int STROKE_WIDTH_LARGE = 3;
  public static final int DEFAULT_TEXT_SIZE = 9; 

  private Animation.AnimationListener mListener;
  private int mShadowRadius;
  private int mBackGroundColor;
  private int mProgressColor;
  private int mProgressStokeWidth;
  private int mArrowWidth;
  private int mArrowHeight;
  private int mProgress;
  private int mMax;
  private int mDiameter;
  private int mInnerRadius;
  private Paint mTextPaint;
  private int mTextColor;
  private int mTextSize;
  private boolean mIfDrawText;
  private boolean mShowArrow;
  private MaterialProgressDrawable mProgressDrawable;
  private ShapeDrawable mBgCircle;
  private boolean mCircleBackgroundEnabled;
  private int[] mColors = new int[]{Color.BLACK}; 

  public CircleProgressBar(Context context) {
    super(context);
    init(context, null, 0); 

  } 

  public CircleProgressBar(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context, attrs, 0); 

  } 

  public CircleProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context, attrs, defStyleAttr);
  } 

  private void init(Context context, AttributeSet attrs, int defStyleAttr) {
    final TypedArray a = context.obtainStyledAttributes(
        attrs, R.styleable.CircleProgressBar, defStyleAttr, 0);
//    <attr name="mlpb_inner_radius" format="dimension"/>
//    <attr name="mlpb_background_color" format="color"/>
//    <attr name="mlpb_progress_color" format="color"/>
//    <attr name="mlpb_progress_stoke_width" format="dimension"/>
//    <attr name="mlpb_arrow_width" format="dimension"/>
//    <attr name="mlpb_arrow_height" format="dimension"/>
//
//    <attr name="mlpb_progress" format="integer"/>
//    <attr name="mlpb_max" format="integer"/>
//
//
//    <attr name="mlpb_progress_text_size" format="dimension"/>
//    <attr name="mlpb_progress_text_color" format="color"/>
//
//    <attr name="mlpb_progress_text_offset" format="dimension"/>
//
//    <attr name="mlpb_progress_text_visibility" format="enum">
//    <enum name="visible" value="0"/>
//    <enum name="invisible" value="1"/>
//    </attr>
    final float density = getContext().getResources().getDisplayMetrics().density; 

    mBackGroundColor = a.getColor(
        R.styleable.CircleProgressBar_mlpb_background_color, DEFAULT_CIRCLE_BG_LIGHT); 

    mProgressColor = a.getColor(
        R.styleable.CircleProgressBar_mlpb_progress_color, DEFAULT_CIRCLE_BG_LIGHT);
    mColors = new int[]{mProgressColor}; 

    mInnerRadius = a.getDimensionPixelOffset(
        R.styleable.CircleProgressBar_mlpb_inner_radius, -1); 

    mProgressStokeWidth = a.getDimensionPixelOffset(
        R.styleable.CircleProgressBar_mlpb_progress_stoke_width, (int) (STROKE_WIDTH_LARGE * density));
    mArrowWidth = a.getDimensionPixelOffset(
        R.styleable.CircleProgressBar_mlpb_arrow_width, -1);
    mArrowHeight = a.getDimensionPixelOffset(
        R.styleable.CircleProgressBar_mlpb_arrow_height, -1);
    mTextSize = a.getDimensionPixelOffset(
        R.styleable.CircleProgressBar_mlpb_progress_text_size, (int) (DEFAULT_TEXT_SIZE * density));
    mTextColor = a.getColor(
        R.styleable.CircleProgressBar_mlpb_progress_text_color, Color.BLACK); 

    mShowArrow = a.getBoolean(R.styleable.CircleProgressBar_mlpb_show_arrow, false);
    mCircleBackgroundEnabled = a.getBoolean(R.styleable.CircleProgressBar_mlpb_enable_circle_background, true); 

    mProgress = a.getInt(R.styleable.CircleProgressBar_mlpb_progress, 0);
    mMax = a.getInt(R.styleable.CircleProgressBar_mlpb_max, 100);
    int textVisible = a.getInt(R.styleable.CircleProgressBar_mlpb_progress_text_visibility, 1);
    if (textVisible != 1) {
      mIfDrawText = true;
    } 

    mTextPaint = new Paint();
    mTextPaint.setStyle(Paint.Style.FILL);
    mTextPaint.setColor(mTextColor);
    mTextPaint.setTextSize(mTextSize);
    mTextPaint.setAntiAlias(true);
    a.recycle();
    mProgressDrawable = new MaterialProgressDrawable(getContext(), this);
    super.setImageDrawable(mProgressDrawable);
  } 

  private boolean elevationSupported() {
    return android.os.Build.VERSION.SDK_INT >= 21;
  } 

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    if (!elevationSupported()) {
      setMeasuredDimension(getMeasuredWidth() + mShadowRadius * 2, getMeasuredHeight()
          + mShadowRadius * 2);
    }
  } 

  @Override
  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    final float density = getContext().getResources().getDisplayMetrics().density;
    mDiameter = Math.min(getMeasuredWidth(), getMeasuredHeight());
    if (mDiameter <= 0) {
      mDiameter = (int) density * DEFAULT_CIRCLE_DIAMETER;
    }
    if (getBackground() == null && mCircleBackgroundEnabled) {
      final int shadowYOffset = (int) (density * Y_OFFSET);
      final int shadowXOffset = (int) (density * X_OFFSET);
      mShadowRadius = (int) (density * SHADOW_RADIUS); 

      if (elevationSupported()) {
        mBgCircle = new ShapeDrawable(new OvalShape());
        ViewCompat.setElevation(this, SHADOW_ELEVATION * density);
      } else {
        OvalShape oval = new OvalShadow(mShadowRadius, mDiameter - mShadowRadius * 2);
        mBgCircle = new ShapeDrawable(oval);
        ViewCompat.setLayerType(this, ViewCompat.LAYER_TYPE_SOFTWARE, mBgCircle.getPaint());
        mBgCircle.getPaint().setShadowLayer(mShadowRadius, shadowXOffset, shadowYOffset,
            KEY_SHADOW_COLOR);
        final int padding = (int) mShadowRadius;
        // set padding so the inner image sits correctly within the shadow.
        setPadding(padding, padding, padding, padding);
      }
      mBgCircle.getPaint().setColor(mBackGroundColor);
      setBackgroundDrawable(mBgCircle);
    }
    mProgressDrawable.setBackgroundColor(mBackGroundColor);
    mProgressDrawable.setColorSchemeColors(mColors);
    mProgressDrawable.setSizeParameters(mDiameter, mDiameter,
        mInnerRadius <= 0 ? (mDiameter - mProgressStokeWidth * 2) / 4 : mInnerRadius,
        mProgressStokeWidth,
        mArrowWidth < 0 ? mProgressStokeWidth * 4 : mArrowWidth,
        mArrowHeight < 0 ? mProgressStokeWidth * 2 : mArrowHeight);
    if (isShowArrow()) {
      mProgressDrawable.showArrowOnFirstStart(true);
      mProgressDrawable.setArrowScale(1f);
      mProgressDrawable.showArrow(true);
    }
    super.setImageDrawable(null);
    super.setImageDrawable(mProgressDrawable);
    mProgressDrawable.setAlpha(255);
    if(getVisibility()==VISIBLE) {
      mProgressDrawable.start();
    }
  } 

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (mIfDrawText) {
      String text = String.format("%s%%", mProgress);
      int x = getWidth() / 2 - text.length() * mTextSize / 4;
      int y = getHeight() / 2 + mTextSize / 4;
      canvas.drawText(text, x, y, mTextPaint);
    }
  } 

  @Override
  final public void setImageResource(int resId) { 

  } 

  public boolean isShowArrow() {
    return mShowArrow;
  } 

  public void setShowArrow(boolean showArrow) {
    this.mShowArrow = showArrow;
  } 

  @Override
  final public void setImageURI(Uri uri) {
    super.setImageURI(uri);
  } 

  @Override
  final public void setImageDrawable(Drawable drawable) {
  } 

  public void setAnimationListener(Animation.AnimationListener listener) {
    mListener = listener;
  } 

  @Override
  public void onAnimationStart() {
    super.onAnimationStart();
    if (mListener != null) {
      mListener.onAnimationStart(getAnimation());
    }
  } 

  @Override
  public void onAnimationEnd() {
    super.onAnimationEnd();
    if (mListener != null) {
      mListener.onAnimationEnd(getAnimation());
    }
  } 

  /**
   * Set the color resources used in the progress animation from color resources.
   * The first color will also be the color of the bar that grows in response
   * to a user swipe gesture.
   *
   * @param colorResIds
   */
  public void setColorSchemeResources(int... colorResIds) {
    final Resources res = getResources();
    int[] colorRes = new int[colorResIds.length];
    for (int i = 0; i < colorResIds.length; i++) {
      colorRes[i] = res.getColor(colorResIds[i]);
    }
    setColorSchemeColors(colorRes);
  } 

  /**
   * Set the colors used in the progress animation. The first
   * color will also be the color of the bar that grows in response to a user
   * swipe gesture.
   *
   * @param colors
   */
  public void setColorSchemeColors(int... colors) {
    mColors = colors;
    if (mProgressDrawable != null) {
      mProgressDrawable.setColorSchemeColors(colors);
    }
  } 

  /**
   * Update the background color of the mBgCircle image view.
   */
  public void setBackgroundColor(int colorRes) {
    if (getBackground() instanceof ShapeDrawable) {
      final Resources res = getResources();
      ((ShapeDrawable) getBackground()).getPaint().setColor(res.getColor(colorRes));
    }
  } 

  public boolean isShowProgressText() {
    return mIfDrawText;
  } 

  public void setShowProgressText(boolean mIfDrawText) {
    this.mIfDrawText = mIfDrawText;
  } 

  public int getMax() {
    return mMax;
  } 

  public void setMax(int max) {
    mMax = max;
  } 

  public int getProgress() {
    return mProgress;
  } 

  public void setProgress(int progress) {
    if (getMax() > 0) {
      mProgress = progress;
    }
  } 

  public boolean circleBackgroundEnabled() {
    return mCircleBackgroundEnabled;
  } 

  public void setCircleBackgroundEnabled(boolean enableCircleBackground) {
    this.mCircleBackgroundEnabled = enableCircleBackground;
  } 

  @Override
  public int getVisibility() {
    return super.getVisibility();
  } 

  @Override
  public void setVisibility(int visibility) {
    super.setVisibility(visibility);
    if (mProgressDrawable != null) {
      mProgressDrawable.setVisible(visibility == VISIBLE, false);
      if (visibility != VISIBLE) {
        mProgressDrawable.stop();
      } else {
        if (mProgressDrawable.isRunning()) {
          mProgressDrawable.stop();
        }
        mProgressDrawable.start();
      }
    }
  } 

  @Override
  protected void onAttachedToWindow() {
    super.onAttachedToWindow();
    if (mProgressDrawable != null) {
      mProgressDrawable.stop();
      mProgressDrawable.setVisible(getVisibility() == VISIBLE, false); 

      requestLayout();
    }
  } 

  @Override
  protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    if (mProgressDrawable != null) {
      mProgressDrawable.stop();
      mProgressDrawable.setVisible(false, false);
    }
  } 

  private class OvalShadow extends OvalShape {
    private RadialGradient mRadialGradient;
    private int mShadowRadius;
    private Paint mShadowPaint;
    private int mCircleDiameter; 

    public OvalShadow(int shadowRadius, int circleDiameter) {
      super();
      mShadowPaint = new Paint();
      mShadowRadius = shadowRadius;
      mCircleDiameter = circleDiameter;
      mRadialGradient = new RadialGradient(mCircleDiameter / 2, mCircleDiameter / 2,
          mShadowRadius, new int[]{
          FILL_SHADOW_COLOR, Color.TRANSPARENT
      }, null, Shader.TileMode.CLAMP);
      mShadowPaint.setShader(mRadialGradient);
    } 

    @Override
    public void draw(Canvas canvas, Paint paint) {
      final int viewWidth = CircleProgressBar.this.getWidth();
      final int viewHeight = CircleProgressBar.this.getHeight();
      canvas.drawCircle(viewWidth / 2, viewHeight / 2, (mCircleDiameter / 2 + mShadowRadius),
          mShadowPaint);
      canvas.drawCircle(viewWidth / 2, viewHeight / 2, (mCircleDiameter / 2), paint);
    }
  }
} 

在java代码中设置进度条上的颜色值

progress1 = (CircleProgressBar) findViewById(R.id.progress1);
progress1.setColorSchemeResources(android.R.color.holo_green_light,android.R.color.holo_orange_light,android.R.color.holo_red_light);

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

(0)

相关推荐

  • Android实现环形进度条的实例

    Android实现环形进度条的效果图如下: 自定义控件:AttendanceProgressBar 代码如下: public class AttendanceProgressBar extends View { // 画圆环底部的画笔 private Paint mCirclePaint; // 画圆环的画笔 private Paint mRingPaint; // 画字体的画笔 private Paint mTextPaint; // 圆形颜色 private int mCircleColor

  • Android自定义view实现进度条指示效果

    先看看效果图: 首先是布局文件 <FrameLayout android:layout_width="match_parent" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_height="wrap_content"> <ProgressBar android:id="@+id/p

  • Android实现带数字的圆形进度条(自定义进度条)

    开发 设计搞了一个带圆形进度的进度条,在GitHub上逛了一圈,发现没有,自己撸吧. 先看界面效果: 主要思路是写一个继承ProgressBar的自定义View,不废话,直接上代码: package com.fun.progressbarwithnumber; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.g

  • Android编程基于自定义View实现绚丽的圆形进度条功能示例

    本文实例讲述了Android编程基于自定义View实现绚丽的圆形进度条功能.分享给大家供大家参考,具体如下: 本文包含两个组件,首先上效果图: 1.ProgressBarView1(支持拖动): 2.ProgressBarView2(不同进度值显示不同颜色,不支持拖拽):   代码不多,注释也比较详细,全部贴上了: (一)ProgressBarView1: /** * 自定义绚丽的ProgressBar. */ public class ProgressBarView1 extends View

  • Android带圆形数字进度的自定义进度条示例

    开发 设计搞了一个带圆形进度的进度条,在GitHub上逛了一圈,发现没有,自己撸吧. 先看界面效果: 主要思路是写一个继承ProgressBar的自定义View,不废话,直接上代码: package com.fun.progressbarwithnumber; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.g

  • Android动态自定义圆形进度条

    效果图: A.绘制圆环,圆弧,文本 //1.画圆环 //原点坐标 float circleX = width / 2; float circleY = width / 2; //半径 float radius = width / 2 - roundWidth / 2; //设置画笔的属性 paint.setColor(roundColor); paint.setStrokeWidth(roundWidth); paint.setStyle(Paint.Style.STROKE); canvas.

  • Android自定义控件实现圆形进度条

    项目中常用到的圆形进度条有好多个,从网上搜到的自定义进度条多是封装的比较好的代码,但是不利于初学者,现在本博客就教给大家如何一步步实现自定义进度条的效果 相关视频链接: http://edu.csdn.net/course/detail/3719/65396 先看效果如图- 代码实现过程–main布局 这个布局中就是一个简单的引用 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xm

  • Android编程之ProgressBar圆形进度条颜色设置方法

    本文实例讲述了Android ProgressBar圆形进度条颜色设置方法.分享给大家供大家参考,具体如下: 你是不是还在为设置进度条的颜色而烦恼呢--别着急,且看如下如何解决. ProgressBar分圆形进度条和水平进度条 我这里就分享下如何设置圆形进度条的颜色吧,希望对大家会有帮助. 源码如下: 布局文件代码: <ProgressBar android:id="@+id/progressbar" android:layout_width="wrap_content

  • Android编程实现WebView添加进度条的方法

    本文实例讲述了Android编程实现WebView添加进度条的方法.分享给大家供大家参考,具体如下: 标准的XML界面 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"

  • android自定义view制作圆形进度条效果

    还是我们自定View的那几个步骤: 1.自定义View的属性 2.在View的构造方法中获得我们自定义的属性 [ 3.重写onMesure ] 4.重写onDraw 1.自定义属性: <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="CustomTitleView"> <attr name="m

  • Android编程实现类似于圆形ProgressBar的进度条效果

    本文实例讲述了Android编程实现类似于圆形ProgressBar的进度条效果.分享给大家供大家参考,具体如下: 我们要实现一个类似于小米分享中的圆形播放进度条,android自带的圆形ProgressBar是默认自动旋转的,所以无法实现,于是我们想到了使用自定义一个View,来实现这种效果. 首先来看看自己定义的View package cn.easymobi.application.bell.common; import android.content.Context; import an

随机推荐