首页 > 学院 > 开发设计 > 正文

SurfaceView的基本用法模板自定义实现抽奖盘

2019-11-09 18:44:02
字体:
来源:转载
供稿:网友

一概述 SurfaceView是在子线程中进行绘制的,SurfaceHolder提供Canvas并管理SurfaceView的生命周期。

二、模板编程思路 1、继承SurfaceView,声明一个绘制的线程,获取SurfaceHolder,控制线程的变量,Canvas。 2、构造方法中对变量进行初始化,SurfaceHolder提供Canvas与生命周期的CallBack; 3、在surfaceCreated方法中启动线程绘制 4、surfaceDestroyed方法中停止线程

1、SurfaceViewTempLate类

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

三、PackPan的实现 编码思路: 1、拷贝模板SurfaceViewTempLate类修改下名字 2、声明变量 3、重写下onMeasure方法,并初始化布局大小 4、surfaceCreated类中初始化变量 5、在线程中进行绘制背景,盘块,文字,图片

2、LankPan类

package app.kuxiao.com.demo.lack;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Path;import android.graphics.Rect;import android.graphics.RectF;import android.util.AttributeSet;import android.util.Log;import android.util.TypedValue;import android.view.SurfaceHolder;import android.view.SurfaceView;public class LackPan extends SurfaceView implements SurfaceHolder.Callback, Runnable { private SurfaceHolder holder; private Canvas mCanvas; //用于绘制的线程 private Thread t; //线程控制开关 private boolean isRunning = false; //盘块的图片 private int[] lack_icons = new int[]{R.drawable.danfan, R.drawable.f015, R.drawable.ipad, R.drawable.f040, R.drawable.iphone, R.drawable.meizi}; //盘块的文字 private String[] lack_text = new String[]{"单反", "恭喜发财", "Ipad", "恭喜发财", "iPhone", "服装一套"}; private int[] lack_color = new int[]{0xffffc300, 0xfff17e01, 0xffffc300, 0xfff17e01, 0xffffc300, 0xfff17e01}; //盘块的数量 private int lack_count = 6; private Bitmap[] lack_bitmap = null; //范围 private RectF mRange = null; //整个盘块的直径 private int mRadius = 0; //盘状的画笔 private Paint mPanPaint; //文字的画笔 private Paint mTextPaint; //旋转的速度 private double mSpeed = 0; //开始的角度 private volatile int mStartAngle = 0; //是否点击停止 private boolean isOnClickStop = false; //转盘的中心 private int mCentre = 0; // private int mPadding; //转盘的背景图 private Bitmap bg_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bg2); //设置文字的大小 private float mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, getResources().getDisplayMetrics()); public LackPan(Context context) { this(context, null); } public LackPan(Context context, AttributeSet attrs) { super(context, attrs); holder = getHolder(); holder.addCallback(this); //设置可获得焦点 setFocusable(true); setFocusableInTouchMode(true); //设置常量 setKeepScreenOn(true); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //获取控件的高度与宽度之间的最小值 int width = Math.min(getMeasuredWidth(), getMeasuredHeight()); //以左边距为准设置边距 mPadding = getPaddingLeft(); //设置直径 mRadius = width - 2 * mPadding; //设置中心点 mCentre = width / 2; //设置下View的尺寸 setMeasuredDimension(width, width); } @Override public void surfaceCreated(SurfaceHolder holder) { isRunning = true; //初始化盘的画笔 mPanPaint = new Paint(); //设置普通显示 mPanPaint.setAntiAlias(true); //设置高频 mPanPaint.setDither(true); //初始化文字画笔 mTextPaint = new Paint(); mTextPaint.setTextSize(mTextSize); mTextPaint.setColor(0xffffffff); //初始化绘制的范围 mRange = new RectF(mPadding, mPadding, mPadding + mRadius, mPadding + mRadius); //初始化图片 lack_bitmap = new Bitmap[lack_count]; for (int i = 0; i < lack_count; i++) { lack_bitmap[i] = BitmapFactory.decodeResource(getResources(), lack_icons[i]); } t = new Thread(this); t.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { isRunning = false; } @Override public void run() { //不断进行绘制... while (isRunning) { long start = System.currentTimeMillis(); draw(); long end = System.currentTimeMillis(); //强制绘制的时间为50毫秒以上 if (end - start <= 50) { try { Thread.sleep(50 - (end - start)); } catch (InterruptedException e) { e.printStackTrace(); } } } } private void draw() { try { mCanvas = holder.lockCanvas(); if (mCanvas != null) { //绘制背景 drawBg(); //绘制盘块 drawPan(); } } catch (Exception e) { } finally { if (mCanvas != null) { holder.unlockCanvasAndPost(mCanvas); } } } private void drawPan() { float startAngle = mStartAngle; float sweedAngle = 360 / lack_count; for (int i = 0; i < lack_count; i++) { mPanPaint.setColor(lack_color[i]); //绘制背景扇形 mCanvas.drawArc(mRange, startAngle, sweedAngle, true, mPanPaint); //绘制文字 drawText(startAngle, sweedAngle, lack_text[i]); //绘制图片 drawIcon(startAngle, lack_bitmap[i]); startAngle += sweedAngle; } mStartAngle += mSpeed; if (isOnClickStop) { mSpeed--; if (mSpeed < 0) { mSpeed = 0; isOnClickStop = false; } } } /** * 绘制图标 * * @param startAngle * @param bitmap */ private void drawIcon(float startAngle, Bitmap bitmap) { //图片的宽度 int icon_width = mRadius / 8; float angle = (float) ((startAngle + 360 / lack_count / 2) * Math.PI / 180); //极坐标换算公式 x = RCOSα // y = RSinα 求得图片的中心位置 int x = (int) (mCentre + mRadius / 4 * Math.cos(angle)); int y = (int) (mCentre + mRadius / 4 * Math.sin(angle)); //设置图片的范围 Rect rect = new Rect(x - icon_width / 2, y - icon_width / 2, x + icon_width / 2, y + icon_width / 2); mCanvas.drawBitmap(bitmap, null, rect, null); } /** * 绘制文字 * * @param startAngle * @param sweedAngle * @param s */ private void drawText(float startAngle, float sweedAngle, String s) { Path path = new Path(); path.addArc(mRange, startAngle, sweedAngle); //获取文字的长度 float textwidth = mTextPaint.measureText(s); float hOffset = (float) (sweedAngle * Math.PI / 180 / 4 * mRadius - textwidth / 2); float vOffset = mRadius / 2 / 4; mCanvas.drawTextOnPath(s, path, hOffset, vOffset, mTextPaint); } /** * 绘制背景 */ private void drawBg() { mCanvas.drawColor(0xffffffff); mCanvas.drawBitmap(bg_bitmap, null, new RectF(mPadding / 2, mPadding / 2, getMeasuredHeight() - mPadding / 2, getMeasuredHeight() - mPadding / 2), null); } /** * 开始转动 * @param mSpeed */ public void start(int mSpeed,int index) { this.mSpeed = mSpeed; float angle = 360/lack_count; //当前项的中奖范围 //0的话 正中奖是旋转240度,可以偏差30度 所以为 210-270 //1的话 正中奖是旋转180,180-30~180+30 (150-210) //2 float start = 270 - (index + 1 )* angle + 360*3;//转4圈 float end = start + angle; double mSpeed1 = (-1 +(Math.sqrt(1+4*2*start)))/2; double mSpeed2 = (-1 +(Math.sqrt(1+4*2*end)))/2; Log.i("LackPan","mSpeed1的值为" + mSpeed1); Log.i("LackPan","mSpeed2的值为" + mSpeed2); //设置速度为mSpeed1~mSpeed2中的一个随机数 this.mSpeed = mSpeed1; //重新设置开始角度为0; } /** * 停止转动 */ public void stop() { mStartAngle = 0; isOnClickStop = true; /* final Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { mSpeed--; Log.i("LackPan", "mSpeed的值为" + mSpeed); if (mSpeed <= 0) { mSpeed = 0; timer.cancel(); } } }, 0, 20);*/ }}

2、MainActivity类

package app.kuxiao.com.demo.lack;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.ImageView;public class MainActivity extends AppCompatActivity { private LackPan mLackPan = null; private ImageView mImageView = null; private boolean isOnclickStart = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.content_main); mLackPan = (LackPan) findViewById(R.id.lackPan); mImageView = (ImageView) findViewById(R.id.image_start); mImageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isOnclickStart) { mLackPan.stop(); isOnclickStart = false; mImageView.setImageResource(R.drawable.start); }else { isOnclickStart = true; mImageView.setImageResource(R.drawable.stop); mLackPan.start(50,0); } } }); }}

通过改变每一次绘制的初始角度,让转盘运动。


上一篇:你好,2017

下一篇:OC-杂谈篇(1)

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表