package com.sage42.android.view.ui;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.animation.LinearInterpolator;
import android.widget.ProgressBar;
import com.sage42.android.view.R;
/**
* Copyright (C) 2013- Sage 42 App Sdn Bhd
*
* 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.
*
* @author Corey Scott (corey.scott@sage42.com)
*
*/
/**
* Draw a ProgressBar but instead of being solid make it "segmented". This class also supports adding a "gradient" to
* the colors.
*/
public class SegmentedProgressBar extends ProgressBar
{
private static final int DEFAULT_SEGMENT_COUNT = 40;
// start of the color gradient (defaults to black)
private final int mColorStartA;
private final int mColorStartR;
private final int mColorStartG;
private final int mColorStartB;
// end of the color gradient (defaults to startColor)
private final int mColorEndA;
private final int mColorEndR;
private final int mColorEndG;
private final int mColorEndB;
// unfilled color gradient (defaults to gray)
private final int mColorUnfilled;
// interpolator used to calculate the color gradient (defaults to linear)
private int mGradientInterpolatorResId;
// number of visible segments to draw (default: 40)
private int mSegmentCount;
// paint used for drawing segments
private Paint mPaintSegment;
/**
* Default constructor.
*
* @param context
* @param attrs
*/
public SegmentedProgressBar(final Context context, final AttributeSet attrs)
{
this(context, attrs, -1);
}
/**
* Default constructor.
*
* @param context
* @param attrs
* @param defStyle
*/
public SegmentedProgressBar(final Context context, final AttributeSet attrs, final int defStyle)
{
super(context, attrs, defStyle);
// extract params (if provided)
final TypedArray args = context.obtainStyledAttributes(attrs, R.styleable.segmentedProgressBar);
try
{
// colors
final int startColor = args.getColor(R.styleable.segmentedProgressBar_startColor, R.color.black);
int endColor = args.getColor(R.styleable.segmentedProgressBar_endColor, -1);
if (endColor == -1)
{
endColor = startColor;
}
final int unfilledColor = args.getColor(R.styleable.segmentedProgressBar_unfilledColor, R.color.gray);
// interpolator
this.mGradientInterpolatorResId = args.getResourceId(R.styleable.segmentedProgressBar_android_interpolator,
-1);
if (this.mGradientInterpolatorResId != -1)
{
this.setInterpolator(context, this.mGradientInterpolatorResId);
}
else
{
this.setInterpolator(new LinearInterpolator());
}
// other settings
this.mSegmentCount = args.getInt(R.styleable.segmentedProgressBar_segmentCount,
SegmentedProgressBar.DEFAULT_SEGMENT_COUNT);
// create colors based on supplied args
this.mColorStartA = Color.alpha(startColor);
this.mColorStartR = Color.red(startColor);
this.mColorStartG = Color.green(startColor);
this.mColorStartB = Color.blue(startColor);
this.mColorEndA = Color.alpha(endColor);
this.mColorEndR = Color.red(endColor);
this.mColorEndG = Color.green(endColor);
this.mColorEndB = Color.blue(endColor);
this.mColorUnfilled = Color.argb(Color.alpha(unfilledColor), Color.red(unfilledColor),
Color.blue(unfilledColor), Color.green(unfilledColor));
// init paints
this.mPaintSegment = new Paint();
this.mPaintSegment.setColor(startColor);
this.mPaintSegment.setStyle(Style.FILL);
this.mPaintSegment.setAntiAlias(true);
}
finally
{
args.recycle();
}
}
@Override
protected synchronized void onDraw(final Canvas canvas)
{
// retrieve the overall dimensions
final int totalWidth = this.getWidth();
final int segmentHeight = this.getHeight();
final int top = this.getTop();
// calculate the size of a "segment"
// NOTE: there is no "invisible segment drawn after the last, hence the -1
final int totalSegments = (this.mSegmentCount * 2) - 1;
final double segmentWidth = totalWidth / (double) totalSegments;
// calculate how much of the bar to fill
final double progressPercentage = this.getProgress() / (double) this.getMax();
// draw segments
for (int currentSegment = 0; currentSegment < this.mSegmentCount; currentSegment++)
{
// calculate lateral position
final double left = currentSegment * segmentWidth * 2;
// get color for this segment
final double position = currentSegment / (double) this.mSegmentCount;
if (position < progressPercentage)
{
this.mPaintSegment.setColor(this.getColor(currentSegment));
}
else
{
this.mPaintSegment.setColor(this.mColorUnfilled);
}
// draw segment
canvas.drawRect(Double.valueOf(left).floatValue(), Double.valueOf(top).floatValue(),
Double.valueOf(left + segmentWidth).floatValue(), Double.valueOf(top + segmentHeight)
.floatValue(), this.mPaintSegment);
}
}
private int getColor(final int currentSegment)
{
final float percentage = this.getInterpolator().getInterpolation((float) currentSegment / this.mSegmentCount);
final float alpha = ((this.mColorEndA - this.mColorStartA) * percentage) + this.mColorStartA;
final float red = ((this.mColorEndR - this.mColorStartR) * percentage) + this.mColorStartR;
final float green = ((this.mColorEndG - this.mColorStartG) * percentage) + this.mColorStartG;
final float blue = ((this.mColorEndB - this.mColorStartB) * percentage) + this.mColorStartB;
return Color.argb((int) alpha, (int) red, (int) green, (int) blue);
}
}