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

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

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

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;

}

}

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 多点循环缩放

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

以上是 Android自定义控件之三点循环缩放效果 的全部内容, 来源链接: utcz.com/p/241224.html

回到顶部