ProgressBar
works on Lollipop:AnimatedVectorDrawable
used there, which is not available until Lollipop. The solution that I found was a little insidious, but it still gave me a surprisingly very similar result.ProgressBar
(which is the successor of the standard ProgressBar
) which completely bypasses the standard logic of indefinite time and implements its own based on the standard primary and secondary behavior that is already built into the ProgressBar
. The trick is in the method of processing it - first the background, then the second progress and then the first. If the background and the primary progress of one color, and the secondary progress of another color, then the effect of changing the length. public class MaterialProgressBar extends ProgressBar { private static final int INDETERMINATE_MAX = 1000; private static final String SECONDARY_PROGRESS = "secondaryProgress"; private static final String PROGRESS = "progress"; private Animator animator = null; private final int duration; public MaterialProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MaterialProgressBar, defStyleAttr, 0); int backgroundColour; int progressColour; try { backgroundColour = ta.getColor(R.styleable.MaterialProgressBar_backgroundColour, 0); progressColour = ta.getColor(R.styleable.MaterialProgressBar_progressColour, 0); int defaultDuration = context.getResources().getInteger(android.R.integer.config_mediumAnimTime); duration = ta.getInteger(R.styleable.MaterialProgressBar_duration, defaultDuration); } finally { ta.recycle(); } Resources resources = context.getResources(); setProgressDrawable(resources.getDrawable(android.R.drawable.progress_horizontal)); createIndeterminateProgressDrawable(backgroundColour, progressColour); setMax(INDETERMINATE_MAX); super.setIndeterminate(false); this.setIndeterminate(true); } private void createIndeterminateProgressDrawable(@ColorInt int backgroundColour, @ColorInt int progressColour) { LayerDrawable layerDrawable = (LayerDrawable) getProgressDrawable(); if (layerDrawable != null) { layerDrawable.mutate(); layerDrawable.setDrawableByLayerId(android.R.id.background, createShapeDrawable(backgroundColour)); layerDrawable.setDrawableByLayerId(android.R.id.progress, createClipDrawable(backgroundColour)); layerDrawable.setDrawableByLayerId(android.R.id.secondaryProgress, createClipDrawable(progressColour)); } } private Drawable createClipDrawable(@ColorInt int colour) { ShapeDrawable shapeDrawable = createShapeDrawable(colour); return new ClipDrawable(shapeDrawable, Gravity.START, ClipDrawable.HORIZONTAL); } private ShapeDrawable createShapeDrawable(@ColorInt int colour) { ShapeDrawable shapeDrawable = new ShapeDrawable(); setColour(shapeDrawable, colour); return shapeDrawable; } private void setColour(ShapeDrawable drawable, int colour) { Paint paint = drawable.getPaint(); paint.setColor(colour); } . . . }
createIndeterminateProgressDrawable()
which replaces the layer in LayerDrawable
(which will be processed as a ProgressBar
) with matching colors.ProgressBar
with an indefinite time in the constructor - in order to preserve the simplicity and ease of understanding the example. In fact, there is additional code for switching the standard ProgressBar
to a mode with an indefinite time. public class MaterialProgressBar extends ProgressBar { . . . @Override public synchronized void setIndeterminate(boolean indeterminate) { if (isStarted()) { return; } animator = createIndeterminateAnimator(); animator.setTarget(this); animator.start(); } private boolean isStarted() { return animator != null && animator.isStarted(); } private Animator createIndeterminateAnimator() { AnimatorSet set = new AnimatorSet(); Animator progressAnimator = getAnimator(SECONDARY_PROGRESS, new DecelerateInterpolator()); Animator secondaryProgressAnimator = getAnimator(PROGRESS, new AccelerateInterpolator()); set.playTogether(progressAnimator, secondaryProgressAnimator); set.setDuration(duration); return set; } @NonNull private ObjectAnimator getAnimator(String propertyName, Interpolator interpolator) { ObjectAnimator progressAnimator = ObjectAnimator.ofInt(this, propertyName, 0, INDETERMINATE_MAX); progressAnimator.setInterpolator(interpolator); progressAnimator.setDuration(duration); progressAnimator.setRepeatMode(ValueAnimator.RESTART); progressAnimator.setRepeatCount(ValueAnimator.INFINITE); return progressAnimator; } }
ProgressBar
bit more than usual, and slightly slowing down the animation, we will see the following:Source: https://habr.com/ru/post/270317/
All Articles