Android SurfaceView实战 打造抽奖转盘

来源:互联网 发布:csocket编程详解 编辑:程序博客网 时间:2024/05/16 09:35

源码:http://download.csdn.net/detail/lm_zp/9534737



activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:background="#ffffff"    android:layout_height="match_parent" >     <Button          android:id="@+id/button"          android:layout_width="match_parent"          android:layout_height="wrap_content"          android:text="你想要什么"                          />    <com.example.myyuanpan.LuckyPanView        android:id="@+id/id_luckypan"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:layout_centerInParent="true"        android:padding="30dp" />        <ImageView         android:id="@+id/id_start_btn"        android:src="@drawable/start"        android:layout_centerInParent="true"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        /></RelativeLayout>
dialog.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" ><TextView     android:id="@+id/text1"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:text="单反相机"    android:gravity="center_horizontal"    /><TextView     android:id="@+id/text2"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:text="IPAD"    android:gravity="center_horizontal"    /><TextView     android:id="@+id/text3"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:text="恭喜发财"    android:gravity="center_horizontal"    /><TextView     android:id="@+id/text4"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:text="IPHONE"    android:gravity="center_horizontal"    /><TextView     android:id="@+id/text5"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:text="妹子一只"    android:gravity="center_horizontal"    /><TextView     android:id="@+id/text6"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:text="恭喜发财"    android:gravity="center_horizontal"    /></LinearLayout>
res/drawable/start_btn.xml

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android" ><item android:state_pressed="true" android:drawable="@drawable/stop"></item><item android:drawable="@drawable/start"></item></selector>
画圆盘

LuckyPanView.java

package com.example.myyuanpan;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.SurfaceHolder.Callback;import android.view.SurfaceView;public class LuckyPanView extends SurfaceView implements Callback, Runnable{private SurfaceHolder mHolder;/** * 与SurfaceHolder绑定的Canvas */private Canvas mCanvas;/** * 用于绘制的线程 */private Thread t;/** * 线程的控制开关 */private boolean isRunning;/** * 抽奖的文字 */private String[] mStrs = new String[] { "单反相机", "IPAD", "恭喜发财", "IPHONE","妹子一只", "恭喜发财" };/** * 每个盘块的颜色 */private int[] mColors = new int[] { 0xFFFFC300, 0xFFF17E01, 0xFFFFC300,0xFFF17E01, 0xFFFFC300, 0xFFF17E01 };/** * 与文字对应的图片 */private int[] mImgs = new int[] { R.drawable.danfan, R.drawable.ipad,R.drawable.f040, R.drawable.iphone, R.drawable.meizi,R.drawable.f040 };/** * 与文字对应图片的bitmap数组 */private Bitmap[] mImgsBitmap;/** * 盘块的个数 */private int mItemCount = 6;/** * 绘制盘块的范围 */private RectF mRange = new RectF();/** * 圆的直径 */private int mRadius;/** * 绘制盘快的画笔 */private Paint mArcPaint;/** * 绘制文字的画笔 */private Paint mTextPaint;/** * 滚动的速度 */private double mSpeed;private volatile float mStartAngle = 0;/** * 是否点击了停止 */private boolean isShouldEnd;/** * 控件的中心位置 */private int mCenter;/** * 控件的padding,这里我们认为4个padding的值一致,以paddingleft为标准 */private int mPadding;/** * 背景图的bitmap */private Bitmap mBgBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.bg2);/** * 文字的大小 */private float mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, getResources().getDisplayMetrics());public LuckyPanView(Context context){this(context, null);}public LuckyPanView(Context context, AttributeSet attrs){super(context, attrs);mHolder = getHolder();mHolder.addCallback(this);// setZOrderOnTop(true);// 设置画布 背景透明// mHolder.setFormat(PixelFormat.TRANSLUCENT);setFocusable(true);setFocusableInTouchMode(true);this.setKeepScreenOn(true);}/** * 设置控件为正方形 */@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width = Math.min(getMeasuredWidth(), getMeasuredHeight());// 获取圆形的直径mRadius = width - getPaddingLeft() - getPaddingRight();// padding值mPadding = getPaddingLeft();// 中心点mCenter = width / 2;setMeasuredDimension(width, width);}@Overridepublic void surfaceCreated(SurfaceHolder holder){// 初始化绘制圆弧的画笔mArcPaint = new Paint();mArcPaint.setAntiAlias(true);mArcPaint.setDither(true);// 初始化绘制文字的画笔mTextPaint = new Paint();mTextPaint.setColor(0xFFffffff);mTextPaint.setTextSize(mTextSize);// 圆弧的绘制范围mRange = new RectF(getPaddingLeft(), getPaddingLeft(), mRadius+ getPaddingLeft(), mRadius + getPaddingLeft());// 初始化图片mImgsBitmap = new Bitmap[mItemCount];for (int i = 0; i < mItemCount; i++){mImgsBitmap[i] = BitmapFactory.decodeResource(getResources(),mImgs[i]);}// 开启线程isRunning = true;t = new Thread(this);t.start();}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height){// TODO Auto-generated method stub}@Overridepublic void surfaceDestroyed(SurfaceHolder holder){// 通知关闭线程isRunning = false;}@Overridepublic void run(){// 不断的进行drawwhile (isRunning){long start = System.currentTimeMillis();draw();long end = System.currentTimeMillis();try{if (end - start < 50){Thread.sleep(50 - (end - start));}} catch (InterruptedException e){e.printStackTrace();}}}private void draw(){try{// 获得canvasmCanvas = mHolder.lockCanvas();if (mCanvas != null){// 绘制背景图drawBg();/** * 绘制每个块块,每个块块上的文本,每个块块上的图片 */float tmpAngle = mStartAngle;float sweepAngle = (float) (360 / mItemCount);for (int i = 0; i < mItemCount; i++){// 绘制快快mArcPaint.setColor(mColors[i]);//mArcPaint.setStyle(Style.STROKE);mCanvas.drawArc(mRange, tmpAngle, sweepAngle, true,mArcPaint);// 绘制文本drawText(tmpAngle, sweepAngle, mStrs[i]);// 绘制IcondrawIcon(tmpAngle, i);tmpAngle += sweepAngle;}// 如果mSpeed不等于0,则相当于在滚动mStartAngle += mSpeed;// 点击停止时,设置mSpeed为递减,为0值转盘停止if (isShouldEnd){mSpeed -= 1;}if (mSpeed <= 0){mSpeed = 0;isShouldEnd = false;}// 根据当前旋转的mStartAngle计算当前滚动到的区域calInExactArea(mStartAngle);}} catch (Exception e){e.printStackTrace();} finally{if (mCanvas != null)mHolder.unlockCanvasAndPost(mCanvas);}}/** * 根据当前旋转的mStartAngle计算当前滚动到的区域 绘制背景,不重要,完全为了美观 */private void drawBg(){mCanvas.drawColor(0xFFFFFFFF);mCanvas.drawBitmap(mBgBitmap, null, new Rect(mPadding / 2,mPadding / 2, getMeasuredWidth() - mPadding / 2,getMeasuredWidth() - mPadding / 2), null);}/** * 根据当前旋转的mStartAngle计算当前滚动到的区域 *  * @param startAngle */public void calInExactArea(float startAngle){// 让指针从水平向右开始计算float rotate = startAngle + 90;rotate %= 360.0;for (int i = 0; i < mItemCount; i++){// 每个的中奖范围float from = 360 - (i + 1) * (360 / mItemCount);float to = from + 360 - (i) * (360 / mItemCount);if ((rotate > from) && (rotate < to)){Log.d("TAG", mStrs[i]);return;}}}/** * 绘制图片 *  * @param startAngle * @param sweepAngle * @param i */private void drawIcon(float startAngle, int i){// 设置图片的宽度为直径的1/8int imgWidth = mRadius / 8;float angle = (float) ((30 + startAngle) * (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(mImgsBitmap[i], null, rect, null);}/** * 绘制文本 *  * @param rect * @param startAngle * @param sweepAngle * @param string */private void drawText(float startAngle, float sweepAngle, String string){Path path = new Path();path.addArc(mRange, startAngle, sweepAngle);float textWidth = mTextPaint.measureText(string);// 利用水平偏移让文字居中float hOffset = (float) (mRadius * Math.PI / mItemCount / 2 - textWidth / 2);// 水平偏移float vOffset = mRadius / 2 / 6;// 垂直偏移mCanvas.drawTextOnPath(string, path, hOffset, vOffset, mTextPaint);}/** * 点击开始旋转 *  * @param luckyIndex */public void luckyStart(int luckyIndex){// 每项角度大小float angle = (float) (360 / mItemCount);// 中奖角度范围(因为指针向上,所以水平第一项旋转到指针指向,需要旋转210-270;)float from = 270 - (luckyIndex + 1) * angle;float to = from + angle;// 停下来时旋转的距离float targetFrom = 4 * 360 + from;/** * <pre> *  (v1 + 0) * (v1+1) / 2 = target ; *  v1*v1 + v1 - 2target = 0 ; *  v1=-1+(1*1 + 8 *1 * target)/2; * </pre> */float v1 = (float) (Math.sqrt(1 * 1 + 8 * 1 * targetFrom) - 1) / 2;float targetTo = 4 * 360 + to;float v2 = (float) (Math.sqrt(1 * 1 + 8 * 1 * targetTo) - 1) / 2;mSpeed = (float) (v1 + Math.random() * (v2 - v1));isShouldEnd = false;}public void luckyEnd(){mStartAngle = 0;isShouldEnd = true;}public boolean isStart(){return mSpeed != 0;}public boolean isShouldEnd(){return isShouldEnd;}}
MainActivity.java

package com.example.myyuanpan;import android.os.Bundle;import android.app.Activity;import android.app.Dialog;import android.view.LayoutInflater;import android.view.Menu;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.ImageView;import android.widget.TextView;import android.widget.Toast;public class MainActivity extends Activity {private LuckyPanView mLuckyPanView;private ImageView mStartBtn;private Button button;int num = 2;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mLuckyPanView = (LuckyPanView) findViewById(R.id.id_luckypan);mStartBtn = (ImageView) findViewById(R.id.id_start_btn);button = (Button) findViewById(R.id.button);button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stub// Dialog 对话框final Dialog dialog = new Dialog(MainActivity.this);// dialog布局View inflate = LayoutInflater.from(MainActivity.this).inflate(R.layout.dialog, null);dialog.setContentView(inflate);// dialog头dialog.setTitle("选择想要的");dialog.setCanceledOnTouchOutside(true);// 显示dialog.show();TextView text1 = (TextView) inflate.findViewById(R.id.text1);TextView text2 = (TextView) inflate.findViewById(R.id.text2);TextView text3 = (TextView) inflate.findViewById(R.id.text3);TextView text4 = (TextView) inflate.findViewById(R.id.text4);TextView text5 = (TextView) inflate.findViewById(R.id.text5);TextView text6 = (TextView) inflate.findViewById(R.id.text6);text1.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubnum = 0;Toast.makeText(MainActivity.this, "修改完成", 0).show();dialog.dismiss();}});text2.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubnum = 1;Toast.makeText(MainActivity.this, "修改完成", 0).show();dialog.dismiss();}});text3.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubnum = 2;Toast.makeText(MainActivity.this, "修改完成", 0).show();dialog.dismiss();}});text4.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubnum = 3;Toast.makeText(MainActivity.this, "修改完成", 0).show();dialog.dismiss();}});text5.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubnum = 4;Toast.makeText(MainActivity.this, "修改完成", 0).show();dialog.dismiss();}});text6.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubnum = 5;Toast.makeText(MainActivity.this, "修改完成", 0).show();dialog.dismiss();}});}});mStartBtn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if (!mLuckyPanView.isStart()) {mStartBtn.setImageResource(R.drawable.stop);mLuckyPanView.luckyStart(num);} else {if (!mLuckyPanView.isShouldEnd()){mStartBtn.setImageResource(R.drawable.start);mLuckyPanView.luckyEnd();}}}});}}






0 0
原创粉丝点击