android自定义大转盘,Android 自定义View 抽奖大转盘(1)

站在别人的肩膀上慢慢前行

只是部分的转盘主要功能的实现,其他的东西可以慢慢填上,这里做一个简单的介绍

镇楼图

a63567bd2243

S71010-17315559.jpg

github链接 https://github.com/yukunkun/RotateView

来源

主要有四部分组成,

1.外部的圆形转盘。2.内部的文字显示。3.内部的图片显示。4.动画实现。

在获取到了数据之后,初始化一些数据的实现

private void init(Context context, AttributeSet attrs, int s) {

this.context = context;

screeHeight = getResources().getDisplayMetrics().heightPixels;

screenWidth = getResources().getDisplayMetrics().widthPixels;

scroller = ScrollerCompat.create(context);

}

private void initDate() {

//数据不能错误

if(strs.size()!=images.size()||strs.size()==0||images.size()==0){

return;

}

panNum=strs.size();

//获取到角度

InitAngle = 360 / panNum;

//获取到角度

verPanRadius = 360 / panNum;

//初始角度的一半

diffRadius = verPanRadius /2;

//两个扇形的颜色

dPaint.setColor(Color.rgb(255,133,132));

//两个扇形的颜色

sPaint.setColor(Color.rgb(254,104,105));

textPaint.setColor(Color.WHITE);

textPaint.setTextSize(Util.dip2px(context,16));

setClickable(true);

for(int i=0;i

Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), images.get(i));

bitmaps.add(bitmap);

}

}

下面是一些方法,具体的注释写了很多,可以直接看

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//内边距

final int paddingLeft = getPaddingLeft();

final int paddingRight = getPaddingRight();

final int paddingTop = getPaddingTop();

final int paddingBottom = getPaddingBottom();

//view的宽高

int width = getWidth() - paddingLeft - paddingRight;

int height = getHeight() - paddingTop - paddingBottom;

int MinValue = Math.min(width,height);

//获取到圆的半径

radius = MinValue/2;

//获取到view的矩形

RectF rectF = new RectF(getPaddingLeft(),getPaddingTop(),width,height);

//角度的起始是顺时针的,%4==0,如果为4,则就是90度,数学的第三象限开始,否则在第四象限

int angle = (panNum%4 ==0) ? InitAngle : InitAngle-diffRadius;

Log.d("angle", String.valueOf(angle));

//绘制圆弧,两个不同颜色的圆弧

for(int i= 0;i

if(i%2 == 0){

canvas.drawArc(rectF,angle,verPanRadius,true,dPaint);

}else {

canvas.drawArc(rectF,angle,verPanRadius,true,sPaint);

}

angle += verPanRadius;

}

//绘制图片

for(int i=0;i

drawIcon(width/2, height/2, radius, (panNum%4==0)?InitAngle + diffRadius : InitAngle, i, canvas);

InitAngle += verPanRadius;

}

//绘制文字

for(int i=0;i

drawText((panNum%4==0)?InitAngle+diffRadius + (diffRadius*3/4):InitAngle+diffRadius ,strs.get(i), 2*radius, textPaint, canvas,rectF);

InitAngle += verPanRadius;

}

}

以上是外部绘制,文字和图片的绘制

//文字绘制,path路径

private void drawText(float startAngle, String string, int mRadius, Paint mTextPaint, Canvas mCanvas, RectF mRange) {

Path path = new Path();

path.addArc(mRange, startAngle, verPanRadius);

float textWidth = mTextPaint.measureText(string);

//圆弧的水平偏移,保证在转盘内部

float hOffset = (panNum % 4 == 0)?((float) (mRadius * Math.PI / panNum/2 ))

:((float) (mRadius * Math.PI / panNum/2 - textWidth/2 ));

//圆弧的垂直偏移,保证在转盘内部

float vOffset = mRadius / 2 / 6;

mCanvas.drawTextOnPath(string, path, hOffset, vOffset, mTextPaint);

}

private void drawIcon(int xx,int yy,int mRadius,float startAngle, int i,Canvas mCanvas) {

int imgWidth = mRadius / 4;

float angle = (float) Math.toRadians(verPanRadius +startAngle);

//确定图片在圆弧中 中心点的位置

float x = (float) (xx + (mRadius /2 + mRadius/12)* Math.cos(angle));

float y = (float) (yy + (mRadius /2 +mRadius/12) * Math.sin(angle));

// 确定绘制图片的位置,前后偏移,得到图片的位置

RectF rect = new RectF(x - imgWidth *2 / 3, y - imgWidth*2 / 3, x + imgWidth

*2/ 3, y + imgWidth*2/3);

//mCanvas.drawRect(rect,textPaint);

Bitmap bitmap = bitmaps.get(i);

//绘制

mCanvas.drawBitmap(bitmap, null, rect, null);

}

具体的绘制和计算如上所示,可以实现转盘的View了。

主要是动画的处理,有点计算在里面

//旋转的动画

public void startAnimation(int pos){

//Rotate lap. 随机的圈数,>4圈,修改可以控制旋转的圈数和时长

int lap = (int) (Math.random()*2) + 4;

//Rotate angle.

int angle = 0;

if(pos < 0){

//随机角度

angle = (int) (Math.random() * 360);

}else{

//控制某个角度,由具体的位置,计算出具体的角度值

int initPos = queryPosition();

if(pos > initPos){

angle = (pos - initPos)*verPanRadius;

lap -= 1;

angle = 360 - angle;

}else if(pos < initPos){

angle = (initPos - pos)*verPanRadius;

}else{

//nothing to do.

}

}

//All of the rotate angle.

int increaseDegree = lap * 360 + angle;

long time = (lap + angle / 360) * ONE_WHEEL_TIME;

int DesRotate = increaseDegree + InitAngle;

//TODO 为了每次都能旋转到转盘的中间位置

int offRotate = DesRotate % 360 % verPanRadius;

DesRotate -= offRotate;

DesRotate += diffRadius;

//属性动画

ValueAnimator animtor = ValueAnimator.ofInt(InitAngle,DesRotate);

animtor.setInterpolator(new AccelerateDecelerateInterpolator());

animtor.setDuration(time);

animtor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

int updateValue = (int) animation.getAnimatedValue();

//每次绘制的初始值改变,最终会停止到之前设置的角度数值

InitAngle = (updateValue % 360 + 360) % 360;

//重绘制

ViewCompat.postInvalidateOnAnimation(RotateView.this);

}

});

//动画监听,获取到具体的停留位置,这里处理随机位置,其实提前是知道的

animtor.addListener(new AnimatorListenerAdapter() {

@Override

public void onAnimationEnd(Animator animation) {

super.onAnimationEnd(animation);

int pos = InitAngle / 60;

if(pos >= 0 && pos <= 3){

pos = 3 - pos;

}else{

pos = (6-pos) + 3;

}

mOnCallBackPosition.getStopPosition(pos);

//可以回调出去,得到值

// Toast.makeText(context, strs.get(pos), Toast.LENGTH_SHORT).show();

}

});

animtor.start();

}

//由具体的位置,获取到角度

private int queryPosition(){

InitAngle = (InitAngle % 360 + 360) % 360;

int pos = InitAngle / verPanRadius;

if(panNum == 4) pos ++;

return calcumAngle(pos);

}

private int calcumAngle(int pos){

if(pos >= 0 && pos <= panNum/2){

pos = panNum/2 - pos;

}else{

pos = (panNum-pos) + panNum/2;

}

return pos;

}

如上所示,动画实现,采用了属性动画,多次绘制的方法,创造出旋转的效果

具体的使用如下

public class MainActivity extends AppCompatActivity {

private RotateView mRotateView;

List images=new ArrayList<>();

List names=new ArrayList<>();

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mRotateView = (RotateView) findViewById(R.id.rv_rotateview);

intDate();

mRotateView.setImageIcon(images);

mRotateView.setStrName(names);

findViewById(R.id.iv_start).setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

//-1为随机数或者指定位置,但必须小于总个数

mRotateView.startAnimation(-1);

}

});

//获取到位置

mRotateView.setOnCallBackPosition(new RotateView.onCallBackPosition() {

@Override

public void getStopPosition(int pos) {

Toast.makeText(MainActivity.this, "位置:"+names.get(pos), Toast.LENGTH_SHORT).show();

}

});

}

private void intDate() {

images.add(R.mipmap.role);

images.add(R.mipmap.sports);

images.add(R.mipmap.words);

images.add(R.mipmap.action);

images.add(R.mipmap.combat);

images.add(R.mipmap.moba);

names= Arrays.asList(getResources().getStringArray(R.array.name));

}

}

就可以实现旋转的大转盘。还有一部分外围的框,之后在添上,主要的大转盘抽奖功能是实现了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值