Add ProgressWheel
This commit is contained in:
parent
2dd0f1bf99
commit
0161402ab4
213
src/com/todddavies/components/progressbar/ProgressWheel.java
Normal file
213
src/com/todddavies/components/progressbar/ProgressWheel.java
Normal file
@ -0,0 +1,213 @@
|
||||
package com.todddavies.components.progressbar;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.View;
|
||||
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
//Colors (with defaults)
|
||||
private final int barColor = 0xFF33b5e5;
|
||||
private final int rimColor = 0x4433b5e5;
|
||||
|
||||
//Paints
|
||||
private final Paint barPaint, rimPaint, circlePaint;
|
||||
|
||||
//Rectangles
|
||||
private RectF circleBounds;
|
||||
|
||||
//Animation
|
||||
//The amount of pixels to move the bar by on each draw
|
||||
private final int spinSpeed = 2;
|
||||
|
||||
//Sizes
|
||||
private final int fullRadius, barLength, barWidth, rimWidth;
|
||||
|
||||
private int progress;
|
||||
private boolean isSpinning;
|
||||
|
||||
public ProgressWheel(Context context) {
|
||||
super(context);
|
||||
final DisplayMetrics dm = context.getResources().getDisplayMetrics();
|
||||
fullRadius = Math.round(50 * dm.density);
|
||||
barLength = Math.round(25 * dm.density);
|
||||
barWidth = Math.round(5 * dm.density);
|
||||
rimWidth = Math.round(3 * dm.density);
|
||||
|
||||
progress = 0;
|
||||
isSpinning = false;
|
||||
|
||||
barPaint = new Paint();
|
||||
rimPaint = new Paint();
|
||||
circlePaint = new Paint();
|
||||
circleBounds = new RectF();
|
||||
}
|
||||
|
||||
/*
|
||||
* 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’t 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’t 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’t
|
||||
// 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);
|
||||
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(0x44FFFFFF);
|
||||
circlePaint.setStyle(Style.FILL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bounds of the component
|
||||
*/
|
||||
private void setupBounds() {
|
||||
final int centerX = getWidth() / 2;
|
||||
final int centerY = getHeight() / 2;
|
||||
circleBounds = new RectF(centerX - fullRadius, centerY - fullRadius,
|
||||
centerX + fullRadius, centerY + fullRadius);
|
||||
}
|
||||
|
||||
//----------------------------------
|
||||
//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);
|
||||
//Draw the bar
|
||||
if (isSpinning) {
|
||||
canvas.drawArc(circleBounds, progress - 90, barLength, false,
|
||||
barPaint);
|
||||
} else {
|
||||
canvas.drawArc(circleBounds, -90, progress, false, barPaint);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the progress to a specific value
|
||||
*/
|
||||
public void setProgress(int i) {
|
||||
isSpinning = false;
|
||||
progress = i;
|
||||
spinHandler.sendEmptyMessage(0);
|
||||
}
|
||||
|
||||
private final 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.sendEmptyMessage(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user