/*
* Copyright (C) 2014 Jason Fang ( ijasonfang@gmail.com )
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package fyc.framework.anim; import java.util.concurrent.TimeUnit; import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.CountDownTimer;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import fyc.framework.util.Flog;
import fyc.framework.util.RandomUtils; /**
* @author Jason Fang
* @datetime 2015年1月29日 下午7:19:36
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class Lottery {
static final boolean DEBUG = true; private static final int LOADING_UNIT_DEGREE = 360 * 5;
private static final int LOADING_DURATION = 720 * 5;
private static final long LOTTERY_TIME_OUT = TimeUnit.SECONDS.toMillis(5); private ImageView mImageView;
private ObjectAnimator mLoadingAnim;
private float mInitDegree = 0;
private int mMaxLevel = 10;
private int mUnitDegree;
private int[] mLevelMap;
private long mTimeout = LOTTERY_TIME_OUT; private boolean mIsLottering = false;
private boolean mIsInStop = false; private OnLotteryListener mListener;
private LotteryTimeOut mLotteryTimeOut; private Lottery(ImageView imageView, OnLotteryListener listener) {
mImageView = imageView;
mListener = listener;
} public static Lottery newInstance(ImageView imageView, OnLotteryListener listener) {
return new Lottery(imageView, listener);
} public Lottery setLevel(int level) {
mMaxLevel = level;
mUnitDegree = 360 / mMaxLevel;
return this;
} public Lottery setLevelMap(int[] levelMap) {
if (levelMap.length != mMaxLevel) {
throw new IllegalArgumentException("levelMap length must equal MaxLevel!");
}
mLevelMap = levelMap;
return this;
} public Lottery setTimeOut(int timeout) {
if (timeout <= 0) return this; mTimeout = TimeUnit.SECONDS.toMillis(timeout);
return this;
} public Lottery start() {
if (mIsLottering) return this;
mIsLottering = true; if (DEBUG) Flog.i("start"); loadingAnimStart(); if (mListener != null) {
mListener.onLotteryStart();
} mLotteryTimeOut = new LotteryTimeOut();
mLotteryTimeOut.start(); return this;
} public void stop(int level) {
if (mIsInStop) return;
mIsInStop = true; if (mLotteryTimeOut != null) {
mLotteryTimeOut.cancel();
} int levelAward = getLevelAward(level); if (mLoadingAnim != null && mLoadingAnim.isRunning()) {
mLoadingAnim.cancel();
} if (levelAward < 0 || levelAward > mMaxLevel) {
throw new IllegalArgumentException("level cannot below 0 or than MaxLevel!");
} float stopDegree = 0;
if (levelAward == 0) {
stopDegree = LOADING_UNIT_DEGREE - mUnitDegree / 2;
} else {
stopDegree = (LOADING_UNIT_DEGREE - mUnitDegree / 2) + RandomUtils.getRandom(mUnitDegree * levelAward + 5, mUnitDegree * (levelAward + 1) - 5);
} float startDegree = 0f;
if (mLoadingAnim != null) {
startDegree = (Float)mLoadingAnim.getAnimatedValue() % 360;
} else {
throw new RuntimeException("Must invoke start first!");
} long duration = (long)((stopDegree - startDegree) / ((LOADING_UNIT_DEGREE / (float)LOADING_DURATION))); stopAnimStart(startDegree, stopDegree, duration, levelAward); mInitDegree = stopDegree;
} int getLevelAward(int level) {
if (mLevelMap == null || mLevelMap.length == 0 || level == 0) return level;
return mLevelMap[level - 1];
} void loadingAnimStart() {
mLoadingAnim = ObjectAnimator.ofFloat(mImageView, "rotation", mInitDegree % 360, LOADING_UNIT_DEGREE);
mLoadingAnim.setInterpolator(new LinearInterpolator());
mLoadingAnim.setRepeatCount(ValueAnimator.INFINITE);
mLoadingAnim.setDuration(LOADING_DURATION);
mLoadingAnim.start();
} void stopAnimStart(float startDegree, float stopDegree, long duration, int levelAward) {
ObjectAnimator anim = ObjectAnimator.ofFloat(mImageView, "rotation", startDegree, stopDegree);
anim.setInterpolator(new DecelerateInterpolator());
anim.setDuration(duration * 2);
anim.addListener(new LotteryAnimatorListener(levelAward));
anim.start();
} class LotteryTimeOut extends CountDownTimer { public LotteryTimeOut() {
super(mTimeout, mTimeout);
} @Override
public void onTick(long millisUntilFinished) {
} @Override
public void onFinish() {
stop(0);
} } class LotteryAnimatorListener implements AnimatorListener { private int mLevel; public LotteryAnimatorListener() {
} public LotteryAnimatorListener(int level) {
mLevel = level;
} @Override
public void onAnimationStart(Animator animation) {
} @Override
public void onAnimationEnd(Animator animation) {
if (mListener != null) {
mListener.onLotteryStop(mLevel);
mIsLottering = false;
mIsInStop = false;
}
} @Override
public void onAnimationCancel(Animator animation) {
} @Override
public void onAnimationRepeat(Animator animation) {
} } public interface OnLotteryListener {
public void onLotteryStart();
public void onLotteryStop(int level);
}
}
如果要指针初始化指向圆盘的缝隙. 需要做简要的修改!
DEMO
mLottery = Lottery.newInstance(mWheel, new OnLotteryListener() { @Override
public void onLotteryStop(int level) {
Flog.i("onLotteryStop:" + level);
} @Override
public void onLotteryStart() {
Flog.i("onLotteryStart");
}
})
.setLevel(10) //总共几个奖
.setLevelMap(new int[]{5, 1, 1, 1, 1, 1, 1, 1, 1, 1}) //映射奖项
.setTimeOut(4);
获取到服务器端值之后调用
mLottery.stop(5); //参数为几等奖