/* * 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); //参数为几等奖