zoukankan      html  css  js  c++  java
  • Android实现抽奖转盘

    一、SurfaceView认识及的应用的思路

    • SurfaceView继承自(extends)View,View是在UI线程中进行绘制;
    • 而SurfaceView是在一个子线程中对自己进行绘制,优势:避免造成UI线程阻塞;
    • SurfaceView中包含一个专门用于绘制的Surface,Surface中包含一个Canvas;
    • 获得Canvas:可以从SurfaceView中方法的getHolder()获得SurfaceHolder,从holder获得Canvas;
    • holder还管理着SurfaceView的生命周期

             ①surfaceCreated()创建子线程,子线程的run()方法中开启SurfaceView的绘制。

             ②surfaceChanged()

               surfaceDestoryed()中关闭子线程。

    二、SurfaceView的一般写法

     1 package com.example.luckypan;
     2 
     3 import android.content.Context;
     4 import android.graphics.Canvas;
     5 import android.util.AttributeSet;
     6 import android.view.SurfaceHolder;
     7 import android.view.SurfaceHolder.Callback;
     8 import android.view.SurfaceView;
     9 
    10 public class SurfaceViewTemplate extends SurfaceView implements Callback, Runnable {
    11 
    12     private SurfaceHolder mHolder;
    13     private Canvas mCanvas;
    14     /**
    15      * 用于绘制线程
    16      */
    17     private Thread thread;
    18     /**
    19      * 线程的控制开关
    20      */
    21     private boolean isRunning;
    22     public SurfaceViewTemplate(Context context) {
    23         this(context, null);
    24     }
    25     public SurfaceViewTemplate(Context context, AttributeSet attrs) {
    26         super(context, attrs);
    27         mHolder=getHolder();
    28         mHolder.addCallback(this);
    29         //可获得焦点
    30         setFocusable(true);
    31         setFocusableInTouchMode(true);
    32         //设置常量
    33         setKeepScreenOn(true);
    34     }
    35     public void surfaceCreated(SurfaceHolder holder) {
    36         isRunning=true;
    37         thread=new Thread(this);
    38         thread.start();
    39         
    40     }
    41     public void surfaceChanged(SurfaceHolder holder, int format, int width,
    42             int height) {
    43         // TODO Auto-generated method stub
    44         
    45     }
    46     public void surfaceDestroyed(SurfaceHolder holder) {
    47         isRunning=false;
    48         
    49     }
    50     public void run() {
    51         //不断进行绘制
    52         while (isRunning)
    53         {
    54             draw();
    55         }
    56     }
    57     private void draw() {
    58         try {
    59             mCanvas=mHolder.lockCanvas();
    60             if (mCanvas!=null) {
    61                 //
    62             }
    63         }
    64         catch (Exception e) {
    65         
    66         }
    67         finally
    68         {
    69             if (mCanvas!=null) {
    70                 mHolder.unlockCanvasAndPost(mCanvas);
    71             }
    72         }
    73     }
    74 
    75 
    76 }
    SurfaceViewTemplate

    三、代码编写

    • 绘制抽奖转盘的盘快
    1.         绘制背景:drawBg(), Canvas的两个方法:drawColor(color the color to draw onto the canvas),这里我设置背景色为白色0xFFFFFFFF、drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint),这个bitmap是背景图片,背景是一个矩形new Rect(),其他参数设置为null。
      1. 1 private void drawBg() {
        2         mCanvas.drawColor(0xFFFFFFFF);
        3         mCanvas.drawBitmap(mBgBitmap, null, new Rect(mPadding/2, mPadding/2, getMeasuredWidth()-mPadding/2, getMeasuredHeight()-mPadding/2), null);
        4     }
        drawBg
    2. 绘制盘快:
    1 //绘制盘快
    2                 float tmpAngle=mStartAngle;
    3                 float sweepAngle=360/mItemCount;
    4                 for (int i = 0; i < mItemCount; i++) {
    5                     mArcPaint.setColor(mColor[i]);
    6                     //绘制盘快
    7                     mCanvas.drawArc(mRange, tmpAngle, sweepAngle,true, mArcPaint);
    View Code
    • 绘制抽奖转盘的奖项文字
     1 /**
     2      * 绘制每个盘快的文本
     3      * @param tmpAngle
     4      * @param sweepAngle
     5      * @param string
     6      */
     7     private void drawText(float tmpAngle, float sweepAngle, String string) {
     8         Path path=new Path();
     9         path.addArc(mRange, tmpAngle, sweepAngle);
    10         //利用水平偏移量让文字居中
    11         float textWidth=mTextPaint.measureText(string);
    12         int hOffset=(int) (mRadius*Math.PI/mItemCount/2-textWidth/2);
    13         int vOffset=mRadius/2/6;//垂直偏移量
    14         mCanvas.drawTextOnPath(string, path, hOffset, vOffset, mTextPaint);
    15     }
    drawText
    • 绘制抽奖转盘的图片
     1 /**
     2      * 绘制图片
     3      * @param tmpAngle
     4      * @param bitmap
     5      */
     6     private void drawIcon(float tmpAngle, Bitmap bitmap) {
     7         //设置图片的宽度为直径的1/8
     8         int imgWidth=mRadius/8;
     9         float angle=(float) ((tmpAngle+360/mItemCount/2)*Math.PI/180);
    10         int x=(int) (mCenter+mRadius/2/2*Math.cos(angle));
    11         int y=(int) (mCenter+mRadius/2/2*Math.sin(angle));
    12         //确定图片位置
    13         Rect rect=new Rect(x-imgWidth/2, y-imgWidth/2, x+imgWidth/2, y+imgWidth/2);
    14         mCanvas.drawBitmap(bitmap, null, rect,null);
    15     }
    drawIcon
    • 转盘滚动及设置停止的指向
     1 private void draw() {
     2         try {
     3             mCanvas=mHolder.lockCanvas();
     4             if (mCanvas!=null) {
     5                 //绘制背景
     6                 drawBg();
     7                 //绘制盘快
     8                 float tmpAngle=mStartAngle;
     9                 float sweepAngle=360/mItemCount;
    10                 for (int i = 0; i < mItemCount; i++) {
    11                     mArcPaint.setColor(mColor[i]);
    12                     //绘制盘快
    13                     mCanvas.drawArc(mRange, tmpAngle, sweepAngle,true, mArcPaint);
    14                     //绘制文本
    15                     drawText(tmpAngle,sweepAngle,mStrings[i]);
    16                     //绘制图片
    17                     drawIcon(tmpAngle,mImagBitmaps[i]);
    18                     tmpAngle+=sweepAngle;
    19                 }
    20                 mStartAngle+=mSpeed;
    21                 //判断是否点击停止按钮
    22                 if (isShouldEnd) {
    23                     mSpeed-=1;
    24                 }
    25                 if (mSpeed<=0)
    26                 {
    27                     mSpeed=0;
    28                     isShouldEnd=false;
    29                 }
    30             }
    31         }
    32         catch (Exception e) {
    33         
    34         }
    35         finally
    36         {
    37             if (mCanvas!=null) {
    38                 mHolder.unlockCanvasAndPost(mCanvas);
    39             }
    40         }
    41     }
    draw

    四、抽奖转盘的秘密

     1 /**
     2      * 电机启动旋转
     3      * 控制指定盘快停止范围
     4      * @param index
     5      */
     6     public void luckyStart(int index)
     7     {
     8         //计算每一项的角度
     9         float angle=360/mItemCount;
    10         //计算每一项的中奖范围
    11         //1->150~210
    12         //0->210~270
    13         float from=270-(index+1)*angle;
    14         float end=from+angle;
    15     //        设置停下来需要旋转的距离
    16         float targetFrom=4*360+from;
    17         float targetEnd=4*360+end;
    18         /**
    19          * <pre>
    20          * v1->0 且每次-1
    21          * (v1+0)*(v1+1)/2=targetFrom 等差数列求和公式;
    22          * v1*v1+v1-2*targetFrom=0;
    23          * v1=(-1+Math.sqrt(1+8*targetFrom))/2 一元二次方程求根公式
    24          * </pre>
    25          */
    26         float v1=(float) ((-1+Math.sqrt(1+8*targetFrom))/2);
    27         float v2=(float) ((-1+Math.sqrt(1+8*targetEnd))/2);
    28         mSpeed=v1+Math.random()*(v2-v1);
    29 //        mSpeed=v2;
    30         isShouldEnd=false;
    31     }
    luckyStart
  • 相关阅读:
    uva 11294 Wedding
    uvalive 4452 The Ministers’ Major Mess
    uvalive 3211 Now Or Later
    uvalive 3713 Astronauts
    uvalive 4288 Cat Vs. Dog
    uvalive 3276 The Great Wall Game
    uva 1411 Ants
    uva 11383 Golden Tiger Claw
    uva 11419 SAM I AM
    uvalive 3415 Guardian Of Decency
  • 原文地址:https://www.cnblogs.com/wucaiyun1/p/4923444.html
Copyright © 2011-2022 走看看