blob: cbb581f24cd5d4a44495c69cb99377e79ad1fd7a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.weex.ui.view.refresh.circlebar;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.animation.Animation;
import android.widget.ImageView;
/**
* Modify of android.support.v4
*/
@SuppressLint("AppCompatCustomView")
public class CircleProgressBar extends ImageView {
private static final int KEY_SHADOW_COLOR = 0x1E000000;
private static final int FILL_SHADOW_COLOR = 0x3D000000;
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;
public static final int DEFAULT_CIRCLE_BG_LIGHT = 0xFFFAFAFA;
public static final int DEFAULT_CIRCLE_COLOR = 0xFFF00000;
private static final int DEFAULT_CIRCLE_DIAMETER = 40;
private static final int STROKE_WIDTH_LARGE = 3;
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 boolean mShowArrow;
public 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 float density = getContext().getResources().getDisplayMetrics().density;
mBackGroundColor = DEFAULT_CIRCLE_BG_LIGHT;
mProgressColor = DEFAULT_CIRCLE_COLOR;
mColors = new int[]{mProgressColor};
mInnerRadius = -1;
mProgressStokeWidth = (int) (STROKE_WIDTH_LARGE * density);
mArrowWidth = -1;
mArrowHeight = -1;
mShowArrow = true;
mCircleBackgroundEnabled = true;
mProgress = 0;
mMax = 100;
mProgressDrawable = new MaterialProgressDrawable(getContext(), this);
super.setImageDrawable(mProgressDrawable);
}
public void setProgressBackGroundColor(int color) {
this.mBackGroundColor = color;
}
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);
}
}
public int getProgressStokeWidth() {
return mProgressStokeWidth;
}
public void setProgressStokeWidth(int mProgressStokeWidth) {
final float density = getContext().getResources().getDisplayMetrics().density;
this.mProgressStokeWidth = (int) (mProgressStokeWidth * density);
}
@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()) {
if(mBgCircle == null) {
mBgCircle = new ShapeDrawable(new OvalShape());
}
ViewCompat.setElevation(this, SHADOW_ELEVATION * density);
} else {
if(!(mBgCircle != null &&
mBgCircle.getShape() instanceof OvalShadow &&
((OvalShadow) mBgCircle.getShape()).mCircleDiameter == (mDiameter - mShadowRadius * 2) &&
((OvalShadow) mBgCircle.getShape()).mShadowRadius == mShadowRadius)) {
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);
if (isShowArrow()) {
mProgressDrawable.setArrowScale(1f);
mProgressDrawable.showArrow(true);
}
super.setImageDrawable(null);
super.setImageDrawable(mProgressDrawable);
mProgressDrawable.setAlpha(255);
if (getVisibility() == VISIBLE) {
mProgressDrawable.setStartEndTrim(0, (float) 0.8);
}
}
public boolean isShowArrow() {
return mShowArrow;
}
public void setShowArrow(boolean showArrow) {
this.mShowArrow = showArrow;
}
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 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 setBackgroundColorResource(int colorRes) {
if (getBackground() instanceof ShapeDrawable) {
final Resources res = getResources();
((ShapeDrawable) getBackground()).getPaint().setColor(res.getColor(colorRes));
}
}
public void setBackgroundColor(int color) {
if (getBackground() instanceof ShapeDrawable) {
((ShapeDrawable) getBackground()).getPaint().setColor(color);
}
}
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;
}
invalidate();
}
public boolean circleBackgroundEnabled() {
return mCircleBackgroundEnabled;
}
public void setCircleBackgroundEnabled(boolean enableCircleBackground) {
this.mCircleBackgroundEnabled = enableCircleBackground;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (mProgressDrawable != null) {
mProgressDrawable.stop();
mProgressDrawable.setVisible(getVisibility() == VISIBLE, false);
}
}
@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);
}
}
public void start() {
mProgressDrawable.start();
}
public void setStartEndTrim(float startAngle, float endAngle) {
mProgressDrawable.setStartEndTrim(startAngle, endAngle);
}
public void stop() {
mProgressDrawable.stop();
}
public void setProgressRotation(float rotation) {
mProgressDrawable.setProgressRotation(rotation);
}
}