转盘功能添加"/>
安卓 转盘功能添加
zhuanpanView.java
/** 说明:* 该类自定义了转盘类,可通过给定转盘中各个块的概率,控制指针的指向* 创建转盘时,需提供转盘背景图像panpic 和 指针图像panhandpic,二者为宽度相同的正方行* 转盘的块数由概率数组p[]限定* * 调用:* final zhuanpanView zhuanpan = new zhuanpanView(this) ; //创建转盘* int p[] = {20, 0, 20, 0, 30, 30}; //p为转盘所有块的概率数组* zhuanpan.startRotate(p); //转盘指向对应块,返回值为块位置(从0顺时针计数) * - 若转盘处于旋转状态再次调用,则返回-1.*/import java.util.Random;import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;//自定义的转盘View
public class zhuanpanView extends View implements Runnable
{ //界面需要的图片 private Bitmap panpic; private Bitmap panhandpic; public int width, height; //转盘的宽度和高度//旋转矩阵private Matrix panRotate=new Matrix(); //可控制盘面的旋转private Matrix panhandTrans=new Matrix(); //可控制指针的旋转private int degree=0; //旋转角度private float degreeSpeed=0; //旋转角度变化增量,控制转盘转速由快到慢private int destdegree=360*6+60; //最终停止角度位置private int offDegree = 0; //角度偏移量,记录转盘指针前一次的位置public boolean flagRotate=false; //标志转盘指针当前是否处于旋转状态private int centerX, centerY; //旋转中心位置public static Random random = new Random(); //随机数对象//创建转盘控件-代码创建时,可调用该函数public zhuanpanView(Context context) {super(context);zhuanpanViewInit(context); } //创建转盘控件-XML布局创建控件时,会调用该函数public zhuanpanView(Context context, AttributeSet attrs) {super(context, attrs);zhuanpanViewInit(context);} //转盘控件自身的初始化private void zhuanpanViewInit(Context context){Resources r=context.getResources();//生成图片 panpic=BitmapFactory.decodeStream(r.openRawResource(R.drawable.table)); panhandpic=BitmapFactory.decodeStream(r.openRawResource(R.drawable.pointer)); //转盘大小自适应屏幕,已480屏幕宽度为基准float magnify = getMagnifyParams((Activity)context);panpic=resize(panpic, magnify);panhandpic=resize(panhandpic, magnify);width = panhandpic.getWidth(); //设置转盘的宽度height = panhandpic.getHeight();centerX = width/2; //获取指针旋转的中心位置centerY = height/2;//用线程来刷新界面 Thread thread=new Thread(this);thread.start(); }//获取与屏幕适配的放大倍数private float getMagnifyParams(Activity activity){float magnify = 1f;//获取屏幕的宽度和高度WindowManager wm = activity.getWindowManager();int screenWidth = wm.getDefaultDisplay().getWidth();int screenHeight = wm.getDefaultDisplay().getHeight();int min = screenWidth < screenHeight ? screenWidth : screenHeight; //取宽高较小的magnify = min/480f;Log.e("转盘自适应:", " ");Log.e("屏幕分辨率", screenWidth+"," + screenHeight);Log.e("转盘放大倍数", magnify+" " );return magnify;}//将Bitmap放大size倍private static Bitmap resize(Bitmap bitmap, float size) {Matrix matrix = new Matrix(); matrix.postScale(size, size); //长和宽放大缩小的比例Bitmap resizeBmp = Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);return resizeBmp;}//重写View类的onDraw()函数 @Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(panpic, panRotate, null); //绘制出转盘panhandTrans.setRotate(degree+offDegree, centerX, centerY); //转盘指针绕其中心旋转角度degreecanvas.drawBitmap(panhandpic, panhandTrans, null); //绘制指针//控制位置的平移//panhandTrans.setTranslate(centerX-panhandpic.getWidth()/2, centerY-panhandpic.getHeight()/5*3); } //重写的run函数,用来控制转盘指针的转动,改变旋转的角度public void run() { try {while(true){ if(flagRotate && degree < destdegree) //控制转盘中的指针旋转到指定角度{this.degree += (int)degreeSpeed; //当前旋转到的角度//这个函数强制UI线程刷新界面 this.postInvalidate(); Thread.sleep(30); //每秒40次绘制degreeAccelerate(); //执行加减速处理if(degree >= destdegree) flagRotate = false;}} } catch (InterruptedException e) { e.printStackTrace(); } } //控制转盘中指针的旋转加减速private void degreeAccelerate(){if(degreeSpeed == 0) degreeSpeed = 1;if(degree<230) //执行加速,大概130度范围加速到最大{if(degreeSpeed <= 20) degreeSpeed *= 1.19f;else if(degreeSpeed >= 21)degreeSpeed = 20.57f;}else if(destdegree - degree < 720) //执行减速{if(degreeSpeed > 1)degreeSpeed *= 0.9752f;else degreeSpeed = 1;}}//转盘数据重置public void reset(){offDegree = 0;degree=0;degreeSpeed=0;}//重置当前角度和转速,保存指针角度位置private void reset2(){offDegree = (degree+offDegree) % 360; //先保存上次的角度偏移值degree=0;degreeSpeed=0;}//根据概率数组p控制转盘的旋转public int startRotate(int p[]){ if(flagRotate) //如果转盘正处于旋转状态{Log.e("转盘选中位置", "-1");return -1; //-1表示转盘当前不可用}reset2(); //获取转盘指针上次的角度偏移值,重置当前角度int select = set_destdegree(p); //根据各块的给定概率设置旋转的最终角度和选中块位置Log.e("转盘选中位置", select+"");this.flagRotate=true; //开始旋转return select; } /*** 按默认概率,控制转盘旋转,* 转盘块数 = 概率数组p.length* startRotate(p)控制转盘旋转,返回值为转盘指针指向的块号*/public void startRotate1(){int p[] = {0, 20, 20, 20, 20, 20, 20, 20};startRotate(p);}//停止指针旋转,可不调用待其自动停止public void stopRotate(){ this.flagRotate=false; } //根据各部分的比例值,设置旋转最终停止位置public int set_destdegree(int p[]){int len = p.length; //转盘中的总块数random.setSeed(random.nextLong()); //随机设置其随机种子,进一步随机化int countp = 0; //统计所有块的总概率for(int j= 0; j < len; j++)countp += p[j];int num = random.nextInt(countp) + 1; //生成1到countp之间的随机数//根据各块的比例值,将num转换为对应的块位置 iint tmp = 0; //累计前面各块的概率和int i=0;for(; i<len && tmp < num; i++){tmp += p[i]; //累计概率if(num <= tmp)break; //num在块p[i]的概率范围内}int partDegree = (int)(360/len); //计算各块所占的角度大小int partRnddegree = random.nextInt(partDegree-3)+2; //块内角度随机偏移, -3)+2避免指向两块的交界处//块位置转化为块的对应角度destdegree = partDegree * i + 360*6 + partRnddegree;//指向选定块,多转6圈,块内角度随机destdegree -= offDegree; //目标角度减少初始偏移return i; //返回指针所指的块位置}
}
添加转盘操作
添加:
=》1.
zhuanpanView.java、
pointer.png、table.png
到项目=》2.
NewActivity.java中(待添加转盘的Activity)添加全局变量:
public zhuanpanView zhuanpan; //添加转盘
public Handler handler; //处理转盘的显示与隐藏NewActivity.onCreate(){}中添加: ——可调整 params.topMargin = 50; 的值修改转盘的垂直位置handler = new Handler()
{@SuppressLint("HandlerLeak")@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case 1: //显示转盘if(zhuanpan==null) //没有创建转盘,则创建{zhuanpan = new zhuanpanView(NewActivity.this); //创建转盘//转盘的布局参数FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(zhuanpan.width, zhuanpan.height);params.topMargin = 50; params.gravity = Gravity.CENTER_HORIZONTAL|Gravity.CENTER_VERTICAL/*Gravity.TOP*/;addContentView(zhuanpan, params); //添加转盘到Activity}else zhuanpan.setVisibility(View.VISIBLE); //已有,则显示break;case 2: //隐藏转盘if(zhuanpan!=null) //转盘存在{zhuanpan.setVisibility(View.INVISIBLE); //隐藏zhuanpan.reset(); //转盘重置,回到初始状态}// if(zhuanpan!=null && zhuanpan.getParent()!=null) ((ViewGroup)zhuanpan.getParent()).removeView(zhuanpan);break;case 3: //启动转盘zhuanpan.startRotate1();break;}}
};=》3.
抽奖控制处添加:(调用函数进行控制)/*** 向父线程发送消息* what = 1, 显示转盘* what = 2, 隐藏转盘*/
private void zhuanpanControl(int what)
{Handler handler = NewActivity.instance.handler; //用于子线程向父线程发送消息Message msg = new Message();msg.what = what; handler.sendMessage(msg); //通知handler处理事件
};/*** 启动转盘* @param p 各转盘块的概率 p = {10, 10, 10, 10, 15, 15, 15, 15}* @return 指针所指向的转盘块位置(从0顺时针计数)*/
private int zhuanpanStart(int[] p)
{return NewActivity.instance.zhuanpan.startRotate(p);
}
下载:
附录:(2015_08_17)
1、 zhuanpanView2.java
package com.linkstudio.popstar.script;/** 说明:* 该类自定义了转盘类,可通过给定转盘中各个块的概率,控制指针的指向* 创建转盘时,需提供转盘背景图像panpic 和 指针图像panhandpic,二者为宽度相同的正方行* 转盘的块数由概率数组p[]长度限定* * 默认设置:初始时,转盘指针指向0度位置,指向第一个块的中心位置(左边缘,设置pointerCenter = false;)* * 调用:* final zhuanpanView zhuanpan = new zhuanpanView2() ; //创建转盘* int p[] = {20, 0, 20, 0, 30, 30}; //p为转盘所有块的概率数组* zhuanpan.startRotate(p); //转盘指向对应块,返回值为块位置(从0顺时针计数) * - 若转盘处于旋转状态再次调用,则返回-1.*/import java.util.Random;import android.util.Log;import com.hlge.lib.base.Component;// 自定义的转盘View
public class zhuanpanView2 implements Runnable
{Component panhand;private int degree = 0; // 旋转角度private float degreeSpeed = 0; // 旋转角度变化增量,控制转盘转速由快到慢private int destdegree = 0; // 最终停止角度位置private int offDegree = 0; // 角度偏移量,记录转盘指针前一次的位置private float drawOffDegree = 0; // 绘制偏移角度,指针指向距0度位置的度数,顺时针为正public boolean flagRotate = false; // 标志转盘指针当前是否处于旋转状态private float centerX, centerY; // 旋转中心位置private int blockNums = 1; // 转盘中的总块数protected float blockDegree = 360; // 一个转盘块占用的角度public static Random random = new Random(); // 随机数对象public boolean pointerCenter = true; // 转盘指针是否指向第一块的中心位置,false:指向第一块的起始边缘// 转盘指针角度的调整public void degreeAdjust(float drawOffDegree){this.drawOffDegree = drawOffDegree - 0.3f;panhand.setRotate(centerX, centerY, -(degree + offDegree + drawOffDegree));}// 设置转盘指针的中心位置public void setCenter(float centerX, float centerY){this.centerX = centerX;this.centerY = centerY;panhand.setRotate(centerX, centerY, -(degree + offDegree + drawOffDegree));}// 创建转盘控件-代码创建时,可调用该函数,X/Y为位置调整public zhuanpanView2(Component panhand, float X, float Y){this.panhand = panhand;panhand.setXY((short) (panhand.x + X), (short) (panhand.y + Y)); // 重新调整位置this.centerX = panhand.width / 2;this.centerY = panhand.height / 2;}public boolean isRun = false;public void start(){Thread thread = new Thread(this);thread.start();isRun = true;}public void interrupt(){isRun = false;}// 重写的run函数,用来控制转盘指针的转动,改变旋转的角度public void run(){try{// while(isRun && (ScriptLib.luckyform != null || ScriptLib.sevenDayReward_Lucky != null))while (isRun){if (flagRotate && degree < destdegree) // 控制转盘中的指针旋转到指定角度{this.degree += (int) degreeSpeed; // 当前旋转到的角度update(); // 转盘旋转时,角度变动执行相应逻辑panhand.setRotate(centerX, centerY, -(degree + offDegree + drawOffDegree)); // 转盘指针绕其中心旋转角度degree// panhand.setRotate(-(degree+offDegree+drawOffDegree));Thread.sleep(25); // 每秒25毫秒操作一次degreeAccelerate(); // 执行加减速处理if (degree >= destdegree){flagRotate = false;rotateStopDoing(); // 转盘停止转动时,执行逻辑interrupt();}}}}catch (InterruptedException e){e.printStackTrace();}}/** 更新操作,供子类重写 */public void update(){}/** 转盘停止转动时调用,供子类重写 */public void rotateStopDoing(){}// 控制转盘中指针的旋转加减速private void degreeAccelerate(){if (degreeSpeed == 0) degreeSpeed = 1;if (degree < 230) // 执行加速,大概130度范围加速到最大{if (degreeSpeed <= 20)degreeSpeed *= 1.19f;else if (degreeSpeed >= 21) degreeSpeed = 20.57f;}else if (destdegree - degree < 720) // 执行减速{if (degreeSpeed > 1)degreeSpeed *= 0.9752f;elsedegreeSpeed = 1;}}// 转盘数据重置public void reset(){offDegree = 0;degree = 0;degreeSpeed = 0;}// 重置当前角度和转速,保存指针角度位置private void reset2(){offDegree = (degree + offDegree) % 360; // 先保存上次的角度偏移值degree = 0;degreeSpeed = 0;}// 根据概率数组p控制转盘的旋转public int startRotate(int p[]){if (flagRotate) // 如果转盘正处于旋转状态{Log.e("转盘选中位置", "-1");return -1; // -1表示转盘当前不可用}reset2(); // 获取转盘指针上次的角度偏移值,重置当前角度int select = set_destdegree(p); // 根据各块的给定概率设置旋转的最终角度和选中块位置Log.e("转盘选中位置", select + "");this.flagRotate = true; // 开始旋转start();return select;}/** 按默认概率,控制转盘旋转, 转盘块数 = 概率数组p.length startRotate(p)控制转盘旋转,返回值为转盘指针指向的块号 */public void startRotate1(){int p[] = { 0, 20, 20, 20, 20, 20, 20, 20 };startRotate(p);}// 停止指针旋转,可不调用待其自动停止public void stopRotate(){this.flagRotate = false;}/*** 获取转盘指针实时角度值,相对于第0块起始边角度位置*/public int curDegree(){float half = (pointerCenter ? (int)(blockDegree / 2) : 0);return (int)(degree + half + offDegree);}/*** 指针角度为degree时,所指的块位置*/public int blockIndex(float degree){return (int) (degree % 360 / blockDegree);}/*** 指针角度为degree时,所指的块位置(限定块角度大小partDegree)*/public int blockIndex(float degree, float partDegree){return (int) (degree % 360 / partDegree);}// 根据各部分的比例值,设置旋转最终停止位置public int set_destdegree(int p[]){blockNums = p.length; // 转盘中的总块数random.setSeed(random.nextLong()); // 随机设置其随机种子,进一步随机化int countp = 0; // 统计所有块的总概率for (int j = 0; j < blockNums; j++)countp += p[j];int num = random.nextInt(countp) + 1; // 生成1到countp之间的随机数// 根据各块的比例值,将num转换为对应的块位置 iint tmp = 0; // 累计前面各块的概率和int i = 0;for (; i < blockNums && tmp < num; i++){tmp += p[i]; // 累计概率if (num <= tmp) break; // num在块p[i]的概率范围内}blockDegree = 360 / blockNums; // 计算各块所占的角度大小int partRnddegree = random.nextInt((int)blockDegree - 9) + 5; // 块内角度随机偏移, -9)+5避免指向两块的交界处// 块位置转化为块的对应角度destdegree = (int)(blockDegree * i) + 360 * 6 + partRnddegree; // 指向选定块,多转6圈,块内角度随机if (pointerCenter) destdegree -= (int)(blockDegree / 2); // 相对于转盘背景少转动半个块内角destdegree -= offDegree; // 目标角度减少初始偏移return i; // 返回指针所指的块位置}
}
/*** 2015-8-11上午10:18:58* wangzhongyuan*/
package com.linkstudio.popstar.script;import android.util.Log;import com.hlge.lib.base.Component;
import com.hlge.lib.tool.SoundManager;/*** zhuanpanView 继承自转盘基础类zhuanpanView2,新增转盘指示灯、即时音效* -----* 2015-8-11 上午10:18:58 * wangzhongyuan*/
public class zhuanpanView extends zhuanpanView2
{private float nextDegree = 0; // 下一处更新操作,角度位置zhuanpanLights16 tex;private boolean thisFormDebug = true;public zhuanpanView(Component panhand, float X, float Y, zhuanpanLights16 tex){super(panhand, X, Y);this.tex = tex;}/** 转盘指针指向各个块时,的更新操作 */public void update(){int degree = curDegree();if (degree > nextDegree){int index = blockIndex(degree, blockDegree / 2); // (blockDegree/2)块大小的块索引if (index % 2 == 1) SoundManager.playSound("zhuandong.mp3", false);updateProcess(index); // 显示指针所指块索引对应内容nextDegree += blockDegree / 2; // 间隔一定角度值,执行更新操作}}String info = "";// 更新转盘显示信息private void updateProcess(int curBlock){if (thisFormDebug) info += curBlock + ", " + nextDegree + "; ";tex.index = curBlock;}/** 转盘停止转动时调用 */public void rotateStopDoing(){selectMessage(); //转盘停止转动调用逻辑SoundManager.playSound("zhuandong_js.mp3", false); //播放转盘停止转动音效tex.index = -1; //转盘重置,不绘制灯if (thisFormDebug){Log.e("转盘指针所指块变动:", info);info = "";}nextDegree %= 360;}/*** 转盘停止转动时调用,选中块处理逻辑,供子类调用*/public void selectMessage() {}
}
3、zhuanpanLights16.java
/*** 2015-8-11上午10:19:17* wangzhongyuan*/
package com.linkstudio.popstar.script;import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.hlge.lib.base.HlgeTexture;
import com.hlge.lib.base.SpineTexture;/*** Lights16 转盘指示灯* -----* 2015-8-11 上午10:19:17 * wangzhongyuan*/
public class zhuanpanLights16 extends HlgeTexture
{SpineTexture[] lights;public int index = -1, preIndex = -1;/** 创建Texture */public zhuanpanLights16(){super();lights = new SpineTexture[16];for (int i = 0; i < 16; i++)lights[i] = new SpineTexture("7", (14 + i) + "", true);}/** SpineTexture的绘制 */public void paint(SpriteBatch g){paint(g, x, -y);}/** SpineTexture的绘制 */public void paint(SpriteBatch g, float x, float y){if (index >= lights.length) index = 0;if (index >= 0 && lights[index] != null){g.setColor(color.toIntBits()); // 设置透明度if (parent != null){x += parent.width / 2;y += parent.height / 2;}// if (index != preIndex)
// {
// preIndex = index;
// if (lights[index].isPlayOver()) lights[index].rePlay(); // lights[index].spine.setAction(spine.actionId, false); //
// }lights[index].paint(g, x, y);}}@Overridepublic void dispose(){for (int i = 0; i < lights.length; i++)if (lights[i] != null) lights[i].dispose();lights = null;}
}
更多推荐
安卓 转盘功能添加
发布评论