Android 九宫格抽奖

来源:互联网 发布:threadfactory vb 编辑:程序博客网 时间:2024/05/21 09:10

思路: 在开始绘制九宫格之前,我们先重写onMeasure方法,主要是为了让九宫格成为一个正方形,
SurfaceView一般不是通过重写onDraw方法来绘制控件的,那么怎么获取到Canvas呢?主要是通过SurfaceHolder监听Callback事件来获取的 ,有了对象SurfaceHolder对象,我们就可以获取到Canvas对象了,下面开始真正的绘制工作。

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

主要核心技术:
SurfaceView,SurfaceHolder

OK,有了基本步骤,接下来就是根据步骤一步一步来进行了。 代码如下

<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.example.myapplication.MainActivity">    <com.example.myapplication.LotteryView        android:id="@+id/nl"        android:layout_width="368dp"        android:layout_height="495dp"        tools:layout_editor_absoluteY="8dp"        tools:layout_editor_absoluteX="8dp" /></android.support.constraint.ConstraintLayout>
package com.example.myapplication;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.widget.Toast;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        LotteryView nl;        setContentView(R.layout.activity_main);        nl = (LotteryView) findViewById(R.id.nl);        int[] prizesIcon = {R.drawable.navicon_a, R.drawable.navicon_b, R.drawable.navicon_c, R.drawable.navicon_d,                R.drawable.navicon_e, R.drawable.navicon_a, R.drawable.navicon_d, R.drawable.navicon_b, R.drawable.navicon_e};        final List<Prize> prizes = new ArrayList<Prize>();        for (int x = 0; x < 9; x++) {            Prize lottery = new Prize();            lottery.setId(x + 1);            lottery.setName("Lottery" + (x + 1));            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), prizesIcon[x]);            lottery.setIcon(bitmap);            if ((x + 1) % 2 == 0) {                lottery.setBgColor(0xff4fccee);            } else if (x == 4) {                lottery.setBgColor(0xffffffff);            } else {                lottery.setBgColor(0xff00ff34);            }            prizes.add(lottery);        }        nl.setPrizes(prizes);        nl.setOnTransferWinningListener(new LotteryView.OnTransferWinningListener() {            @Override            public void onWinning(int position) {                Toast.makeText(getApplicationContext(), prizes.get(position).getName(), Toast.LENGTH_SHORT).show();            }        });    }}
package com.example.myapplication;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Point;import android.graphics.PorterDuff.Mode;import android.graphics.Rect;import android.os.SystemClock;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.SurfaceHolder;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;import java.util.List;import java.util.Random;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;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,getMeasuredWidth())){                    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 current,int len){        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 click() {                    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);    }}
package com.example.myapplication;import android.graphics.Bitmap;import android.graphics.Point;import android.graphics.Rect;/** * Created by Cr on 2017/9/18. * 奖品的属性 */ class Prize  {    int Id;    String Name;    Bitmap Icon;    int BgColor;    Rect rect;    public OnClickListener getListener() {        return listener;    }    public void setListener(OnClickListener listener) {        this.listener = listener;    }    OnClickListener listener;    public Rect getRect() {        return rect;    }    public void setRect(Rect rect) {        this.rect = rect;    }    public int getId() {        return Id;    }    public void setId(int id) {        Id = id;    }    public String getName() {        return Name;    }    public void setName(String name) {        Name = name;    }    public Bitmap getIcon() {        return Icon;    }    public void setIcon(Bitmap icon) {        Icon = icon;    }    public int getBgColor() {        return BgColor;    }    public void setBgColor(int bgColor) {        BgColor = bgColor;    }   public  interface OnClickListener{        void click();    }    public void click(){        listener.click();    }    public boolean isClick (Point touchPoint,int width){       if (touchPoint.x < width/3*2&touchPoint.x > width/3&touchPoint.y < width/3*2&touchPoint.y > width/3){           return true;       }else{           return false;       }    }}