一、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. Python抓取页面中超链接(URL)的三中方法比较(HTMLParser、pyquery、正则表达式) <转>

    Python抓取页面中超链接(URL)的3中方法比较(HTMLParser.pyquery.正则表达式) HTMLParser版: #!/usr/bin/python # -*- coding: UT ...

  2. 解决ArcGIS Android Could not find class 'com.esri.android.map.MapView'问题

    环境win7 64bit sp1,eclipse 4.2.1 ,android API 16,ADT 23.0.2,arcgis android sdk 10.2.4 从arcgis-android- ...

  3. SQL Server-删除表中重复的记录!

    比如现在有一人员表  (表名:peosons)若想将姓名.身份证号.住址这三个字段完全相同的记录查询出来 select   p1.*   from   persons   p1,persons   p ...

  4. C++ Code_HotKey

            Code::使用HotKeyCtrl定义一个系统热键 // 关联HotKeyCtrl控件变量 m_HotKey1       BEGIN_MESSAGE_MAP(CXyzDlg, CD ...

  5. 黑客破译android开发代码真就那么简单?

    很多程序员辛辛苦苦开发出的android开发代码,很容易就被黑客翻译了. Google似乎也发现了这个问题,从SDK2.3开始我们可以看到在android-sdk-windows\tools\下面多了 ...

  6. 关于Android圆形图片的一种优化方案(可以显示网络图片)

    在Android App中,我们经常看到圆形头像图片,然后网上也有很多开源的控件.刚好这个项目用到了,也去找了一些开源的,发现并不完美,所以只好自己优化了,废话不多说,先上效果图: 下面是源码:本人能 ...

  7. 当调用List Remove 失效时 [C#] .

    有没有试过从一个集合里面移除一个对象之后,这个集合仍然留有这个对象?世界之大,无奇不有.稍有疏忽,便会导致这种奇怪的现象.现在让我们看看这个“不死”对象究竟是怎么一回事. 1.“不死”对象现身 这个问 ...

  8. SQL Sever 2008 数据库文件的备份和还原

    数据库文件备份保存的方式我知道的有两种,第一种就是我们知道到的简单的分离,生成.mdf和.ldf文件,然后使用的时候直接进行附加数据库就可以了. 那么还有生成备份的文件.bak 的,这个操作要在步骤: ...

  9. VC6.0常见编译错误提示

    原文:http://c.biancheng.net/cpp/html/746.html 1) error C2001: newline in constant 编号:C2001 直译:在常量中出现了换 ...

  10. android studio无法更新之解决方案

    当发现android studio有更新时,当然第一时间就想更新,可惜被墙了. 解决方案: 下载wallproxy,百度你懂的 在proxy.ini中最上面,找到ip和port 接着,在android ...