一、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的一般写法

 package com.example.luckypan;

 import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView; public class SurfaceViewTemplate extends SurfaceView implements Callback, Runnable { private SurfaceHolder mHolder;
private Canvas mCanvas;
/**
* 用于绘制线程
*/
private Thread thread;
/**
* 线程的控制开关
*/
private boolean isRunning;
public SurfaceViewTemplate(Context context) {
this(context, null);
}
public SurfaceViewTemplate(Context context, AttributeSet attrs) {
super(context, attrs);
mHolder=getHolder();
mHolder.addCallback(this);
//可获得焦点
setFocusable(true);
setFocusableInTouchMode(true);
//设置常量
setKeepScreenOn(true);
}
public void surfaceCreated(SurfaceHolder holder) {
isRunning=true;
thread=new Thread(this);
thread.start(); }
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub }
public void surfaceDestroyed(SurfaceHolder holder) {
isRunning=false; }
public void run() {
//不断进行绘制
while (isRunning)
{
draw();
}
}
private void draw() {
try {
mCanvas=mHolder.lockCanvas();
if (mCanvas!=null) {
//
}
}
catch (Exception e) { }
finally
{
if (mCanvas!=null) {
mHolder.unlockCanvasAndPost(mCanvas);
}
}
} }

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.  private void drawBg() {
      mCanvas.drawColor(0xFFFFFFFF);
      mCanvas.drawBitmap(mBgBitmap, null, new Rect(mPadding/2, mPadding/2, getMeasuredWidth()-mPadding/2, getMeasuredHeight()-mPadding/2), null);
      }

      drawBg

  2. 绘制盘快:
 //绘制盘快
float tmpAngle=mStartAngle;
float sweepAngle=360/mItemCount;
for (int i = 0; i < mItemCount; i++) {
mArcPaint.setColor(mColor[i]);
//绘制盘快
mCanvas.drawArc(mRange, tmpAngle, sweepAngle,true, mArcPaint);
  • 绘制抽奖转盘的奖项文字
 /**
* 绘制每个盘快的文本
* @param tmpAngle
* @param sweepAngle
* @param string
*/
private void drawText(float tmpAngle, float sweepAngle, String string) {
Path path=new Path();
path.addArc(mRange, tmpAngle, sweepAngle);
//利用水平偏移量让文字居中
float textWidth=mTextPaint.measureText(string);
int hOffset=(int) (mRadius*Math.PI/mItemCount/2-textWidth/2);
int vOffset=mRadius/2/6;//垂直偏移量
mCanvas.drawTextOnPath(string, path, hOffset, vOffset, mTextPaint);
}

drawText

  • 绘制抽奖转盘的图片
 /**
* 绘制图片
* @param tmpAngle
* @param bitmap
*/
private void drawIcon(float tmpAngle, Bitmap bitmap) {
//设置图片的宽度为直径的1/8
int imgWidth=mRadius/8;
float angle=(float) ((tmpAngle+360/mItemCount/2)*Math.PI/180);
int x=(int) (mCenter+mRadius/2/2*Math.cos(angle));
int y=(int) (mCenter+mRadius/2/2*Math.sin(angle));
//确定图片位置
Rect rect=new Rect(x-imgWidth/2, y-imgWidth/2, x+imgWidth/2, y+imgWidth/2);
mCanvas.drawBitmap(bitmap, null, rect,null);
}

drawIcon

  • 转盘滚动及设置停止的指向
 private void draw() {
try {
mCanvas=mHolder.lockCanvas();
if (mCanvas!=null) {
//绘制背景
drawBg();
//绘制盘快
float tmpAngle=mStartAngle;
float sweepAngle=360/mItemCount;
for (int i = 0; i < mItemCount; i++) {
mArcPaint.setColor(mColor[i]);
//绘制盘快
mCanvas.drawArc(mRange, tmpAngle, sweepAngle,true, mArcPaint);
//绘制文本
drawText(tmpAngle,sweepAngle,mStrings[i]);
//绘制图片
drawIcon(tmpAngle,mImagBitmaps[i]);
tmpAngle+=sweepAngle;
}
mStartAngle+=mSpeed;
//判断是否点击停止按钮
if (isShouldEnd) {
mSpeed-=1;
}
if (mSpeed<=0)
{
mSpeed=0;
isShouldEnd=false;
}
}
}
catch (Exception e) { }
finally
{
if (mCanvas!=null) {
mHolder.unlockCanvasAndPost(mCanvas);
}
}
}

draw

四、抽奖转盘的秘密

 /**
* 电机启动旋转
* 控制指定盘快停止范围
* @param index
*/
public void luckyStart(int index)
{
//计算每一项的角度
float angle=360/mItemCount;
//计算每一项的中奖范围
//1->150~210
//0->210~270
float from=270-(index+1)*angle;
float end=from+angle;
// 设置停下来需要旋转的距离
float targetFrom=4*360+from;
float targetEnd=4*360+end;
/**
* <pre>
* v1->0 且每次-1
* (v1+0)*(v1+1)/2=targetFrom 等差数列求和公式;
* v1*v1+v1-2*targetFrom=0;
* v1=(-1+Math.sqrt(1+8*targetFrom))/2 一元二次方程求根公式
* </pre>
*/
float v1=(float) ((-1+Math.sqrt(1+8*targetFrom))/2);
float v2=(float) ((-1+Math.sqrt(1+8*targetEnd))/2);
mSpeed=v1+Math.random()*(v2-v1);
// mSpeed=v2;
isShouldEnd=false;
}

luckyStart

Android实现抽奖转盘的更多相关文章

  1. android仿漫画源码、抽奖转盘、Google相册、动画源码等

    Android精选源码 android实现仿今日头条的开源项目 波浪效果,实现流量的动态显示 美妆领域的app, 集成了摄像头取色, 朋友圈, 滤镜等 android仿漫画源码 android一个视差 ...

  2. jquery实现抽奖转盘

    用jquery通过配置参数实现抽奖转盘 1.html代码 <!DOCTYPE html> <html lang="zh-CN"> <head> ...

  3. JS:九宫格抽奖转盘实例

    工作需要,所以做了个抽奖转盘的插件,当然这里只做最简单的演示.可以用于取代一些flash抽奖程序. 机制说明: 1.通过定义lottery-unit来控制节点的个数及索引: 2.通过设置lottery ...

  4. Html5-Canvas实现简易的抽奖转盘

    ###Html5实现抽奖转盘效果 1.实现的基本效果 2.主要的内容 html5中canvas标签的使用 jQueryRotate.js旋转插件 3.主要html代码 <body> < ...

  5. 使用CSS3+jquery.js 实现微信抽奖转盘效果

    上次发表了一篇 微信抽奖转盘活动-效果源码分析 最近想起了刚接到这个项目时第一时间脑海里迸出的解决方法 “CSS3”! 为什么不能用CSS3来实现呢? 所以我打算用CSS3来实现这个效果.并不需要依赖 ...

  6. 抽奖转盘(jqueryrotate.js)

    jqueryrotate.js抽奖转盘,使用方便,兼容各浏览器,效果如下图 <!DOCTYPE> <head> <meta http-equiv="Conten ...

  7. 利用java实现抽奖转盘(着重安全控制)

    本文是针对jquery 实现抽奖转盘作者的一个补充(主要用java去实现转盘结果生成及存储,解决jquery 做法 非法用户采用模拟器实现改变转盘值的风险性),针对jQuery的具体实现,请看案例:h ...

  8. 用CSS实现一个抽奖转盘

    效果 基本是用CSS实现的,没有用图片,加一丢丢JS.完全没有考虑兼容性. 首先画一个转盘, <!DOCTYPE html> <html lang="en"> ...

  9. css 如何“画”一个抽奖转盘

    主要描述的是如何运用 css 绘制一个抽奖转盘,并运用原生 js 实现转盘抽奖效果. 先来张效果图: 布局 一般来说,转盘一般有四个部分组成:外层闪烁的灯.内层旋转的圆盘.圆盘上的中奖结果.指针. 所 ...

随机推荐

  1. Thread Pool Engine, and Work-Stealing scheduling algorithm

    http://pages.videotron.com/aminer/threadpool.htm http://pages.videotron.com/aminer/zip/threadpool.zi ...

  2. PostgreSQL的AnynonArray的例子

    程序: CREATE OR REPLACE FUNCTION kappend(anynonarray, anyelement) RETURNS text AS $$ ; $$ LANGUAGE SQL ...

  3. UVA 1108 - Mining Your Own Business

    刘汝佳书上都给出了完整的代码 在这里理一下思路: 由题意知肯定存在一个或者多个双连通分量: 假设某一个双连通分量有割顶.那太平井一定不能打在割顶上. 而是选择割顶之外的随意一个点: 假设没有割顶,则要 ...

  4. CSS定位规则之BFC 你居然一直不知道的东西!!!!!

    相关文档: http://blog.sina.com.cn/s/blog_877284510101jo5d.html http://www.cnblogs.com/dojo-lzz/p/3999013 ...

  5. 即时通信(RPC)的Rtmp实现--代码实现篇

    实现的一般步骤是: step 1: 定义NetConnection对象连接rtmp,并监听NetStatusEvent.NET_STATUS事件 step 2: 在NetStatusEvent.NET ...

  6. 创建透明的UIToolbar

    TranslucentToolbar.h文件 #import <UIKit/UIKit.h> @interface TranslucentToolbar : UIToolbar @end ...

  7. JRebel_修改class后无法正确调试问题解决【2014-03-12】

    原文地址:http://www.cnblogs.com/hbbbs/p/3596179.html 现象 修改了class,编译后,JRebel自动装载到Web容器中.但此时调试这个类会发现无法正常调试 ...

  8. Action 和 Func

    C# 中的两个动态委托类型 也就是说我们不用在使用委托的时候就去声明一个委托对象,而是通过Action和Func就可以模拟出我们自己要用到的委托 区别: Action 表示没有返回值的委托  例如:A ...

  9. EF 预热

    由于EF第一次加载比较慢,所以要对EF进行一次初始化的加载,类似第一次打开网页很慢,但第二次打开都很快了的原理一样:第一次把所有静态的图片和JS缓存到本地了:当第二次打开的时候都不需要再去下载这些东西 ...

  10. PEAR:使用PHPDoc轻松建立你的PEAR文档

    对于一个开发人员,文档总是最感到头疼的事情之一.而且,很可能你对待文档会采取截然不同的2种态度: 当你使用别人的代码库的时候,最希望得到的是它的技术文档,尤其是当时间很紧,而你又不得不硬着头皮去读那些 ...