Guest User

Untitled

a guest
Oct 19th, 2018
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.66 KB | None | 0 0
  1. package com.gtv.hanhee.novelreading.Ui.CustomView;
  2.  
  3. import android.animation.Animator;
  4. import android.animation.AnimatorSet;
  5. import android.animation.ValueAnimator;
  6. import android.content.Context;
  7. import android.content.res.TypedArray;
  8. import android.graphics.Canvas;
  9. import android.graphics.Paint;
  10. import android.graphics.Rect;
  11. import android.graphics.RectF;
  12. import android.os.Parcel;
  13. import android.os.Parcelable;
  14. import android.support.v4.view.animation.FastOutSlowInInterpolator;
  15. import android.util.AttributeSet;
  16. import android.util.TypedValue;
  17. import android.view.View;
  18. import android.view.animation.Interpolator;
  19. import android.view.animation.LinearInterpolator;
  20.  
  21. import com.gtv.hanhee.novelreading.R;
  22.  
  23. public class LoadingView extends View {
  24.  
  25. //the size in wrap_content model
  26. private static final int CIRCLE_DIAMETER = 56;
  27.  
  28. private static final float CENTER_RADIUS = 15f;
  29. private static final float STROKE_WIDTH = 3.5f;
  30.  
  31. private static final float MAX_PROGRESS_ARC = 300f;
  32. private static final float MIN_PROGRESS_ARC = 20f;
  33.  
  34. private static final long ANIMATOR_DURATION = 1332;
  35.  
  36. private Rect bounds;
  37. private Ring mRing;
  38.  
  39. private Animator animator = null;
  40. private AnimatorSet animatorSet = null;
  41. private boolean mIsAnimatorCancel = false;
  42.  
  43. private Interpolator interpolator = null;
  44. //the ring's RectF
  45. private final RectF mTempBounds = new RectF();
  46. //绘制半圆的paint
  47. private Paint mPaint;
  48. private final int DEFAULT_COLOR = 0xFF3B99DF;
  49. private boolean mAnimationStarted = false;
  50. //the ring style
  51. static final int RING_STYLE_SQUARE = 0;
  52. static final int RING_STYLE_ROUND = 1;
  53.  
  54. //the animator style
  55. static final int PROGRESS_STYLE_MATERIAL = 0;
  56. static final int PROGRESS_STYLE_LINEAR = 1;
  57.  
  58. private float mRotation = 0f;
  59.  
  60. public LoadingView(Context context) {
  61. this(context, null);
  62. }
  63.  
  64. public LoadingView(Context context, AttributeSet attrs) {
  65. this(context, attrs, 0);
  66. }
  67.  
  68. public LoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
  69. super(context, attrs, defStyleAttr);
  70. mRing = new Ring();
  71. bounds = new Rect();
  72. mPaint = new Paint();
  73. mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
  74. mPaint.setStyle(Paint.Style.STROKE);
  75. mPaint.setStrokeWidth(mRing.strokeWidth);
  76.  
  77. if (attrs != null) {
  78. TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LoadingView, 0, 0);
  79. setColor(a.getInt(R.styleable.LoadingView_loadding_color, DEFAULT_COLOR));
  80. setRingStyle(a.getInt(R.styleable.LoadingView_ring_style, RING_STYLE_SQUARE));
  81. setProgressStyle(a.getInt(R.styleable.LoadingView_progress_style, PROGRESS_STYLE_MATERIAL));
  82. setStrokeWidth(a.getDimension(R.styleable.LoadingView_ring_width, dp2px(STROKE_WIDTH)));
  83. setCenterRadius(a.getDimension(R.styleable.LoadingView_ring_radius, dp2px(CENTER_RADIUS)));
  84. a.recycle();
  85. }
  86. }
  87.  
  88. /**
  89. * set the ring strokeWidth
  90. *
  91. * @param stroke
  92. */
  93. public void setStrokeWidth(float stroke) {
  94. mRing.strokeWidth = stroke;
  95. mPaint.setStrokeWidth(stroke);
  96. }
  97.  
  98. public void setCenterRadius(float radius) {
  99. mRing.ringCenterRadius = radius;
  100. }
  101.  
  102. public void setRingStyle(int style) {
  103. switch (style) {
  104. case RING_STYLE_SQUARE:
  105. mPaint.setStrokeCap(Paint.Cap.SQUARE);
  106. break;
  107. case RING_STYLE_ROUND:
  108. mPaint.setStrokeCap(Paint.Cap.ROUND);
  109. break;
  110. }
  111. }
  112.  
  113. /**
  114. * set the animator's interpolator
  115. *
  116. * @param style
  117. */
  118. public void setProgressStyle(int style) {
  119. switch (style) {
  120. case PROGRESS_STYLE_MATERIAL:
  121. interpolator = new FastOutSlowInInterpolator();
  122. break;
  123. case PROGRESS_STYLE_LINEAR:
  124. interpolator = new LinearInterpolator();
  125. break;
  126. }
  127. }
  128.  
  129. @Override
  130. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  131. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  132. int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
  133. int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
  134. int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
  135. int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
  136. int width = (int) dp2px(CIRCLE_DIAMETER);
  137. int height = (int) dp2px(CIRCLE_DIAMETER);
  138. if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {
  139. setMeasuredDimension(width, height);
  140. } else if (widthSpecMode == MeasureSpec.AT_MOST) {
  141. setMeasuredDimension(width, heightSpecSize);
  142. } else if (heightSpecMode == MeasureSpec.AT_MOST) {
  143. setMeasuredDimension(widthSpecSize, height);
  144. }
  145. }
  146.  
  147. @Override
  148. protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  149. super.onSizeChanged(w, h, oldw, oldh);
  150. final Ring ring = mRing;
  151. ring.setInsets(w, h);
  152. bounds.set(0, 0, w, h);
  153. }
  154.  
  155. private void buildAnimator() {
  156. final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f).setDuration(ANIMATOR_DURATION);
  157. valueAnimator.setRepeatCount(-1);
  158. valueAnimator.setInterpolator(new LinearInterpolator());
  159. valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  160. @Override
  161. public void onAnimationUpdate(ValueAnimator animation) {
  162. mRotation = (float) valueAnimator.getAnimatedValue();
  163. invalidate();
  164. }
  165. });
  166. animator = valueAnimator;
  167. animatorSet = buildFlexibleAnimation();
  168. animatorSet.addListener(animatorListener);
  169. }
  170.  
  171. @Override
  172. protected void onDraw(Canvas canvas) {
  173. if (!mIsAnimatorCancel) {
  174. final Rect bounds = getBounds();
  175. final int saveCount = canvas.save();
  176. canvas.rotate(mRotation * 360, bounds.exactCenterX(), bounds.exactCenterY());
  177. drawRing(canvas, bounds);
  178. canvas.restoreToCount(saveCount);
  179. } else {
  180. canvas.restore();
  181. }
  182. }
  183.  
  184. /**
  185. * draw the ring
  186. *
  187. * @param canvas to draw the Ring
  188. * @param bounds the ring's rect
  189. */
  190. private void drawRing(Canvas canvas, Rect bounds) {
  191. final RectF arcBounds = mTempBounds;
  192. final Ring ring = mRing;
  193. arcBounds.set(bounds);
  194. arcBounds.inset(ring.strokeInset, ring.strokeInset);
  195. canvas.drawArc(arcBounds, ring.start, ring.sweep, false, mPaint);
  196. }
  197.  
  198. public void start() {
  199. if (mAnimationStarted) {
  200. return;
  201. }
  202.  
  203. if (animator == null || animatorSet == null) {
  204. mRing.reset();
  205. buildAnimator();
  206. }
  207.  
  208. animator.start();
  209. animatorSet.start();
  210. mAnimationStarted = true;
  211. mIsAnimatorCancel = false;
  212. }
  213.  
  214.  
  215. public void stop() {
  216. mIsAnimatorCancel = true;
  217. if (animator != null) {
  218. animator.end();
  219. animator.cancel();
  220. }
  221. if (animatorSet != null) {
  222.  
  223. animatorSet.end();
  224. animatorSet.cancel();
  225. }
  226. animator = null;
  227. animatorSet = null;
  228.  
  229. mAnimationStarted = false;
  230. mRing.reset();
  231. mRotation = 0;
  232. invalidate();
  233. }
  234.  
  235. public Rect getBounds() {
  236. return bounds;
  237. }
  238.  
  239. public void setBounds(Rect bounds) {
  240. this.bounds = bounds;
  241. }
  242.  
  243. /**
  244. * build FlexibleAnimation to control the progress
  245. *
  246. * @return Animatorset for control the progress
  247. */
  248. private AnimatorSet buildFlexibleAnimation() {
  249. final Ring ring = mRing;
  250. AnimatorSet set = new AnimatorSet();
  251. ValueAnimator increment = ValueAnimator.ofFloat(0, MAX_PROGRESS_ARC - MIN_PROGRESS_ARC).setDuration(ANIMATOR_DURATION / 2);
  252. increment.setInterpolator(new LinearInterpolator());
  253. increment.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  254. @Override
  255. public void onAnimationUpdate(ValueAnimator animation) {
  256. float sweeping = ring.sweeping;
  257. final float value = (float) animation.getAnimatedValue();
  258. ring.sweep = sweeping + value;
  259. invalidate();
  260. }
  261. });
  262. increment.addListener(animatorListener);
  263. ValueAnimator reduce = ValueAnimator.ofFloat(0, MAX_PROGRESS_ARC - MIN_PROGRESS_ARC).setDuration(ANIMATOR_DURATION / 2);
  264. reduce.setInterpolator(interpolator);
  265. reduce.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
  266. @Override
  267. public void onAnimationUpdate(ValueAnimator animation) {
  268. float sweeping = ring.sweeping;
  269. float starting = ring.starting;
  270. float value = (float) animation.getAnimatedValue();
  271. ring.sweep = sweeping - value;
  272. ring.start = starting + value;
  273. }
  274. });
  275. set.play(reduce).after(increment);
  276. return set;
  277. }
  278.  
  279.  
  280. public void setColor(int color) {
  281. mRing.color = color;
  282. mPaint.setColor(color);
  283. }
  284.  
  285. public int getColor() {
  286. return mRing.color;
  287. }
  288.  
  289. @Override
  290. protected void onAttachedToWindow() {
  291. super.onAttachedToWindow();
  292. start();
  293. }
  294.  
  295. @Override
  296. protected void onDetachedFromWindow() {
  297. super.onDetachedFromWindow();
  298. stop();
  299. }
  300.  
  301. @Override
  302. protected void onVisibilityChanged(View changedView, int visibility) {
  303. super.onVisibilityChanged(changedView, visibility);
  304. if (visibility == VISIBLE) {
  305. start();
  306. } else {
  307. stop();
  308. }
  309. }
  310.  
  311. /**
  312. * turn dp to px
  313. *
  314. * @param dp value
  315. * @return result px value
  316. */
  317. private float dp2px(float dp) {
  318. return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
  319. }
  320.  
  321.  
  322. @Override
  323. protected Parcelable onSaveInstanceState() {
  324. Parcelable parcelable = super.onSaveInstanceState();
  325. SavedState state = new SavedState(parcelable);
  326. state.ring = mRing;
  327. return state;
  328. }
  329.  
  330. @Override
  331. protected void onRestoreInstanceState(Parcelable state) {
  332. SavedState savedState = (SavedState) state;
  333. super.onRestoreInstanceState(state);
  334. mRing = savedState.ring;
  335. }
  336.  
  337. static class Ring implements Parcelable {
  338.  
  339.  
  340. public float strokeInset = 0f;
  341. public float strokeWidth = 0f;
  342. public float ringCenterRadius = 0f;
  343. public float start = 0f;
  344. public float end = 0f;
  345. public float sweep = 0f;
  346. public float sweeping = MIN_PROGRESS_ARC;
  347.  
  348. public float starting = 0f;
  349. public float ending = 0f;
  350. public int color;
  351.  
  352.  
  353. public void restore() {
  354. starting = start;
  355. sweeping = sweep;
  356. ending = end;
  357. }
  358.  
  359. public void reset() {
  360. end = 0f;
  361. start = 0f;
  362. sweeping = MIN_PROGRESS_ARC;
  363. sweep = 0f;
  364. starting = 0f;
  365. }
  366.  
  367. public void setInsets(int width, int height) {
  368. final float minEdge = (float) Math.min(width, height);
  369. float insets;
  370. if (ringCenterRadius <= 0 || minEdge < 0) {
  371. insets = (float) Math.ceil(strokeWidth / 2.0f);
  372. } else {
  373. insets = (minEdge / 2.0f - ringCenterRadius);
  374. }
  375.  
  376.  
  377. strokeInset = insets;
  378. }
  379.  
  380. @Override
  381. public int describeContents() {
  382. return 0;
  383. }
  384.  
  385. @Override
  386. public void writeToParcel(Parcel dest, int flags) {
  387. dest.writeFloat(this.strokeInset);
  388. dest.writeFloat(this.strokeWidth);
  389. dest.writeFloat(this.ringCenterRadius);
  390. dest.writeFloat(this.start);
  391. dest.writeFloat(this.end);
  392. dest.writeFloat(this.sweep);
  393. dest.writeFloat(this.sweeping);
  394. dest.writeFloat(this.starting);
  395. dest.writeFloat(this.ending);
  396. dest.writeInt(this.color);
  397. }
  398.  
  399. public Ring() {
  400. }
  401.  
  402. protected Ring(Parcel in) {
  403. this.strokeInset = in.readFloat();
  404. this.strokeWidth = in.readFloat();
  405. this.ringCenterRadius = in.readFloat();
  406. this.start = in.readFloat();
  407. this.end = in.readFloat();
  408. this.sweep = in.readFloat();
  409. this.sweeping = in.readFloat();
  410. this.starting = in.readFloat();
  411. this.ending = in.readFloat();
  412. this.color = in.readInt();
  413. }
  414.  
  415. public static final Parcelable.Creator<Ring> CREATOR = new Parcelable.Creator<Ring>() {
  416. @Override
  417. public Ring createFromParcel(Parcel source) {
  418. return new Ring(source);
  419. }
  420.  
  421. @Override
  422. public Ring[] newArray(int size) {
  423. return new Ring[size];
  424. }
  425. };
  426. }
  427.  
  428. /**
  429. *
  430. */
  431. static class SavedState extends BaseSavedState {
  432. public Ring ring;
  433.  
  434.  
  435. public SavedState(Parcelable superState) {
  436. super(superState);
  437. }
  438.  
  439. private SavedState(Parcel in) {
  440. super(in);
  441. ring = in.readParcelable(Ring.class.getClassLoader());
  442. }
  443.  
  444. @Override
  445. public void writeToParcel(Parcel dest, int flags) {
  446. super.writeToParcel(dest, flags);
  447. dest.writeParcelable(this.ring, flags);
  448. }
  449.  
  450.  
  451. public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
  452. @Override
  453. public SavedState createFromParcel(Parcel source) {
  454. return new SavedState(source);
  455. }
  456.  
  457. @Override
  458. public SavedState[] newArray(int size) {
  459. return new SavedState[size];
  460. }
  461. };
  462. }
  463.  
  464. /**
  465. * Listen the animatorSet and the IncrementAnimator;
  466. */
  467. Animator.AnimatorListener animatorListener = new Animator.AnimatorListener() {
  468.  
  469. @Override
  470. public void onAnimationStart(Animator animation) {
  471.  
  472. }
  473.  
  474. @Override
  475. public void onAnimationEnd(Animator animation) {
  476. if (mIsAnimatorCancel) return;
  477. if (animation instanceof ValueAnimator) {
  478. mRing.sweeping = mRing.sweep;
  479. } else if (animation instanceof AnimatorSet) {
  480. mRing.restore();
  481. animatorSet.start();
  482. }
  483. }
  484.  
  485. @Override
  486. public void onAnimationCancel(Animator animation) {
  487.  
  488. }
  489.  
  490. @Override
  491. public void onAnimationRepeat(Animator animation) {
  492.  
  493. }
  494. };
  495. }
Add Comment
Please, Sign In to add comment