【安卓笔记】扁平化的ProgressBar-----ProgressWheel

ProgressWheel是github上一个开源的项目,为开发者提供一个扁平化的ProgressBar,并可以对其进行深度定制。效果如下:

下面介绍使用方式:

1.下面是ProgressWheel源码,拷到项目下。

package com.example.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;
import com.example.progresswheeldemo.R;
/**
 * An indicator of progress, similar to Android's ProgressBar. Can be used in
 * 'spin mode' or 'increment mode'
 *
 * @author Todd Davies
 *         <p/>
 *         Licensed under the Creative Commons Attribution 3.0 license see:
 *         http://creativecommons.org/licenses/by/3.0/
 */
public class ProgressWheel extends View
{
	// Sizes (with defaults)
	private int layout_height = 0;
	private int layout_width = 0;
	private int fullRadius = 100;
	private int circleRadius = 80;
	private int barLength = 60;
	private int barWidth = 20;
	private int rimWidth = 20;
	private int textSize = 20;
	private float contourSize = 0;
	// Padding (with defaults)
	private int paddingTop = 5;
	private int paddingBottom = 5;
	private int paddingLeft = 5;
	private int paddingRight = 5;
	// Colors (with defaults)
	private int barColor = 0xAA000000;
	private int contourColor = 0xAA000000;
	private int circleColor = 0x00000000;
	private int rimColor = 0xAADDDDDD;
	private int textColor = 0xFF000000;
	// Paints
	private Paint barPaint = new Paint();
	private Paint circlePaint = new Paint();
	private Paint rimPaint = new Paint();
	private Paint textPaint = new Paint();
	private Paint contourPaint = new Paint();
	// Rectangles
	@SuppressWarnings("unused")
	private RectF rectBounds = new RectF();
	private RectF circleBounds = new RectF();
	private RectF circleOuterContour = new RectF();
	private RectF circleInnerContour = new RectF();
	// Animation
	// The amount of pixels to move the bar by on each draw
	private int spinSpeed = 2;
	// The number of milliseconds to wait inbetween each draw
	private int delayMillis = 0;
	private Handler spinHandler = new Handler()
	{
		/**
		 * This is the code that will increment the progress variable and so
		 * spin the wheel
		 */
		@Override
		public void handleMessage(Message msg)
		{
			invalidate();
			if (isSpinning)
			{
				progress += spinSpeed;
				if (progress > 360)
				{
					progress = 0;
				}
				spinHandler.sendEmptyMessageDelayed(0, delayMillis);
			}
			// super.handleMessage(msg);
		}
	};
	int progress = 0;
	boolean isSpinning = false;
	// Other
	private String text = "";
	private String[] splitText =
	{};
	/**
	 * The constructor for the ProgressWheel
	 *
	 * @param context
	 * @param attrs
	 */
	public ProgressWheel(Context context, AttributeSet attrs)
	{
		super(context, attrs);
		parseAttributes(context.obtainStyledAttributes(attrs,
				R.styleable.ProgressWheel));
	}
	// ----------------------------------
	// Setting up stuff
	// ----------------------------------
	/*
	 * When this is called, make the view square. From:
	 * http://www.jayway.com/2012
	 * /12/12/creating-custom-android-views-part-4-measuring
	 * -and-how-to-force-a-view-to-be-square/
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
	{
		// The first thing that happen is that we call the superclass
		// implementation of onMeasure. The reason for that is that measuring
		// can be quite a complex process and calling the super method is a
		// convenient way to get most of this complexity handled.
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// We can鈥檛 use getWidth() or getHight() here. During the measuring
		// pass the view has not gotten its final size yet (this happens first
		// at the start of the layout pass) so we have to use getMeasuredWidth()
		// and getMeasuredHeight().
		int size = 0;
		int width = getMeasuredWidth();
		int height = getMeasuredHeight();
		int widthWithoutPadding = width - getPaddingLeft() - getPaddingRight();
		int heigthWithoutPadding = height - getPaddingTop()
				- getPaddingBottom();
		// Finally we have some simple logic that calculates the size of the
		// view
		// and calls setMeasuredDimension() to set that size.
		// Before we compare the width and height of the view, we remove the
		// padding,
		// and when we set the dimension we add it back again. Now the actual
		// content
		// of the view will be square, but, depending on the padding, the total
		// dimensions
		// of the view might not be.
		if (widthWithoutPadding > heigthWithoutPadding)
		{
			size = heigthWithoutPadding;
		} else
		{
			size = widthWithoutPadding;
		}
		// If you override onMeasure() you have to call setMeasuredDimension().
		// This is how you report back the measured size. If you don鈥檛 call
		// setMeasuredDimension() the parent will throw an exception and your
		// application will crash.
		// We are calling the onMeasure() method of the superclass so we don鈥檛
		// actually need to call setMeasuredDimension() since that takes care
		// of that. However, the purpose with overriding onMeasure() was to
		// change the default behaviour and to do that we need to call
		// setMeasuredDimension() with our own values.
		setMeasuredDimension(size + getPaddingLeft() + getPaddingRight(), size
				+ getPaddingTop() + getPaddingBottom());
	}
	/**
	 * Use onSizeChanged instead of onAttachedToWindow to get the dimensions of
	 * the view, because this method is called after measuring the dimensions of
	 * MATCH_PARENT & WRAP_CONTENT. Use this dimensions to setup the bounds and
	 * paints.
	 */
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh)
	{
		super.onSizeChanged(w, h, oldw, oldh);
		// Share the dimensions
		layout_width = w;
		layout_height = h;
		setupBounds();
		setupPaints();
		invalidate();
	}
	/**
	 * Set the properties of the paints we're using to draw the progress wheel
	 */
	private void setupPaints()
	{
		barPaint.setColor(barColor);
		barPaint.setAntiAlias(true);
		barPaint.setStyle(Style.STROKE);
		barPaint.setStrokeWidth(barWidth);
		rimPaint.setColor(rimColor);
		rimPaint.setAntiAlias(true);
		rimPaint.setStyle(Style.STROKE);
		rimPaint.setStrokeWidth(rimWidth);
		circlePaint.setColor(circleColor);
		circlePaint.setAntiAlias(true);
		circlePaint.setStyle(Style.FILL);
		textPaint.setColor(textColor);
		textPaint.setStyle(Style.FILL);
		textPaint.setAntiAlias(true);
		textPaint.setTextSize(textSize);
		contourPaint.setColor(contourColor);
		contourPaint.setAntiAlias(true);
		contourPaint.setStyle(Style.STROKE);
		contourPaint.setStrokeWidth(contourSize);
	}
	/**
	 * Set the bounds of the component
	 */
	private void setupBounds()
	{
		// Width should equal to Height, find the min value to steup the circle
		int minValue = Math.min(layout_width, layout_height);
		// Calc the Offset if needed
		int xOffset = layout_width - minValue;
		int yOffset = layout_height - minValue;
		// Add the offset
		paddingTop = this.getPaddingTop() + (yOffset / 2);
		paddingBottom = this.getPaddingBottom() + (yOffset / 2);
		paddingLeft = this.getPaddingLeft() + (xOffset / 2);
		paddingRight = this.getPaddingRight() + (xOffset / 2);
		int width = getWidth(); // this.getLayoutParams().width;
		int height = getHeight(); // this.getLayoutParams().height;
		rectBounds = new RectF(paddingLeft, paddingTop, width - paddingRight,
				height - paddingBottom);
		circleBounds = new RectF(paddingLeft + barWidth, paddingTop + barWidth,
				width - paddingRight - barWidth, height - paddingBottom
						- barWidth);
		circleInnerContour = new RectF(circleBounds.left + (rimWidth / 2.0f)
				+ (contourSize / 2.0f), circleBounds.top + (rimWidth / 2.0f)
				+ (contourSize / 2.0f), circleBounds.right - (rimWidth / 2.0f)
				- (contourSize / 2.0f), circleBounds.bottom - (rimWidth / 2.0f)
				- (contourSize / 2.0f));
		circleOuterContour = new RectF(circleBounds.left - (rimWidth / 2.0f)
				- (contourSize / 2.0f), circleBounds.top - (rimWidth / 2.0f)
				- (contourSize / 2.0f), circleBounds.right + (rimWidth / 2.0f)
				+ (contourSize / 2.0f), circleBounds.bottom + (rimWidth / 2.0f)
				+ (contourSize / 2.0f));
		fullRadius = (width - paddingRight - barWidth) / 2;
		circleRadius = (fullRadius - barWidth) + 1;
	}
	/**
	 * Parse the attributes passed to the view from the XML
	 *
	 * @param a
	 *            the attributes to parse
	 */
	private void parseAttributes(TypedArray a)
	{
		barWidth = (int) a.getDimension(R.styleable.ProgressWheel_barWidth,
				barWidth);
		rimWidth = (int) a.getDimension(R.styleable.ProgressWheel_rimWidth,
				rimWidth);
		spinSpeed = (int) a.getDimension(R.styleable.ProgressWheel_spinSpeed,
				spinSpeed);
		delayMillis = a.getInteger(R.styleable.ProgressWheel_delayMillis,
				delayMillis);
		if (delayMillis < 0)
		{
			delayMillis = 0;
		}
		barColor = a.getColor(R.styleable.ProgressWheel_barColor, barColor);
		barLength = (int) a.getDimension(R.styleable.ProgressWheel_barLength,
				barLength);
		textSize = (int) a.getDimension(R.styleable.ProgressWheel_textSize,
				textSize);
		textColor = (int) a.getColor(R.styleable.ProgressWheel_textColor,
				textColor);
		// if the text is empty , so ignore it
		if (a.hasValue(R.styleable.ProgressWheel_text))
		{
			setText(a.getString(R.styleable.ProgressWheel_text));
		}
		rimColor = (int) a.getColor(R.styleable.ProgressWheel_rimColor,
				rimColor);
		circleColor = (int) a.getColor(R.styleable.ProgressWheel_circleColor,
				circleColor);
		contourColor = a.getColor(R.styleable.ProgressWheel_contourColor,
				contourColor);
		contourSize = a.getDimension(R.styleable.ProgressWheel_contourSize,
				contourSize);
		// Recycle
		a.recycle();
	}
	// ----------------------------------
	// Animation stuff
	// ----------------------------------
	protected void onDraw(Canvas canvas)
	{
		super.onDraw(canvas);
		// Draw the inner circle
		canvas.drawArc(circleBounds, 360, 360, false, circlePaint);
		// Draw the rim
		canvas.drawArc(circleBounds, 360, 360, false, rimPaint);
		canvas.drawArc(circleOuterContour, 360, 360, false, contourPaint);
		canvas.drawArc(circleInnerContour, 360, 360, false, contourPaint);
		// Draw the bar
		if (isSpinning)
		{
			canvas.drawArc(circleBounds, progress - 90, barLength, false,
					barPaint);
		} else
		{
			canvas.drawArc(circleBounds, -90, progress, false, barPaint);
		}
		// Draw the text (attempts to center it horizontally and vertically)
		float textHeight = textPaint.descent() - textPaint.ascent();
		float verticalTextOffset = (textHeight / 2) - textPaint.descent();
		for (String s : splitText)
		{
			float horizontalTextOffset = textPaint.measureText(s) / 2;
			canvas.drawText(s, this.getWidth() / 2 - horizontalTextOffset,
					this.getHeight() / 2 + verticalTextOffset, textPaint);
		}
	}
	/**
	 * Check if the wheel is currently spinning
	 */
	public boolean isSpinning()
	{
		if (isSpinning)
		{
			return true;
		} else
		{
			return false;
		}
	}
	/**
	 * Reset the count (in increment mode)
	 */
	public void resetCount()
	{
		progress = 0;
		setText("0%");
		invalidate();
	}
	/**
	 * Turn off spin mode
	 */
	public void stopSpinning()
	{
		isSpinning = false;
		progress = 0;
		spinHandler.removeMessages(0);
	}
	/**
	 * Puts the view on spin mode
	 */
	public void spin()
	{
		isSpinning = true;
		spinHandler.sendEmptyMessage(0);
	}
	/**
	 * Increment the progress by 1 (of 360)
	 */
	public void incrementProgress()
	{
		isSpinning = false;
		progress += 20;
		if (progress > 360)
			progress = 0;
		// setText(Math.round(((float) progress / 360) * 100) + "%");
		spinHandler.sendEmptyMessage(0);
	}
	/**
	 * Set the progress to a specific value
	 */
	public void setProgress(int i)
	{
		isSpinning = false;
		progress = i;
		spinHandler.sendEmptyMessage(0);
	}
	// ----------------------------------
	// Getters + setters
	// ----------------------------------
	/**
	 * Set the text in the progress bar Doesn't invalidate the view
	 *
	 * @param text
	 *            the text to show ('\n' constitutes a new line)
	 */
	public void setText(String text)
	{
		this.text = text;
		splitText = this.text.split("\n");
	}
	public int getCircleRadius()
	{
		return circleRadius;
	}
	public void setCircleRadius(int circleRadius)
	{
		this.circleRadius = circleRadius;
	}
	public int getBarLength()
	{
		return barLength;
	}
	public void setBarLength(int barLength)
	{
		this.barLength = barLength;
	}
	public int getBarWidth()
	{
		return barWidth;
	}
	public void setBarWidth(int barWidth)
	{
		this.barWidth = barWidth;
	}
	public int getTextSize()
	{
		return textSize;
	}
	public void setTextSize(int textSize)
	{
		this.textSize = textSize;
	}
	public int getPaddingTop()
	{
		return paddingTop;
	}
	public void setPaddingTop(int paddingTop)
	{
		this.paddingTop = paddingTop;
	}
	public int getPaddingBottom()
	{
		return paddingBottom;
	}
	public void setPaddingBottom(int paddingBottom)
	{
		this.paddingBottom = paddingBottom;
	}
	public int getPaddingLeft()
	{
		return paddingLeft;
	}
	public void setPaddingLeft(int paddingLeft)
	{
		this.paddingLeft = paddingLeft;
	}
	public int getPaddingRight()
	{
		return paddingRight;
	}
	public void setPaddingRight(int paddingRight)
	{
		this.paddingRight = paddingRight;
	}
	public int getBarColor()
	{
		return barColor;
	}
	public void setBarColor(int barColor)
	{
		this.barColor = barColor;
	}
	public int getCircleColor()
	{
		return circleColor;
	}
	public void setCircleColor(int circleColor)
	{
		this.circleColor = circleColor;
	}
	public int getRimColor()
	{
		return rimColor;
	}
	public void setRimColor(int rimColor)
	{
		this.rimColor = rimColor;
	}
	public Shader getRimShader()
	{
		return rimPaint.getShader();
	}
	public void setRimShader(Shader shader)
	{
		this.rimPaint.setShader(shader);
	}
	public int getTextColor()
	{
		return textColor;
	}
	public void setTextColor(int textColor)
	{
		this.textColor = textColor;
	}
	public int getSpinSpeed()
	{
		return spinSpeed;
	}
	public void setSpinSpeed(int spinSpeed)
	{
		this.spinSpeed = spinSpeed;
	}
	public int getRimWidth()
	{
		return rimWidth;
	}
	public void setRimWidth(int rimWidth)
	{
		this.rimWidth = rimWidth;
	}
	public int getDelayMillis()
	{
		return delayMillis;
	}
	public void setDelayMillis(int delayMillis)
	{
		this.delayMillis = delayMillis;
	}
}

2.将如下的属性文件拷到attrs.xml中:

<?xml version="1.0" encoding="utf-8"?>
<resources>
	<declare-styleable name="ProgressWheel">
        <attr name="text" format="string" />
        <attr name="textColor" format="color" />
        <attr name="textSize" format="dimension" />
        <attr name="barColor" format="color" /><!-- 进度条颜色 -->
        <attr name="rimColor" format="color" /><!-- 默认轮廓颜色 -->
        <attr name="rimWidth" format="dimension" />
        <attr name="spinSpeed" format="dimension" />
        <attr name="delayMillis" format="integer" />
        <attr name="circleColor" format="color" /><!-- 圆圈内部的颜色 -->
        <attr name="radius" format="dimension" />
        <attr name="barWidth" format="dimension" /><!-- 进度条宽度 -->
        <attr name="barLength" format="dimension" /><!-- 进度条长度(即进度条走过的长度) -->
        <attr name="contourColor" format="color"/><!-- 控制外边缘颜色 -->
        <attr name="contourSize" format="dimension"/>
    </declare-styleable>
</resources>

3.在布局文件中声明控件:

注:首先你得加上命名空间:

xmlns:ProgressWheel="http://schemas.android.com/apk/res/包名"

声明控件:

<com.example.view.ProgressWheel
        android:id="@+id/pw_spinner"
        android:layout_width="180dp"
        android:layout_height="180dp"
        android:layout_centerInParent="true"
        ProgressWheel:barColor="#0097D6"
        ProgressWheel:barLength="160dp"
        ProgressWheel:barWidth="15dp"
        ProgressWheel:rimColor="#330097D6"
        ProgressWheel:rimWidth="15dp"
        ProgressWheel:text="wait..."
        ProgressWheel:contourColor="#330097D6"
        ProgressWheel:textColor="#222"

4.在代码中使用控件:

wheel = (ProgressWheel) findViewById(R.id.pw_spinner);//找到控件
		wheel.setProgress(180);//设置进度
		wheel.incrementProgress();//增加进度
		wheel.spin();//使控件开始旋转
		wheel.stopSpinning();//停止旋转
时间: 2024-10-08 20:31:23

【安卓笔记】扁平化的ProgressBar-----ProgressWheel的相关文章

android扁平化ProgressBar--progressWheel

ProgressWheel是git是一个开源项目,为开发者提供一个扁平化的ProgressBar,并可对其进行深度定制 1,将ProgressWheel的源码拷贝到项目中 public class ProgressWheel extends View { // Sizes (with defaults) private int layout_height = 0; private int layout_width = 0; private int fullRadius = 100; privat

扁平化设计

扁平化概念的核心意义是:去除冗余.厚重和繁杂的装饰效果.而具体表现在去掉了多余的透视.纹理.渐变以及能做出3D效果的元素,这样可以让“信息”本身重新作为核心被凸显出来.同时在设计元素上,则强调了抽象.极简和符号化. 例如:Windows.Mac OS.iOS.Android等操作系统的设计已经往“扁平化设计”发展.其设计语言主要有Material Design.Modern UI等. 扁平化的设计,尤其是手机的系统直接体现在:更少的按钮和选项,这样使得UI界面变得更加干净整齐,使用起来格外简洁,

扁平化网页的设计方法-页面空间的运用

这两年的时间内扁平化网页越来越受到大部分人的喜爱,很多企业也想向这方面发展,在扁平化的设计中有一个重要的项目就是页面上空间的运用,今天我们就给大家讲讲网站设计中扁平化网站的设计技巧.        当一个元素使用不对称的空间,它对周围的其他元素.它会显得更加有活力,如果你设计一个网页,一个链接或按钮的要求比别人更多的关注领域是特别有帮助的. 今天我们要仔细看看不对称表示通过对比,间距和布局.我们观察对比思考,如何关注空间的驱动器. 不对称也可以关注内部关系如图像缩略图或文本对齐.例如,一个图像画

关于扁平化视觉设计趋势的一些小分享

本文来自网易云社区 作者:刘戈 作为视觉设计师来说,能设计出一款赏心悦目.走在设计潮流前线而又有自己品牌设计基因的产品是每个人心目中的追求.如果提到当今移动产品UI设计风格趋势时,相信不少设计师心目中的答案是扁平化设计.无可否认,在2013年扁平化设计风格全面普及以来至今,扁平化依旧是移动产品设计的主流方向,但众多产品使用扁平化设计的同时会使得产品之间的视觉差异越来越小,设计师如何把自己的产品设计做得与众不同,让自己产品于同类竞品中脱颖而出就变得尤为关键,这要求设计师时刻要保持设计上的创新,而创

扁平化设计2.0

时至今日,扁平化已不再是流行一时的设计风潮,而是一种美学风格.扁平化大胆的用色,简洁明快的界面风格一度让大家耳目一新,当它对元素效果抛弃的如此彻底之际,它又将效果捡起来,改装成另一番模样,使得扁平化进化为扁平化2.0. 扁平化设计特质 对于扁平化的定义,依然没有一个固定范式,但概括起来有下面四个特征: 1)没有多余的效果,例如投影.凹凸或渐变等 2)使用简洁风格的元素和图标 3)大胆丰富且明亮的配色风格 4)尽量减少装饰的极简设计 扁平化所追随的细节依然不变,然而这些"规范"开始松懈了

扁平化设计的历史

[摘要]"扁平化设计"是一种设计风格术语,它抛弃任何能使得作品突显3D效果的特性. 如今一提到网站设计,就会不可避免地碰到"扁平化设计"(flat design)这个词.近几年扁平化设计趋势风生水起,也受到很多大公司的青睐. 但扁平化设计来源是哪里?为什么它风靡网站设计?在设计中,我们只有知道一种风格和技术的来源以及它背后的历史,我们在使用这种美学风格时才能更加得心应手.下面让我们追根溯源,了解扁平化设计的前世今生. 究竟什么是扁平化设计 对于没接触过的人来说,&q

1.扁平化

对象 - 对象映射的一个常见用法是获取一个复杂的对象模型,并将其展开成一个更简单的模型. 您可以采取复杂的模型,如: 1 public class Order 2 { 3 private readonly IList<OrderLineItem> _orderLineItems = new List<OrderLineItem>(); 4 5 public Customer Customer { get; set; } 6 7 public OrderLineItem[] GetO

你认为扁平化模式好还是树形结构好?

我认为对于小公司来说,扁平化的模式更好一些.由于小公司的规模比较小,公司内的员工不多,所需要的管理层次不多.扁平化模式的决策层和操作层之间的中间管理层次少,这可以使企业能够快速地将决策权延至企业生产.营销的最前线,从而为提高企业效率.而且由于公司规模小,管理部门之间的信息资源的交流.相互调用不会太多,这样可以是决策者集中更多的精力在企业的市场对策和企业发展的战略问题上. 对于大公司来说,树形结构会更好一些.大公司的规模比较大,所要做的项目比较多,如果一个人负责多个项目会造成项目完成效率不高.在树

怎样做出优秀的扁平化设计风格 PPT 或 Keynote 幻灯片演示文稿?

怎样做出优秀的扁平化设计风格 PPT 或 Keynote 幻灯片演示文稿? http://www.zhihu.com/question/21274267/answer/62857878