今天分享一个抽奖的类Lottery

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

 

posted @ 2015-02-04 10:21  小草房Jason  阅读(1235)  评论(0编辑  收藏  举报