Android打造流畅九宫格抽奖

因为company项目中需要做九宫格抽奖活动,以前都没有做过类似的功能,虽然之前在浏览大神们的博客中,无意中也看到了好多关于抽奖的项目,但因为项目中没有需要,一直都没有点击进去看。这次不去看估计不行。直到公司计划要做抽奖功能,才迫不得已上网查找demo


网上找了大半天,好不容易找到了几个demo,下载下来,解压缩包发现竟然里面空空如也,只有几张九宫格的图片,害我白白浪费了几个CSDN积分。后面在eoe网站那发现了一个demo,于是好开心,下载下来后马上导入到工程中,运行看了效果,九宫格是出来了,但效果真不敢恭维,主要是运行不流畅。但我还是进去稍微看了一下demo,基本思路是这样的:定义好九宫格界面,然后开启子线程不断循环修改状态,再通过handler发送消息到主线程中修改界面(子线程不能直接修改界面)。


这个demo虽然功能上实现了,但不是我想要的效果,因为我这一关都不能通过,到了产品那边更加不用说了。那怎么办呢?


于是我想到了一个控件,叫做SurfaceView,做游戏开发的同志们,应该对这个控件不陌生吧?首先介绍一下这个控件:
1.SurfaceView继承于View,多用于游戏开发中
2.可以直接在子线程中运行(其他UI控件都必须在主线程中运行的)。
3.一般的UI控件自定义时都是重写onDraw方法,但在SurfaceView中是通过SurfaceHolder获取Canvas来绘制图形的

这样,下面我开始根据我的想法,把自定义九宫格的步骤说一下。

步骤:

1.计算各位方块的位置
2.绘制每个奖品的方块(主要让界面更加好看)
3.绘制奖品图
4.计算旋转方块的下一步位置
5.绘制旋转方块
6.监听点击开始按钮事件

主要核心技术:
SurfaceView,SurfaceHolder


直接上代码

public class LotteryView extends SurfaceView implements Callback{

    /**
     * holder
     */
    private SurfaceHolder mHolder;


    private List<Prize>prizes;
    private boolean flags;

    private int lottery=6;   //设置中奖号码

    private int current=2;   //抽奖开始的位置

    private int count=0;   //旋转次数累计

    private int countDown;    //倒计次数,快速旋转完成后,需要倒计多少次循环才停止


    private int transfer= 0xffff0000;

    private int MAX=50;   //最大旋转次数

    private OnTransferWinningListener listener;

    public void setOnTransferWinningListener(OnTransferWinningListener listener){
        this.listener=listener;
    }

    public interface OnTransferWinningListener{
        /**
         * 中奖回调
         * @param position
         */
        void onWinning(int position);
    }


    /**
     * 设置中奖号码
     * @param lottery
     */
    public void setLottery(int lottery) {
        if(prizes!=null&&Math.round(prizes.size()/2)==0){
            throw new RuntimeException("开始抽奖按钮不能设置为中奖位置!");
        }
        this.lottery = lottery;
    }

    /**
     * 设置转盘颜色
     * @param transfer
     */
    public void setTransfer(int transfer) {
        this.transfer = transfer;
    }

    /**
     * 设置奖品集合
     * @param prizes
     */
    public void setPrizes(List<Prize>prizes){
        this.prizes=prizes;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        handleTouch(event);
        return super.onTouchEvent(event);
    }

    /**
     * 触摸
     * @param event
     */
    public void handleTouch(MotionEvent event) {


        Point touchPoint=new Point((int)event.getX()-getLeft(),(int)event.getY());
        switch(event.getAction()){
        case MotionEvent.ACTION_DOWN:
            Prize prize = prizes.get(Math.round(prizes.size())/2);
            if(prize.isClick(touchPoint)){
                if(!flags){
                    setStartFlags(true);
                    prize.click();
                }
            }
            break ;
        default:
            break ;
        }
    }
    private class SurfaceRunnable implements Runnable{
        @Override
        public void run() {
            while(flags){
                Canvas canvas=null;
                try {
                    canvas = mHolder.lockCanvas();

                    drawBg(canvas);

                    drawTransfer(canvas);

                    drawPrize(canvas);

                    controllerTransfer();
                } catch (Exception e) {
                    e.printStackTrace();
                }finally{
                    //涓轰簡璁╂瘡娆$粯鍒跺浘褰㈡椂鑳藉椤哄埄杩涜锛屾渶濂藉皢瑙i攣鏀惧埌寮傚父涓繘琛屽鐞嗭紝涔熷氨鏄锛屽鏋渃anvas涓嶄负绌猴紝閮藉皢鍏跺叧闂紝璁╀笅涓�娆″惊鐜兘澶熼『鍒╄繘琛岀粯鍒�
                    if(canvas!=null)
                        mHolder.unlockCanvasAndPost(canvas);    
                }
            }
        }
    }

    //绘制背景
    private void drawBg(Canvas canvas) {
        canvas.drawColor(Color.WHITE, Mode.CLEAR);
        int width = getMeasuredWidth()/3;
        int x1=0;
        int y1=0;

        int x2=0;
        int y2=0;

        int len = (int) Math.sqrt(prizes.size());

        for(int x=0;x<len*len;x++){

            Prize prize = prizes.get(x);

            int index=x;
            x1=getPaddingLeft()+width*(Math.abs(index)%len);
            y1=getPaddingTop()+width*(index/len);

            x2=x1+width;
            y2=y1+width;
            Rect rect=new Rect(x1,y1,x2,y2);

            Paint paint=new Paint();
            paint.setColor(prize.getBgColor());
            canvas.drawRect(rect, paint);
        }
    }

    //绘制旋转的方块
    private void drawTransfer(Canvas canvas) {
        int width = getMeasuredWidth()/3;
        int x1;
        int y1;

        int x2;
        int y2;
        int len = (int) Math.sqrt(prizes.size());
        current=next(current, len);
        x1=getPaddingLeft()+width*(Math.abs(current)%len);
        y1=getPaddingTop()+width*((current)/len);

        x2=x1+width;
        y2=y1+width;

        Rect rect=new Rect(x1,y1,x2,y2);
        Paint paint=new Paint();
        paint.setColor(transfer);
        canvas.drawRect(rect, paint);
    }

    //控制旋转
    private void controllerTransfer() {
        if(count>MAX){
            countDown++;
            SystemClock.sleep(count*5);
        }else{
            SystemClock.sleep(count*2);
        }

        count++;
        if(countDown>2){
            if(lottery==current){
                countDown=0;
                count=0;
                setStartFlags(false);

                if(listener!=null){
                    //切换到主线程中运行
                    post(new Runnable() {

                        @Override
                        public void run() {
                            listener.onWinning(current);
                        }
                    });

                }
            }
        }
    }

    public void setStartFlags(boolean flags){
        this.flags=flags;
    }

    //绘制奖品
    private void drawPrize(Canvas canvas) {
        int width = getMeasuredWidth()/3;
        int x1=0;
        int y1=0;

        int x2=0;
        int y2=0;

        int len = (int) Math.sqrt(prizes.size());

        for(int x=0;x<len*len;x++){

            Prize prize = prizes.get(x);

            int index=x;
            x1=getPaddingLeft()+width*(Math.abs(index)%len);
            y1=getPaddingTop()+width*(index/len);

            x2=x1+width;
            y2=y1+width;
            Rect rect=new Rect(x1+width/6,y1+width/6,x2-width/6,y2-width/6);
            prize.setRect(rect);
            canvas.drawBitmap(prize.getIcon(), null, rect, null);

        }
    }


    public void start() {
        setLottery(getRandom());
        ExecutorService service = Executors.newCachedThreadPool();
        service.execute(new SurfaceRunnable());
    }

    //获取随机中奖数,实际开发中一般中奖号码是服务器告诉我们的
    private int getRandom(){
        Random r=new Random();
        int nextInt =r.nextInt(prizes.size());
        if(nextInt%(Math.round(prizes.size()/2))==0){
            //随机号码等于中间开始位置,需要继续摇随机号
            return getRandom();
        }
        return nextInt;
    }

    //下一步
    public int next(int position,int len){
        int current=position;
        if(current+1<len){
            return ++current;
        }

        if((current+1)%len==0&&current<len*len-1){
            return current+=len;
        }

        if(current%len==0){
            return current-=len;
        }

        if(current<len*len){
            return --current;
        }

        return current;
    }


    public LotteryView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mHolder = this.getHolder();
        mHolder.addCallback(this);
    }

    public LotteryView(Context context) {
        this(context,null);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Canvas canvas=null;
        try {
            canvas = mHolder.lockCanvas();
            drawBg(canvas);
            drawPrize(canvas);

            Prize prize = prizes.get(Math.round(prizes.size()/2));
            prize.setListener(new Prize.OnClickListener() {

                @Override
                public void onClick() {
                    start();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(canvas!=null)
                mHolder.unlockCanvasAndPost(canvas);    
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        setStartFlags(false);
    }

    /** 
     * 重新测量
     */  
    @Override  
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)  
    {  
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
        int width = Math.min(getMeasuredWidth(), getMeasuredHeight());  
        setMeasuredDimension(width, width);  
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值