溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Android自定義控件之三點(diǎn)循環(huán)縮放效果

發(fā)布時(shí)間:2020-08-19 14:41:19 來源:腳本之家 閱讀:158 作者:Luo446718254 欄目:移動(dòng)開發(fā)

本文實(shí)例為大家分享了Android自定義控件之三點(diǎn)循環(huán)縮放的具體代碼,供大家參考,具體內(nèi)容如下

Android自定義控件之三點(diǎn)循環(huán)縮放效果

效果圖如上,就是三點(diǎn)循環(huán)的變大、變小

package com.example.dotdemo;

import java.util.ArrayList;
import java.util.List;


import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@SuppressLint("NewApi")
public class DilatingDotsProgressBar extends View {
 public static final String TAG = DilatingDotsProgressBar.class.getSimpleName();
 public static final double START_DELAY_FACTOR = 0.35;
 private static final float DEFAULT_GROWTH_MULTIPLIER = 1.75f;
 private static final int MIN_SHOW_TIME = 500; // ms
 private static final int MIN_DELAY = 500; // ms
 private int mDotColor;
 private int mAnimationDuration;
 private int mWidthBetweenDotCenters;
 private int mNumberDots;
 private float mDotRadius;
 private float mDotScaleMultiplier;
 private float mDotMaxRadius;
 private float mHorizontalSpacing;
 private long mStartTime = -1;
 private boolean mShouldAnimate;
 private boolean mDismissed = false;
 private ArrayList<DilatingDotDrawable> mDrawables = new ArrayList<DilatingDotDrawable>();
 private final List<Animator> mAnimations = new ArrayList<Animator>();
 /** delayed runnable to stop the progress */
 private final Runnable mDelayedHide = new Runnable() {
 @Override
 public void run() {
  mStartTime = -1;
  setVisibility(View.GONE);
  stopAnimations();
 }
 };
 /** delayed runnable to start the progress */
 private final Runnable mDelayedShow = new Runnable() {
 @Override
 public void run() {
  if (!mDismissed) {
  mStartTime = System.currentTimeMillis();
  setVisibility(View.VISIBLE);
  startAnimations();
  }
 }
 };

 public DilatingDotsProgressBar(Context context) {
 this(context, null);
 }

 public DilatingDotsProgressBar(Context context, AttributeSet attrs) {
 this(context, attrs, 0);
 }

 public DilatingDotsProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
 super(context, attrs, defStyleAttr);
 init(attrs);
 }

 private void init(AttributeSet attrs) {
 TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.DilatingDotsProgressBar);
 mNumberDots = a.getInt(R.styleable.DilatingDotsProgressBar_dd_numDots, 3);
 mDotRadius = a.getDimension(R.styleable.DilatingDotsProgressBar_android_radius, 8);
 mDotColor = a.getColor(R.styleable.DilatingDotsProgressBar_android_color, 0xff9c27b0);
 mDotScaleMultiplier = a.getFloat(R.styleable.DilatingDotsProgressBar_dd_scaleMultiplier, DEFAULT_GROWTH_MULTIPLIER);
 mAnimationDuration = a.getInt(R.styleable.DilatingDotsProgressBar_dd_animationDuration, 300);
 mHorizontalSpacing = a.getDimension(R.styleable.DilatingDotsProgressBar_dd_horizontalSpacing, 12);
 boolean isShow = a.getBoolean(R.styleable.DilatingDotsProgressBar_dd_show_now, false);
 a.recycle();

 mShouldAnimate = false;
 calculateMaxRadius();
 calculateWidthBetweenDotCenters();

 initDots();
 updateDots();

 if (isShow) {
  showNow();
 }
 }

 @Override
 protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) {
 super.onSizeChanged(w, h, oldw, oldh);
 if (computeMaxHeight() != h || w != computeMaxWidth()) {
  updateDots();
 }
 }

 @Override
 public void onDetachedFromWindow() {
 super.onDetachedFromWindow();
 removeCallbacks();
 }

 private void removeCallbacks() {
 removeCallbacks(mDelayedHide);
 removeCallbacks(mDelayedShow);
 }

 public void reset() {
 hideNow();
 }

 /**
 * Hide the progress view if it is visible. The progress view will not be
 * hidden until it has been shown for at least a minimum show time. If the
 * progress view was not yet visible, cancels showing the progress view.
 */
 public void hide() {
 hide(MIN_SHOW_TIME);
 }

 public void hide(int delay) {
 mDismissed = true;
 removeCallbacks(mDelayedShow);
 long diff = System.currentTimeMillis() - mStartTime;
 if ((diff >= delay) || (mStartTime == -1)) {
  mDelayedHide.run();
 } else {
  if ((delay - diff) <= 0) {
  mDelayedHide.run();
  } else {
  postDelayed(mDelayedHide, delay - diff);
  }
 }
 }

 /**
 * Show the progress view after waiting for a minimum delay. If
 * during that time, hide() is called, the view is never made visible.
 */
 @SuppressWarnings ("unused")
 public void show() {
 show(MIN_DELAY);
 }

 @SuppressWarnings ("unused")
 public void showNow() {
 show(0);
 }

 @SuppressWarnings ("unused")
 public void hideNow() {
 hide(0);
 }

 public void show(int delay) {
 mStartTime = -1;
 mDismissed = false;
 removeCallbacks(mDelayedHide);

 if (delay == 0) {
  mDelayedShow.run();
 } else {
  postDelayed(mDelayedShow, delay);
 }
 }

 @Override
 protected void onDraw(Canvas canvas) {
 if (shouldAnimate()) {
  for (DilatingDotDrawable dot : mDrawables) {
  dot.draw(canvas);
  }
 }
 }

 @Override
 protected boolean verifyDrawable(final Drawable who) {
 if (shouldAnimate()) {
  return mDrawables.contains(who);
 }
 return super.verifyDrawable(who);
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 setMeasuredDimension((int) computeMaxWidth(), (int) computeMaxHeight());
 }

 private float computeMaxHeight() {
 return mDotMaxRadius * 2;
 }

 private float computeMaxWidth() {
 return computeWidth() + ((mDotMaxRadius - mDotRadius) * 2);
 }

 private float computeWidth() {
 return (((mDotRadius * 2) + mHorizontalSpacing) * mDrawables.size()) - mHorizontalSpacing;
 }

 private void calculateMaxRadius() {
 mDotMaxRadius = mDotRadius * mDotScaleMultiplier;
 }

 private void calculateWidthBetweenDotCenters() {
 mWidthBetweenDotCenters = (int) (mDotRadius * 2) + (int) mHorizontalSpacing;
 }

 @SuppressLint("NewApi")
 private void initDots() {
 mDrawables.clear();
 mAnimations.clear();

 Log.i("lcf", "mAnimationDuration = "+mAnimationDuration );

 for (int i = 1; i <= mNumberDots; i++) {
  final DilatingDotDrawable dot = new DilatingDotDrawable(mDotColor, mDotRadius, mDotMaxRadius);
  dot.setCallback(this);
  mDrawables.add(dot);

  ValueAnimator growAnimator = ObjectAnimator.ofFloat(dot, "radius", mDotRadius, mDotMaxRadius, mDotRadius);
  growAnimator.setDuration(mAnimationDuration);
  growAnimator.setInterpolator(new AccelerateDecelerateInterpolator());

  if (i == mNumberDots) {
  growAnimator.addListener(new AnimatorListenerAdapter() {
   @TargetApi(Build.VERSION_CODES.HONEYCOMB)
   @Override
   public void onAnimationEnd(Animator animation) {
   if (shouldAnimate()) {
    startAnimations();//注意這個(gè)地方,是從新開始啟動(dòng)動(dòng)畫
   }
   }
  });
  }


  growAnimator.setStartDelay((i - 1) * (int) (START_DELAY_FACTOR * mAnimationDuration));

  mAnimations.add(growAnimator);
 }
 }

 @SuppressLint("NewApi")
 private void updateDots() {
 if (mDotRadius <= 0) {
  mDotRadius = getHeight() / 2 / mDotScaleMultiplier;
 }

 int left = (int) (mDotMaxRadius - mDotRadius);
 int right = (int) (left + mDotRadius * 2) + 2;
 int top = 0;
 int bottom = (int) (mDotMaxRadius * 2) + 2;

 for (int i = 0; i < mDrawables.size(); i++) {
  final DilatingDotDrawable dot = mDrawables.get(i);
  dot.setRadius(mDotRadius);
  dot.setBounds(left, top, right, bottom);
  ValueAnimator growAnimator = (ValueAnimator) mAnimations.get(i);
  growAnimator.setFloatValues(mDotRadius, mDotRadius * mDotScaleMultiplier, mDotRadius);

  left += mWidthBetweenDotCenters;
  right += mWidthBetweenDotCenters;
 }
 }

 protected void startAnimations() {
 mShouldAnimate = true;
 for (Animator anim : mAnimations) {
  anim.start();
 }
 }

 protected void stopAnimations() {
 mShouldAnimate = false;
 removeCallbacks();
 for (Animator anim : mAnimations) {
  anim.cancel();
 }
 }

 protected boolean shouldAnimate() {
 return mShouldAnimate;
 }

 // -------------------------------
 // ------ Getters & Setters ------
 // -------------------------------

 public void setDotRadius(float radius) {
 reset();
 mDotRadius = radius;
 calculateMaxRadius();
 calculateWidthBetweenDotCenters();
 setupDots();
 }

 public void setDotSpacing(float horizontalSpacing) {
 reset();
 mHorizontalSpacing = horizontalSpacing;
 calculateWidthBetweenDotCenters();
 setupDots();
 }

 public void setGrowthSpeed(int growthSpeed) {
 reset();
 mAnimationDuration = growthSpeed;
 setupDots();
 }

 public void setNumberOfDots(int numDots) {
 reset();
 mNumberDots = numDots;
 setupDots();
 }

 public void setDotScaleMultpiplier(float multplier) {
 reset();
 mDotScaleMultiplier = multplier;
 calculateMaxRadius();
 setupDots();
 }

 public void setDotColor(int color) {
 mDotColor = color;
 for (DilatingDotDrawable dot : mDrawables) {
  dot.setColor(mDotColor);
 }
 }

 private void setupDots() {
 initDots();
 updateDots();
 showNow();
 }

 public int getDotGrowthSpeed() {
 return mAnimationDuration;
 }

 public float getDotRadius() {
 return mDotRadius;
 }

 public float getHorizontalSpacing() {
 return mHorizontalSpacing;
 }

 public int getNumberOfDots() {
 return mNumberDots;
 }

 public float getDotScaleMultiplier() {
 return mDotScaleMultiplier;
 }
}

package com.example.dotdemo;

import android.annotation.SuppressLint;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;

@SuppressLint("Override")
public class extends Drawable {
 private static final String TAG = DilatingDotDrawable.class.getSimpleName();
 private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 private float radius;
 private float maxRadius;
 final Rect mDirtyBounds = new Rect(0, 0, 0, 0);

 public DilatingDotDrawable(final int color, final float radius, final float maxRadius) {
 mPaint.setColor(color);
 mPaint.setStyle(Paint.Style.FILL);
 mPaint.setStrokeCap(Paint.Cap.ROUND);
 mPaint.setStrokeJoin(Paint.Join.ROUND);

 this.radius = radius;
 setMaxRadius(maxRadius);
 }

 @Override
 public void draw(Canvas canvas) {
 final Rect bounds = getBounds();
 canvas.drawCircle(bounds.centerX(), bounds.centerY(), radius - 1, mPaint);
 }

 @Override
 public void setAlpha(int alpha) {
 if (alpha != mPaint.getAlpha()) {
  mPaint.setAlpha(alpha);
  invalidateSelf();
 }
 }

 @Override
 public void setColorFilter(ColorFilter colorFilter) {
 mPaint.setColorFilter(colorFilter);
 invalidateSelf();
 }

 @Override
 public int getOpacity() {
 return PixelFormat.TRANSLUCENT;
 }

 public void setColor(int color) {
 mPaint.setColor(color);
 invalidateSelf();
 }

 public void setRadius(float radius) {
 this.radius = radius;
 invalidateSelf();
 }

 public float getRadius() {
 return radius;
 }

 @Override
 public int getIntrinsicWidth() {
 return (int) (maxRadius * 2) + 2;
 }

 @Override
 public int getIntrinsicHeight() {
 return (int) (maxRadius * 2) + 2;
 }

 public void setMaxRadius(final float maxRadius) {
 this.maxRadius = maxRadius;
 mDirtyBounds.bottom = (int) (maxRadius * 2) + 2;
 mDirtyBounds.right = (int) (maxRadius * 2) + 2;
 }

 public Rect getDirtyBounds() {
 return mDirtyBounds;
 }

 @Override
 protected void onBoundsChange(final Rect bounds) {
 super.onBoundsChange(bounds);
 mDirtyBounds.offsetTo(bounds.left, bounds.top);
 }
}

源碼下載:Android 多點(diǎn)循環(huán)縮放

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI