答案 0 :(得分:31)
我在网上找到的最好的两个库是github:
希望能帮到你
答案 1 :(得分:27)
我遇到了同样的问题而没有为我的案子找到任何合适的解决方案,所以我决定采取另一种方式。我已经创建了自定义可绘制类。在这个课程中,我为进度线和背景线(有一些更大的笔划)创建了2个Paints。首先在构造函数中设置startAngle和sweepAngle:
mSweepAngle = 0;
mStartAngle = 270;
以下是此类的onDraw方法:
@Override
public void draw(Canvas canvas) {
// draw background line
canvas.drawArc(mRectF, 0, 360, false, mPaintBackground);
// draw progress line
canvas.drawArc(mRectF, mStartAngle, mSweepAngle, false, mPaintProgress);
}
所以现在你需要做的就是将这个drawable设置为视图的backgorund,在后台线程更改中扫描一下:
mSweepAngle += 360 / totalTimerTime // this is mStep
并在具有此drawable作为背景的视图上以一定的间隔(例如,如果您希望平滑进度更改,每隔1秒或更多次)直接调用InvalidateSelf()。多数民众赞成!
P.S。我知道,我知道......当然你想要更多的代码。所以这就是所有流程:
创建XML视图:
<View
android:id="@+id/timer"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
创建和配置Custom Drawable类(如上所述)。不要忘记为线条设置Paints。这里绘制了进度线:
mPaintProgress = new Paint();
mPaintProgress.setAntiAlias(true);
mPaintProgress.setStyle(Paint.Style.STROKE);
mPaintProgress.setStrokeWidth(widthProgress);
mPaintProgress.setStrokeCap(Paint.Cap.ROUND);
mPaintProgress.setColor(colorThatYouWant);
相同的背景画(如果你愿意,可以设置更多的宽度)
在drawable类中创建更新方法(上述步骤计算)
public void update() {
mSweepAngle += mStep;
invalidateSelf();
}
将此drawable类设置为YourTimerView(我在运行时完成) - 使用上面xml的@ + id / timer查看:
OurSuperDrawableClass superDrawable = new OurSuperDrawableClass();
YourTimerView.setBackgroundDrawable(superDrawable);
使用runnable和update视图创建后台线程:
YourTimerView.post(new Runnable() {
@Override
public void run() {
// update progress view
superDrawable.update();
}
});
多数民众赞成!享受你的酷进度吧。如果您对此大量文字感到厌倦,请在此处截断结果。
答案 2 :(得分:9)
for more information on How to create Circle Android Custom Progress Bar view this link
步骤01 您应该在可绘制文件上创建一个xml文件,以配置进度条的外观。所以我创建我的xml文件为circular_progress_bar.xml。
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="120"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="140">
<item android:id="@android:id/background">
<shape
android:innerRadiusRatio="3"
android:shape="ring"
android:useLevel="false"
android:angle="0"
android:type="sweep"
android:thicknessRatio="50.0">
<solid android:color="#000000"/>
</shape>
</item>
<item android:id="@android:id/progress">
<rotate
android:fromDegrees="120"
android:toDegrees="120">
<shape
android:innerRadiusRatio="3"
android:shape="ring"
android:angle="0"
android:type="sweep"
android:thicknessRatio="50.0">
<solid android:color="#ffffff"/>
</shape>
</rotate>
</item>
</layer-list>
步骤02 然后在xml文件上创建进度条 然后在你的drawable文件夹中给出xml文件的名称作为android:progressDrawable
的部分 <ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_marginLeft="0dp"
android:layout_centerHorizontal="true"
android:indeterminate="false"
android:max="100"
android:progressDrawable="@drawable/circular_progress_bar" />
步骤03 使用线程
显示进度条package com.example.progress;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.view.Menu;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends Activity {
private ProgressBar progBar;
private TextView text;
private Handler mHandler = new Handler();
private int mProgressStatus=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progBar= (ProgressBar)findViewById(R.id.progressBar);
text = (TextView)findViewById(R.id.textView1);
dosomething();
}
public void dosomething() {
new Thread(new Runnable() {
public void run() {
final int presentage=0;
while (mProgressStatus < 63) {
mProgressStatus += 1;
// Update the progress bar
mHandler.post(new Runnable() {
public void run() {
progBar.setProgress(mProgressStatus);
text.setText(""+mProgressStatus+"%");
}
});
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
答案 3 :(得分:6)
Android中自定义进度条的一个非常有用的lib。
在您的布局文件中
<com.lylc.widget.circularprogressbar.example.CircularProgressBar
android:id="@+id/mycustom_progressbar"
.
.
.
/>
和Java文件
CircularProgressBar progressBar = (CircularProgressBar) findViewById(R.id.mycustom_progressbar);
progressBar.setTitle("Circular Progress Bar");
答案 4 :(得分:4)
尝试使用这段代码创建循环进度条(饼图)。传递整数值来绘制填充区域的百分之几。 :)
private void circularImageBar(ImageView iv2, int i) {
Bitmap b = Bitmap.createBitmap(300, 300,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(b);
Paint paint = new Paint();
paint.setColor(Color.parseColor("#c4c4c4"));
paint.setStrokeWidth(10);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(150, 150, 140, paint);
paint.setColor(Color.parseColor("#FFDB4C"));
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.FILL);
final RectF oval = new RectF();
paint.setStyle(Paint.Style.STROKE);
oval.set(10,10,290,290);
canvas.drawArc(oval, 270, ((i*360)/100), false, paint);
paint.setStrokeWidth(0);
paint.setTextAlign(Align.CENTER);
paint.setColor(Color.parseColor("#8E8E93"));
paint.setTextSize(140);
canvas.drawText(""+i, 150, 150+(paint.getTextSize()/3), paint);
iv2.setImageBitmap(b);
}
答案 5 :(得分:4)
我通过创建自定义视图解决了这个很酷的自定义进度条。我已经覆盖onDraw()方法在画布上绘制圆圈,填充圆弧和文本。
以下是自定义进度条
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import com.investorfinder.utils.UiUtils;
public class CustomProgressBar extends View {
private int max = 100;
private int progress;
private Path path = new Path();
int color = 0xff44C8E5;
private Paint paint;
private Paint mPaintProgress;
private RectF mRectF;
private Paint textPaint;
private String text = "0%";
private final Rect textBounds = new Rect();
private int centerY;
private int centerX;
private int swipeAndgle = 0;
public CustomProgressBar(Context context) {
super(context);
initUI();
}
public CustomProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
initUI();
}
public CustomProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initUI();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CustomProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initUI();
}
private void initUI() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(UiUtils.dpToPx(getContext(), 1));
paint.setStyle(Paint.Style.STROKE);
paint.setColor(color);
mPaintProgress = new Paint();
mPaintProgress.setAntiAlias(true);
mPaintProgress.setStyle(Paint.Style.STROKE);
mPaintProgress.setStrokeWidth(UiUtils.dpToPx(getContext(), 9));
mPaintProgress.setColor(color);
textPaint = new Paint();
textPaint.setAntiAlias(true);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setColor(color);
textPaint.setStrokeWidth(2);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int viewWidth = MeasureSpec.getSize(widthMeasureSpec);
int viewHeight = MeasureSpec.getSize(heightMeasureSpec);
int radius = (Math.min(viewWidth, viewHeight) - UiUtils.dpToPx(getContext(), 2)) / 2;
path.reset();
centerX = viewWidth / 2;
centerY = viewHeight / 2;
path.addCircle(centerX, centerY, radius, Path.Direction.CW);
int smallCirclRadius = radius - UiUtils.dpToPx(getContext(), 7);
path.addCircle(centerX, centerY, smallCirclRadius, Path.Direction.CW);
smallCirclRadius += UiUtils.dpToPx(getContext(), 4);
mRectF = new RectF(centerX - smallCirclRadius, centerY - smallCirclRadius, centerX + smallCirclRadius, centerY + smallCirclRadius);
textPaint.setTextSize(radius * 0.5f);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(path, paint);
canvas.drawArc(mRectF, 270, swipeAndgle, false, mPaintProgress);
drawTextCentred(canvas);
}
public void drawTextCentred(Canvas canvas) {
textPaint.getTextBounds(text, 0, text.length(), textBounds);
canvas.drawText(text, centerX - textBounds.exactCenterX(), centerY - textBounds.exactCenterY(), textPaint);
}
public void setMax(int max) {
this.max = max;
}
public void setProgress(int progress) {
this.progress = progress;
int percentage = progress * 100 / max;
swipeAndgle = percentage * 360 / 100;
text = percentage + "%";
invalidate();
}
public void setColor(int color) {
this.color = color;
}
}
布局XML
<com.your.package.name.CustomProgressBar
android:id="@+id/progress_bar"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_alignParentRight="true"
android:layout_below="@+id/txt_title"
android:layout_marginRight="15dp" />
活动
CustomProgressBar progressBar = (CustomProgressBar)findViewById(R.id.progress_bar);
progressBar.setMax(9);
progressBar.setProgress(5);
答案 6 :(得分:0)
我将创建一个新的视图类并从现有的ProgressBar派生。然后覆盖onDraw函数。你需要对画布进行直接绘制调用,因为它的自定义 - drawText,drawArc和drawOval的组合应该这样做 - 外圈和空部分的椭圆形,以及部分着色。您可能最终还需要覆盖onMeasure和onLayout。然后在你的xml中,当你想使用它时,按类名引用这个视图。
答案 7 :(得分:0)
我做了一个简单的类,您可以用它来制作自定义的ProgressBar对话框。 实际上,它具有2个默认布局: -第一个对话框,没有面板,进度条和动画文本居中 -带有面板,进度栏,标题和消息的第二个普通对话框
这只是一个类,因此不是可在您的项目中导入的可自定义库,因此您需要复制它并按需要更改它。 它是一个DialogFragment类,但是您可以在活动中将其用作常规片段,就像使用FragmentManager处理经典片段一样。
public class ProgressBarDialog extends DialogFragment {
private static final String TAG = ProgressBarDialog.class.getSimpleName();
private static final String KEY = TAG.concat(".key");
// Argument Keys
private static final String KEY_DIALOG_TYPE = KEY.concat(".dialogType");
private static final String KEY_TITLE = KEY.concat(".title");
private static final String KEY_PROGRESS_TEXT = KEY.concat(".progressText");
private static final String KEY_CUSTOM_LAYOUT_BUILDER = KEY.concat(".customLayoutBuilder");
// Class Names
private static final String CLASS_GRADIENT_STATE = "GradientState";
// Field Names
private static final String FIELD_THICKNESS = "mThickness";
private static final String FIELD_INNER_RADIUS = "mInnerRadius";
/** Dialog Types **/
private static final int TYPE_PROGRESS_BAR_ONLY_NO_ANIM = 0x0;
private static final int TYPE_PROGRESS_BAR_ONLY_ROTATE_ANIM = 0x1;
private static final int TYPE_PROGRESS_BAR_ONLY_FADE_ANIM = 0x2;
private static final int TYPE_PROGRESS_BAR_AND_MSG = 0xF;
/** Animations Values **/
private static final long CENTER_TEXT_VIEWS_ANIMATION_DURATION = 250L;
private static final long CENTER_TEXT_VIEWS_START_OFFSET_MULTIPLIER = 250L;
private MaterialProgressBar mProgressBar;
private LinearLayout mllTextContainer;
private TextView mtvTitle;
private TextView mtvProgressText;
private List<TextView> mCenterTextViews;
private int mDialogType;
private String mTitle;
private String mProgressText;
private CustomLayoutBuilder mCustomLayoutBuilder;
/** Public Static Factory Methods **/
public static ProgressBarDialog initLayoutProgressBarOnlyNoAnim(String text, CustomLayoutBuilder builder){
return initLayoutProgressBarOnly(TYPE_PROGRESS_BAR_ONLY_NO_ANIM, text, builder);
}
public static ProgressBarDialog initLayoutProgressBarOnlyRotateAnim(String text, CustomLayoutBuilder builder){
return initLayoutProgressBarOnly(TYPE_PROGRESS_BAR_ONLY_ROTATE_ANIM, text, builder);
}
public static ProgressBarDialog initLayoutProgressBarOnlyFadeAnim(String text, CustomLayoutBuilder builder){
return initLayoutProgressBarOnly(TYPE_PROGRESS_BAR_ONLY_FADE_ANIM, text, builder);
}
public static ProgressBarDialog initLayoutProgressBarAndMsg(String title, String text, CustomLayoutBuilder builder){
ProgressBarDialog mInstance = new ProgressBarDialog();
Bundle args = new Bundle();
args.putInt(KEY_DIALOG_TYPE, TYPE_PROGRESS_BAR_AND_MSG);
args.putString(KEY_TITLE, title);
args.putString(KEY_PROGRESS_TEXT, text);
args.putParcelable(KEY_CUSTOM_LAYOUT_BUILDER, builder);
mInstance.setArguments(args);
return mInstance;
}
/** Private Static Factory Methods **/
private static ProgressBarDialog initLayoutProgressBarOnly(int animation, String text, CustomLayoutBuilder builder){
ProgressBarDialog mInstance = new ProgressBarDialog();
Bundle args = new Bundle();
args.putInt(KEY_DIALOG_TYPE, animation);
args.putString(KEY_PROGRESS_TEXT, text);
args.putParcelable(KEY_CUSTOM_LAYOUT_BUILDER, builder);
mInstance.setArguments(args);
return mInstance;
}
/** Override Lifecycle Methods **/
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initData();
}
@Override @Nullable
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.dialog_progress_bar, container, false);
initViews(view);
if(getContext() != null && mCustomLayoutBuilder != null) {
mProgressBar.setIndeterminateDrawable(getResources().getDrawable(mCustomLayoutBuilder.getLayoutResID()));
initShapes();
}
return view;
}
private void initShapes(){
if(mProgressBar.getIndeterminateDrawable() instanceof LayerDrawable) {
LayerDrawable layerDrawable = (LayerDrawable) mProgressBar.getIndeterminateDrawable();
for (int i = 0; i < layerDrawable.getNumberOfLayers(); i++) {
if(layerDrawable.getDrawable(i) instanceof RotateDrawable) {
RotateDrawable rotateDrawable = (RotateDrawable) layerDrawable.getDrawable(i);
int[] fromToDeg = mCustomLayoutBuilder.getDegreesMatrixRow(i);
if(fromToDeg.length > 0){
rotateDrawable.setFromDegrees(fromToDeg[CustomLayoutBuilder.INDEX_FROM_DEGREES]);
rotateDrawable.setToDegrees(fromToDeg[CustomLayoutBuilder.INDEX_TO_DEGREES]);
}
if(rotateDrawable.getDrawable() instanceof GradientDrawable){
GradientDrawable gradientDrawable = (GradientDrawable) rotateDrawable.getDrawable();
int innerRadius = getResources().getDimensionPixelSize(mCustomLayoutBuilder.getInnerRadius(i));
if(mDialogType == TYPE_PROGRESS_BAR_AND_MSG){
innerRadius /= 3;
}
int thickness = getResources().getDimensionPixelSize(mCustomLayoutBuilder.getThickness(i));
int[] colors = mCustomLayoutBuilder.getColorsMatrixRow(i);
if(colors.length > 0x0){
gradientDrawable.setColors(DataUtils.resourcesIDsToColors(this.getContext(), colors));
}
if(innerRadius != -0x1){
DataUtils.setSubClassFieldIntValue(gradientDrawable.getConstantState(), gradientDrawable.getClass(), CLASS_GRADIENT_STATE, FIELD_INNER_RADIUS, innerRadius);
}
if(thickness != -0x1){
DataUtils.setSubClassFieldIntValue(gradientDrawable.getConstantState(), gradientDrawable.getClass(), CLASS_GRADIENT_STATE, FIELD_THICKNESS, thickness);
}
}
}
}
}
}
@Override
public void onStart() {
super.onStart();
setWindowSize();
startAnimation();
}
/** Public Methods **/
public void changeTextViews(String progressText){
mProgressText = progressText;
initTextViews();
startAnimation();
}
public String getProgressText(){
return mProgressText;
}
/** Private Methods **//** Init Methods **/
private void initData(){
if(getArguments() != null) {
if (getArguments().containsKey(KEY_DIALOG_TYPE)) {
mDialogType = getArguments().getInt(KEY_DIALOG_TYPE);
}
if(getArguments().containsKey(KEY_TITLE)){
mTitle = getArguments().getString(KEY_TITLE);
}
if (getArguments().containsKey(KEY_PROGRESS_TEXT)) {
mProgressText = getArguments().getString(KEY_PROGRESS_TEXT);
}
if (getArguments().containsKey(KEY_CUSTOM_LAYOUT_BUILDER)){
mCustomLayoutBuilder = getArguments().getParcelable(KEY_CUSTOM_LAYOUT_BUILDER);
}
}
mCenterTextViews = new ArrayList<>();
}
private void initViews(View layout){
if(layout != null){
switch(mDialogType){
case TYPE_PROGRESS_BAR_ONLY_NO_ANIM:
case TYPE_PROGRESS_BAR_ONLY_ROTATE_ANIM:
case TYPE_PROGRESS_BAR_ONLY_FADE_ANIM:
if(getDialog() != null && getDialog().getWindow() != null) {
getDialog().getWindow().setBackgroundDrawableResource(android.R.color.transparent);
}
LinearLayout mLayoutProgressBarOnly = layout.findViewById(R.id.layout_progress_bar_only);
mLayoutProgressBarOnly.setVisibility(LinearLayout.VISIBLE);
mProgressBar = layout.findViewById(R.id.dpb_progress_bar);
if(mCustomLayoutBuilder.getProgressBarWidthDimen() != -0x1){
ConstraintLayout.LayoutParams lp = (ConstraintLayout.LayoutParams) mProgressBar.getLayoutParams();
lp.width = getResources().getDimensionPixelSize(mCustomLayoutBuilder.getProgressBarWidthDimen());
lp.height = getResources().getDimensionPixelSize(mCustomLayoutBuilder.getProgressBarHeightDimen());
mProgressBar.setLayoutParams(lp);
}
mllTextContainer = layout.findViewById(R.id.dpb_text_container);
initTextViews();
break;
case TYPE_PROGRESS_BAR_AND_MSG:
LinearLayout mLayoutProgressBarAndMsg = layout.findViewById(R.id.layout_progress_bar_and_msg);
mLayoutProgressBarAndMsg.setVisibility(LinearLayout.VISIBLE);
mProgressBar = layout.findViewById(R.id.dpb_progress_bar_and_msg);
mtvTitle = layout.findViewById(R.id.pbd_title);
mtvProgressText = layout.findViewById(R.id.dpb_progress_msg);
initProgressMsg();
break;
}
}
}
private void initTextViews(){
if(!TextUtils.isEmpty(mProgressText)){
clearTextContainer();
for(char digit : mProgressText.toCharArray()){
TextView tv = new TextView(getContext(), null, 0x0, R.style.PBDCenterTextStyleWhite);
if(mCustomLayoutBuilder.getProgressMsgColor() != CustomLayoutBuilder.DEFAULT_COLOR && getContext() != null){
tv.setTextColor(ActivityCompat.getColor(getContext(), mCustomLayoutBuilder.getProgressMsgColor()));
}
if(mCustomLayoutBuilder.getProgressMsgDimen() != CustomLayoutBuilder.DEFAULT_DIMEN){
tv.setTextSize(getResources().getDimension(mCustomLayoutBuilder.getProgressMsgDimen()));
}
tv.setText(String.valueOf(digit));
mCenterTextViews.add(tv);
mllTextContainer.addView(tv);
}
}
}
private void initProgressMsg(){
mtvTitle.setText(mTitle);
mtvProgressText.setText(mProgressText);
if(mCustomLayoutBuilder.getProgressMsgColor() != CustomLayoutBuilder.DEFAULT_COLOR){
mtvProgressText.setTextColor(mCustomLayoutBuilder.getProgressMsgColor());
}
if(mCustomLayoutBuilder.getProgressMsgDimen() != CustomLayoutBuilder.DEFAULT_DIMEN){
mtvProgressText.setTextSize(getResources().getDimension(mCustomLayoutBuilder.getProgressMsgDimen()));
}
}
private void clearTextContainer(){
if(mllTextContainer.getChildCount() >= 0x0){
for(int i=0; i < mllTextContainer.getChildCount(); i++){
View v = mllTextContainer.getChildAt(i);
if(v instanceof TextView){
TextView tv = (TextView) v;
if(tv.getAnimation() != null){
tv.clearAnimation();
}
}
}
}
mllTextContainer.removeAllViews();
}
private void setWindowSize(){
Dialog dialog = getDialog();
if(dialog != null && dialog.getWindow() != null){
int width = 0x0, height = 0x0;
switch(mDialogType){
case TYPE_PROGRESS_BAR_ONLY_NO_ANIM:
case TYPE_PROGRESS_BAR_ONLY_ROTATE_ANIM:
case TYPE_PROGRESS_BAR_ONLY_FADE_ANIM:
width = ViewGroup.LayoutParams.WRAP_CONTENT; //getResources().getDimensionPixelSize(R.dimen.pbd_window_width);
height = ViewGroup.LayoutParams.WRAP_CONTENT; //getResources().getDimensionPixelSize(R.dimen.pbd_window_height);
break;
case TYPE_PROGRESS_BAR_AND_MSG:
width = ViewGroup.LayoutParams.MATCH_PARENT;
height = ViewGroup.LayoutParams.WRAP_CONTENT; //getResources().getDimensionPixelSize(R.dimen.pbd_textual_window_height);
break;
}
dialog.getWindow().setLayout(width, height);
}
}
/** Animation Methods **/
private void startAnimation(){
switch(mDialogType){
case TYPE_PROGRESS_BAR_ONLY_ROTATE_ANIM:
startRotateAnimations();
break;
case TYPE_PROGRESS_BAR_ONLY_FADE_ANIM:
startFadeInAnimations();
break;
}
}
private void startRotateAnimations(){
for(TextView tv : mCenterTextViews){
if(tv != null && tv.getText() != null && !TextUtils.isEmpty(tv.getText().toString().trim())) {
int i = mCenterTextViews.indexOf(tv);
RotateAnimation anim = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
anim.setDuration(CENTER_TEXT_VIEWS_ANIMATION_DURATION);
anim.setFillAfter(true);
anim.setStartOffset(CENTER_TEXT_VIEWS_START_OFFSET_MULTIPLIER * i);
if (i == (mCenterTextViews.size() - 0x1)) {
anim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
startRotateAnimations();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
tv.startAnimation(anim);
}
}
}
private void startFadeInAnimations(){
for(TextView tv : mCenterTextViews){
if(tv != null && tv.getText() != null && !TextUtils.isEmpty(tv.getText().toString().trim())) {
int i = mCenterTextViews.indexOf(tv);
AlphaAnimation anim = new AlphaAnimation(0x1, 0x0);
anim.setDuration(CENTER_TEXT_VIEWS_ANIMATION_DURATION);
anim.setFillAfter(true);
anim.setStartOffset(CENTER_TEXT_VIEWS_START_OFFSET_MULTIPLIER * i);
if (i == (mCenterTextViews.size() - 0x1)) {
anim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
startFadeOutAnimations();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
tv.startAnimation(anim);
}
}
}
private void startFadeOutAnimations(){
for(TextView tv : mCenterTextViews){
int i = mCenterTextViews.indexOf(tv);
AlphaAnimation anim = new AlphaAnimation(0x0, 0x1);
anim.setDuration(CENTER_TEXT_VIEWS_ANIMATION_DURATION);
anim.setFillAfter(true);
anim.setStartOffset(CENTER_TEXT_VIEWS_START_OFFSET_MULTIPLIER * i);
if(i == (mCenterTextViews.size() - 0x1)){
anim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
startFadeInAnimations();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
tv.startAnimation(anim);
}
}
/** Progress Bar Custom Layout Builder Class **/
public static class CustomLayoutBuilder implements Parcelable {
/** Shapes **/
private static final int RING = GradientDrawable.RING;
/** Colors **/
private static final int[][] COLORS_MATRIX_RYGB = new int[][]{
new int[]{ R.color.transparent, R.color.transparent, R.color.material_red_A700 },
new int[]{ R.color.transparent, R.color.transparent, R.color.material_amber_A700 },
new int[]{ R.color.transparent, R.color.transparent, R.color.material_light_green_A700 },
new int[]{ R.color.transparent, R.color.transparent, R.color.material_blue_A700 }
};
private static final int DEFAULT_COLOR = -0x1;
/** Dimens **/
private static final int DEFAULT_DIMEN = -0x1;
private static final int[] DEFAULT_PROGRESS_BAR_DIMEN = new int[]{};
/** Indexes **/
private static final int INDEX_PROGRESS_BAR_WIDTH = 0x0;
private static final int INDEX_PROGRESS_BAR_HEIGHT = 0x1;
private static final int INDEX_FROM_DEGREES = 0x0;
private static final int INDEX_TO_DEGREES = 0x1;
/** Arrays Sizes **/
private static final int SIZE_PROGRESS_BAR_DIMENS_ARRAY = 0x2;
/** Matrix Columns Number **/
private static final int NUM_COLUMNS_DEGREES_MATRIX = 0x2; /* Degrees Matrix Index -> degrees[3] = { fromDegrees, toDegrees } */
private static final int NUM_COLUMNS_COLORS_MATRIX = 0x3; /* GradientDrawable Colors Matrix Index -> colors[3] = { startColor, centerColor, endColor } */
/** Drawables Layout Resource IDs **/
private static final int LAYOUT_RES_PROGRESS_BAR_RINGS = R.drawable.progress_bar_rings;
/** Layout Data: Four Rings Overlaid **/
private static final int RINGS_OVERLAID_LAYERS = 0x4;
private static final int[][] RINGS_OVERLAID_DEGREES = new int[][]{ new int[]{ 300, 660 }, new int[]{ 210, 570 }, new int[]{ 120, 480 }, new int[]{ 30, 390 } };
private static final int[] RINGS_OVERLAID_SHAPES = new int[]{ RING, RING, RING, RING };
private static final int[] RINGS_OVERLAID_INNER_RADIUS = new int[]{ R.dimen.pbd_inner_radius_60dp, R.dimen.pbd_inner_radius_60dp, R.dimen.pbd_inner_radius_60dp, R.dimen.pbd_inner_radius_60dp};
private static final int[] RINGS_OVERLAID_THICKNESS = new int[]{ R.dimen.pbd_thickness_40dp, R.dimen.pbd_thickness_30dp, R.dimen.pbd_thickness_20dp, R.dimen.pbd_thickness_10dp };
/** Layout Data: Four Rings Spaced **/
private static final int RINGS_SPACED_LAYERS = 0x4;
private static final int[][] RINGS_SPACED_DEGREES = new int[][]{ new int[]{ 180, 540 }, new int[]{ 0, 360 }, new int[]{ 90, 450 }, new int[]{ 270, 630 } };
private static final int[] RINGS_SPACED_SHAPES = new int[]{ RING, RING, RING, RING };
private static final int[] RINGS_SPACED_INNER_RADIUS = new int[]{ R.dimen.pbd_inner_radius_30dp, R.dimen.pbd_inner_radius_60dp, R.dimen.pbd_inner_radius_90dp, R.dimen.pbd_inner_radius_120dp };
private static final int[] RINGS_SPACED_THICKNESS = new int[]{ R.dimen.pbd_thickness_10dp, R.dimen.pbd_thickness_15dp, R.dimen.pbd_thickness_20dp, R.dimen.pbd_thickness_25dp };
private int mLayoutResID;
private int[] mProgressBarDimens;
private int mNumLayers;
private int[][] mRotateDegrees;
private int[] mShapes;
private int[] mInnerRadius;
private int[] mThickness;
private int[][] mColors;
private int mProgressMsgColor;
private int mProgressMsgDimen;
public static Parcelable.Creator CREATOR = new CreatorCustomLayoutBuilder();
/** Constructors **/
private CustomLayoutBuilder(int layoutResID, int[] progressBarDimens, int numLayers, int[][] degreesMatrix, int[] shapes, int[] innerRadius, int[] thickness,
int[][] colorsMatrix, int msgColor, int progressMsgDimen){
mLayoutResID = layoutResID;
mProgressBarDimens = progressBarDimens;
mNumLayers = numLayers;
mRotateDegrees = degreesMatrix;
mShapes = shapes;
mInnerRadius = innerRadius;
mThickness = thickness;
mColors = colorsMatrix;
mProgressMsgColor = msgColor;
mProgressMsgDimen = progressMsgDimen;
}
private CustomLayoutBuilder(Parcel in){
mLayoutResID = in.readInt();
mProgressBarDimens = new int[SIZE_PROGRESS_BAR_DIMENS_ARRAY];
in.readIntArray(mProgressBarDimens);
mNumLayers = in.readInt();
int[] tempArray = new int[NUM_COLUMNS_DEGREES_MATRIX * mNumLayers];
in.readIntArray(tempArray);
mRotateDegrees = DataUtils.arrayToMatrix(tempArray, NUM_COLUMNS_DEGREES_MATRIX);
mShapes = new int[mNumLayers];
in.readIntArray(mShapes);
mInnerRadius = new int[mNumLayers];
in.readIntArray(mInnerRadius);
mThickness = new int[mNumLayers];
in.readIntArray(mThickness);
tempArray = new int[NUM_COLUMNS_COLORS_MATRIX * mNumLayers];
in.readIntArray(tempArray);
mColors = DataUtils.arrayToMatrix(tempArray, NUM_COLUMNS_COLORS_MATRIX);
mProgressMsgColor = in.readInt();
mProgressMsgDimen = in.readInt();
}
/** Public Static Factory Methods **/
public static CustomLayoutBuilder initLayoutRingsOverlaid(){
return new CustomLayoutBuilder(LAYOUT_RES_PROGRESS_BAR_RINGS, DEFAULT_PROGRESS_BAR_DIMEN, RINGS_OVERLAID_LAYERS, RINGS_OVERLAID_DEGREES, RINGS_OVERLAID_SHAPES,
RINGS_OVERLAID_INNER_RADIUS, RINGS_OVERLAID_THICKNESS, COLORS_MATRIX_RYGB, R.color.material_white, DEFAULT_DIMEN);
}
public static CustomLayoutBuilder initLayoutRingsOverlaid(int[] resProgBarDimens, int resProgMsgColor, int resProgMsgDimen){
return new CustomLayoutBuilder(LAYOUT_RES_PROGRESS_BAR_RINGS, resProgBarDimens, RINGS_OVERLAID_LAYERS, RINGS_OVERLAID_DEGREES, RINGS_OVERLAID_SHAPES,
RINGS_OVERLAID_INNER_RADIUS, RINGS_OVERLAID_THICKNESS, COLORS_MATRIX_RYGB, resProgMsgColor, resProgMsgDimen);
}
public static CustomLayoutBuilder initLayoutRingsSpaced(){
return new CustomLayoutBuilder(LAYOUT_RES_PROGRESS_BAR_RINGS, DEFAULT_PROGRESS_BAR_DIMEN, RINGS_SPACED_LAYERS, RINGS_SPACED_DEGREES, RINGS_SPACED_SHAPES,
RINGS_SPACED_INNER_RADIUS, RINGS_SPACED_THICKNESS, COLORS_MATRIX_RYGB, DEFAULT_COLOR, DEFAULT_DIMEN);
}
/** Override Parcelable Methods **/
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mLayoutResID);
out.writeIntArray(mProgressBarDimens);
out.writeInt(mNumLayers);
out.writeIntArray(DataUtils.matrixToArray(mRotateDegrees));
out.writeIntArray(mShapes);
out.writeIntArray(mInnerRadius);
out.writeIntArray(mThickness);
out.writeIntArray(DataUtils.matrixToArray(mColors));
out.writeInt(mProgressMsgColor);
out.writeInt(mProgressMsgDimen);
}
/** Getter & Setter Methods **/
private int getLayoutResID() {
return mLayoutResID;
}
private void setLayoutResID(int layoutResID) {
this.mLayoutResID = layoutResID;
}
private int[] getProgressBarDimens() {
return mProgressBarDimens;
}
private void setProgressBarDimens(int[] progressBarDimens) {
this.mProgressBarDimens = progressBarDimens;
}
private int getProgressBarWidthDimen(){ // Used to check if 'mProgressBarDimens' array is set.
if(mProgressBarDimens != null && mProgressBarDimens.length == SIZE_PROGRESS_BAR_DIMENS_ARRAY){
return mProgressBarDimens[INDEX_PROGRESS_BAR_WIDTH];
} else {
return -0x1;
}
}
private int getProgressBarHeightDimen(){
return mProgressBarDimens[INDEX_PROGRESS_BAR_HEIGHT];
}
private int getNumLayers() {
return mNumLayers;
}
private void setNumLayers(int numLayers) {
this.mNumLayers = numLayers;
}
private int[][] getRotateDegrees() {
return mRotateDegrees;
}
private void setRotateDegrees(int[][] rotateDegrees) {
this.mRotateDegrees = rotateDegrees;
}
private int[] getShapes() {
return mShapes;
}
private void setShapes(int[] shapes) {
this.mShapes = shapes;
}
private int[] getInnerRadius() {
return mInnerRadius;
}
private void setInnerRadius(int[] innerRadius) {
this.mInnerRadius = innerRadius;
}
private int[] getThickness() {
return mThickness;
}
private void setThickness(int[] thickness) {
this.mThickness = thickness;
}
private int[][] getColorsMatrix() {
return mColors;
}
private void setColorsMatrix(int[][] colorsMatrix) {
this.mColors = colorsMatrix;
}
private int getProgressMsgColor() {
return mProgressMsgColor;
}
private void setProgressMsgColor(int progressMsgColor) {
this.mProgressMsgColor = progressMsgColor;
}
private int getProgressMsgDimen() {
return mProgressMsgDimen;
}
private void setProgressMsgDimen(int progressMsgDimen) {
this.mProgressMsgDimen = progressMsgDimen;
}
/** Public Methods **/
private int[] getDegreesMatrixRow(int numRow){
if(mRotateDegrees != null && mRotateDegrees.length > numRow) {
return mRotateDegrees[numRow];
} else {
return new int[]{};
}
}
private int getShape(int position){
if(mShapes != null && mShapes.length > position){
return mShapes[position];
} else {
return -0x1;
}
}
private int getInnerRadius(int position){
if(mInnerRadius != null && mInnerRadius.length > position){
return mInnerRadius[position];
} else {
return -0x1;
}
}
private int getThickness(int position){
if(mThickness != null && mThickness.length > position){
return mThickness[position];
} else {
return -0x1;
}
}
private int[] getColorsMatrixRow(int numRow) {
if(mColors != null && mColors.length > numRow){
return mColors[numRow];
} else {
return new int[]{};
}
}
/** Private Static Class Parcelable Creator **/
private static class CreatorCustomLayoutBuilder implements Parcelable.Creator<CustomLayoutBuilder> {
@Override
public CustomLayoutBuilder createFromParcel(Parcel in) {
return new CustomLayoutBuilder(in);
}
@Override
public CustomLayoutBuilder[] newArray(int size) {
return new CustomLayoutBuilder[size];
}
}
}
}
该类具有进度栏,没有对话框,并且没有自定义文本。 文本可以有2种动画:
淡入->淡出动画:数字会从左到右依次淡出。文本结尾将从左重新开始。
旋转动画:相同的顺序行为,但数字在其自身上一个一个旋转,而不是淡出。
其他方法是带有对话框(标题+消息)的进度栏
答案 8 :(得分:0)
public static int[] resourcesIDsToColors(Context context, int[] resIDs){
int[] colors = new int[resIDs.length];
for(int i=0; i < resIDs.length; i++){
colors[i] = ActivityCompat.getColor(context, resIDs[i]);
}
return colors;
}
public static void setSubClassFieldIntValue(Object objField, Class<?> superClass, String subName, String fieldName, int fieldValue){
Class<?> subClass = getSubClass(superClass, subName);
if(subClass != null) {
Field field = getClassField(subClass, fieldName);
if (field != null) {
setFieldValue(objField, field, fieldValue);
}
}
}
public static Class<?> getSubClass(Class<?> superClass, String subName){
Class<?>[] classes = superClass.getDeclaredClasses();
if(classes != null && classes.length > 0){
for(Class<?> clss : classes){
if(clss.getSimpleName().equals(subName)){
return clss;
}
}
}
return null;
}
public static Field getClassField(Class<?> clss, String fieldName){
try {
Field field = clss.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} catch (NoSuchFieldException nsfE) {
EMaxLogger.onException(TAG, nsfE);
} catch (SecurityException sE){
EMaxLogger.onException(TAG, sE);
} catch (Exception e){
EMaxLogger.onException(TAG, e);
}
return null;
}
public static int[][] arrayToMatrix(int[] array, int numColumns){
int numRows = array.length / numColumns;
int[][] matrix = new int[numRows][numColumns];
int nElemens = array.length;
for(int i=0; i < nElemens; i++){
matrix[i / numColumns][i % numColumns] = array[i];
}
return matrix;
}
public static int[] matrixToArray(int[][] matrix){
/** [+] Square matrix of order n -> A matrix with n rows and n columns, same number of rows and columns.
* [+] Matrix rows & columns number annotations:
* matrix[rows][columns] matrix (rows x columns) matrix rows, columns rows by columns matrix
* **/
int numRows = matrix.length;
int[] arr = new int[]{};
for(int i=0; i < numRows; i++){
int numColumns = matrix[i].length;
int[] row = new int[numColumns];
for(int j=0; j < numColumns; j++){
row[j] = matrix[i][j];
}
arr = ArrayUtils.addAll(arr, row);
}
return arr;
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@color/transparent">
<LinearLayout
android:id="@+id/layout_progress_bar_only"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone">
<android.support.constraint.ConstraintLayout
android:id="@+id/dpb_constraint_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:id="@+id/dpb_progress_bar"
android:layout_width="@dimen/pbd_progressbar_width_2"
android:layout_height="@dimen/pbd_progressbar_height_2"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"/>
<LinearLayout
android:id="@+id/dpb_text_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"/>
</android.support.constraint.ConstraintLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/layout_progress_bar_and_msg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone"
style="@style/PBDTextualMainLayoutStyle">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="@dimen/pbd_textual_card_elevation">
<TextView
android:id="@+id/pbd_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/PBDTextualTitle"/>
</android.support.v7.widget.CardView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/pbd_textual_main_layout_height"
android:orientation="horizontal">
<android.support.v7.widget.CardView
android:layout_width="@dimen/pbd_textual_progressbar_width"
android:layout_height="@dimen/pbd_textual_progressbar_height">
<me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:id="@+id/dpb_progress_bar_and_msg"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="@style/PBDProgressBarStyle"/>
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="@dimen/pbd_textual_msg_container_height">
<TextView
android:id="@+id/dpb_progress_msg"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="@style/PBDTextualProgressMsgStyle"/>
</android.support.v7.widget.CardView>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<rotate
android:fromDegrees="300"
android:toDegrees="660">
<shape
android:shape="ring"
android:useLevel="false">
<gradient
android:type="sweep"/>
</shape>
</rotate>
</item>
<item>
<rotate
android:fromDegrees="210"
android:toDegrees="570">
<shape
android:shape="ring"
android:useLevel="false">
<gradient
android:type="sweep"/>
</shape>
</rotate>
</item>
<item>
<rotate
android:fromDegrees="120"
android:toDegrees="480">
<shape
android:shape="ring"
android:useLevel="false">
<gradient
android:type="sweep"
android:startColor="#00000000"
android:centerColor="#00000000"/>
</shape>
</rotate>
</item>
<item>
<rotate
android:fromDegrees="30"
android:toDegrees="390">
<shape
android:shape="ring"
android:useLevel="false">
<solid android:color="#000000"/>
<gradient
android:type="sweep"/>
</shape>
</rotate>
</item>
</layer-list>
<!-- ProgressBarDialog Dimens (Normal & Textual Versions) -->
<dimen name="pbd_window_width">250dp</dimen>
<dimen name="pbd_window_height">250dp</dimen>
<dimen name="pbd_progressbar_width_1">250dp</dimen>
<dimen name="pbd_progressbar_height_1">250dp</dimen>
<dimen name="pbd_progressbar_width_2">400dp</dimen>
<dimen name="pbd_progressbar_height_2">400dp</dimen>
<dimen name="pbd_textual_window_height">170dp</dimen>
<dimen name="pbd_textual_main_layout_height">150dp</dimen>
<dimen name="pbd_textual_progressbar_width">150dp</dimen>
<dimen name="pbd_textual_progressbar_height">150dp</dimen>
<dimen name="pbd_textual_msg_container_height">150dp</dimen>
<dimen name="pbd_textual_main_layout_margin_horizontal">50dp</dimen>
<dimen name="pbd_textual_main_layout_padding_horizontal">5dp</dimen>
<dimen name="pbd_textual_main_layout_padding_bottom">15dp</dimen>
<dimen name="pbd_textual_title_padding">4dp</dimen>
<dimen name="pbd_textual_msg_container_margin">3dp</dimen>
<dimen name="pbd_textual_msg_container_padding">3dp</dimen>
<dimen name="pbd_textual_card_elevation">15dp</dimen>
<dimen name="pbd_textual_progressmsg_padding_start">10dp</dimen>
<dimen name="pbd_inner_radius_30dp">30dp</dimen>
<dimen name="pbd_inner_radius_60dp">60dp</dimen>
<dimen name="pbd_inner_radius_90dp">90dp</dimen>
<dimen name="pbd_inner_radius_120dp">120dp</dimen>
<dimen name="pbd_thickness_40dp">40dp</dimen>
<dimen name="pbd_thickness_30dp">30dp</dimen>
<dimen name="pbd_thickness_25dp">25dp</dimen>
<dimen name="pbd_thickness_20dp">20dp</dimen>
<dimen name="pbd_thickness_15dp">15dp</dimen>
<dimen name="pbd_thickness_10dp">10dp</dimen>
<!-- PROGRESS BAR DIALOG STYLES -->
<style name="PBDCenterTextStyleWhite">
<item name="android:textAlignment">center</item>
<item name="android:textAppearance">?android:attr/textAppearanceLarge</item>
<item name="android:textStyle">bold|italic</item>
<item name="android:textColor">@color/material_white</item>
<item name="android:layout_gravity">center</item>
<item name="android:gravity">center</item>
</style>
<style name="PBDTextualTitle">
<item name="android:textAlignment">viewStart</item>
<item name="android:textAppearance">?android:attr/textAppearanceLargeInverse</item>
<item name="android:textStyle">bold|italic</item>
<item name="android:textColor">@color/colorAccent</item>
<item name="android:padding">@dimen/pbd_textual_title_padding</item>
<item name="android:layout_gravity">start</item>
<item name="android:gravity">center_vertical|start</item>
<item name="android:background">@color/colorPrimaryDark</item>
</style>
<style name="PBDTextualProgressMsgStyle">
<item name="android:textAlignment">viewStart</item>
<item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
<item name="android:textColor">@color/material_black</item>
<item name="android:textStyle">normal|italic</item>
<item name="android:paddingStart">@dimen/pbd_textual_progressmsg_padding_start</item>
<item name="android:layout_gravity">start</item>
<item name="android:gravity">center_vertical|start</item>
<item name="android:background">@color/material_yellow_A100</item>
</style>
<style name="PBDTextualMainLayoutStyle">
<item name="android:paddingLeft">@dimen/pbd_textual_main_layout_padding_horizontal</item>
<item name="android:paddingRight">@dimen/pbd_textual_main_layout_padding_horizontal</item>
<item name="android:paddingBottom">@dimen/pbd_textual_main_layout_padding_bottom</item>
<item name="android:background">@color/colorPrimaryDark</item>
</style>
<style name="PBDProgressBarStyle">
<item name="android:layout_gravity">center</item>
<item name="android:gravity">center</item>
</style>