Android实现幸运大转盘功能
2022-02-25 本文已影响0人
SeekLife0
image.png
参考:https://blog.csdn.net/lwang057/article/details/78829137
image.png
参考:https://blog.csdn.net/lwang057/article/details/78829137
功能概述:
旋转之后根据随机数来影响最后指针停留的位置,也就是旋转的角度。有两种转法,指针转和转盘转,这里是转盘转,转起来后有一个跑马灯的效果。
布局:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/scroll_view_wheel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="false"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@mipmap/totary_background"
android:orientation="vertical">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="230dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_circle"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/ll_center"
android:layout_width="10dp"
android:layout_height="10dp"
android:orientation="vertical"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<ImageView
android:id="@+id/iv_circle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_gravity="center"
android:src="@mipmap/rotary_circle"
android:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
<ImageView
android:id="@+id/rotary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_gravity="center"
android:layout_marginTop="93dp"
android:src="@mipmap/rotary_pointer"
android:visibility="visible" />
<LinearLayout
android:id="@+id/ll_start_rotate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_gravity="center"
android:layout_marginTop="150dp"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="@+id/tv_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0次机会"
android:textSize="11dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="抽奖"
android:textColor="#FF3030"
android:textSize="20dp" />
</LinearLayout>
</RelativeLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@mipmap/box" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:orientation="vertical">
</LinearLayout>
</FrameLayout>
</LinearLayout>
</ScrollView>
动画文件:
image.png
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:fromDegrees="0"
android:toDegrees="359"
android:pivotX="50%"
android:pivotY="50%"
android:duration="2000"
android:repeatCount="-1">
</rotate>
</rotate>
Activity文件(kotlin):
@Layout(R.layout.activity_rotary)
class MyRotaryActivity : BaseActivity(),View.OnClickListener {
//找到需要旋转的组件
@BindView(R.id.cl_circle)
lateinit var clCircle : ConstraintLayout
//抽奖按钮
@BindView(R.id.ll_start_rotate)
lateinit var startRotate : LinearLayout
//初始化一些必要的属性
lateinit var mStartAnimation : Animation
private lateinit var mEndAnimation : Animation
fun isEndAnimation()=::mEndAnimation.isInitialized
private var isRunning = false
private var mPrizeGrade = 8 //奖品级别,0代表没有
private var mItemCount = 8
//4,7->金币1个 88% //2->金币50 10% //3->爱奇艺 0.5% //5->绿萝 0.5% //6->口罩 1% //0->苹果 0% //->京东 0%
private var mPrizePosition = arrayListOf<Int>(4, 7, 2, 3, 5, 6, 0, 1) //奖品在转盘中的位置(到达一等奖的距离)
//抽奖数据(一般情况下抽奖数据需要请求服务器获取,随机概率也可以由服务端做)
private var data = LuckyWheelData.Data()
override fun initViews() {
//初始化动画
mStartAnimation = AnimationUtils.loadAnimation(this, R.anim.rotary_anim)
val acc = AccelerateInterpolator()
mStartAnimation.interpolator = acc
}
override fun initDatas(parameter: JumpParameter?) {
}
@RequiresApi(Build.VERSION_CODES.M)
override fun setEvents() {
//抽奖监听
startRotate.setOnClickListener(this)
}
//设置的点击事件,点击中间抽奖启动旋转动画
override fun onClick(v: View?) {
//如果抽奖次数大于0那么可以抽奖
if(data.surplusLuckDrawCount > 0){
isRunning = true
//禁止点击抽奖,抽奖完成后可以点击
startRotate.isClickable = false
}else{
isRunning = false
ToastUtils.showShort("没有抽奖次数了")
}
// 未抽过奖并有抽奖的机会
if (isRunning) {
//请求后台传递的抽取物品,根据抽取物品来选择realPositin就行了
// requestStart()
//直接开转
//重置转盘开始旋转
isRunning = false;
mStartAnimation.reset();
clCircle.startAnimation(mStartAnimation)
if(isEndAnimation()){
mEndAnimation.cancel()
}
Handler().postDelayed(Runnable {
endAnimation()
},1000)
}
}
}
// 结束动画,慢慢停止转动,抽中的奖品定格在指针指向的位置
private fun endAnimation() {
var position = mPrizePosition[0] //mPrizeGrade - 1
//最垃圾奖品位置计算
var toDegreeMin = 360 / mItemCount * (position - 0.5f + 1 )
var random = Random()
// //举例,随机从100里面取一个整数,小于88就1金币
var realPosition = 0
var randomInt = random.nextInt(200)
var endString = ""
if(randomInt < 88){
//转到1金币
realPosition = 45 * 5
endString = "转到1金币 - 黄色"
}else if(randomInt in 88..176){
//转到1金币
realPosition = 0
endString = "转到1金币 - 白色"
}else if(randomInt in 176..196){
//转到金币50
realPosition = 45 * 2
endString = "转到金币50"
}else if(randomInt in 196..197){
//爱奇艺
// realPosition = 45
//转到金币50
realPosition = 45 * 2
endString = "爱奇艺"
}else if(randomInt in 197..198){
//绿萝
// realPosition = 45 * 7
//转到金币50
realPosition = 45 * 2
endString = "绿萝"
}else if(randomInt in 198..200){
//口罩
// realPosition = 45 * 6
//转到金币50
realPosition = 45 * 2
endString = "口罩"
}
var toDegree = toDegreeMin + realPosition + 360 * 3; //5周 + 偏移量
// 按中心点旋转 toDegree 度
// 参数:旋转的开始角度、旋转的结束角度、X轴的伸缩模式、X坐标的伸缩值、Y轴的伸缩模式、Y坐标的伸缩值
mEndAnimation = RotateAnimation(0F, toDegree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
mEndAnimation.setDuration(3000) // 设置旋转时间
mEndAnimation.setRepeatCount(0) // 设置重复次数
mEndAnimation.setFillAfter(true)// 动画执行完后是否停留在执行完的状态
mEndAnimation.setInterpolator(DecelerateInterpolator()) // 动画播放的速度
mEndAnimation.setAnimationListener(object : Animation.AnimationListener{
override fun onAnimationStart(animation: Animation?) {
}
override fun onAnimationEnd(animation: Animation?) {
isRunning = false
startRotate.isClickable = true
// ToastUtils.showShort(endString)
showPopup(endString)
}
override fun onAnimationRepeat(animation: Animation?) {
}
})
clCircle.startAnimation(mEndAnimation)
mStartAnimation.cancel()
}
//停止动画(异常情况,没有奖品)
fun stopAnimation() {
//转盘停止回到初始状态
if (isRunning) {
mStartAnimation.cancel()
// mLuckyTurntable.clearAnimation();
clCircle.clearAnimation()
isRunning = false
}
}