Android 九宫格抽奖

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

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

主要核心技术:
SurfaceView,SurfaceHolder

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


<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 prizes = new ArrayList();
        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 Listprizes;
    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(Listprizes){
        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;xint 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;xint 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+1return ++current;
        }

        if((current+1)%len==0¤t1){
            return current+=len;
        }

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

        if(currentreturn --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;
       }
    }
}

你可能感兴趣的:(Android,技术)