服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - Android自定义控件之三点循环缩放效果

Android自定义控件之三点循环缩放效果

2022-08-08 11:06Luo446718254 Android

这篇文章主要为大家详细介绍了Android自定义控件之三点循环缩放效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了Android自定义控件之三点循环缩放的具体代码,供大家参考,具体内容如下

Android自定义控件之三点循环缩放效果

效果图如上,就是三点循环的变大、变小

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
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();//注意这个地方,是从新开始启动动画
   }
   }
  });
  }
 
 
  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;
 }
}

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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 多点循环缩放

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/luo446718254/article/details/52230552

延伸 · 阅读

精彩推荐