Android实现幸运大转盘功能

2022-02-25  本文已影响0人  SeekLife0
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
        }
    }
上一篇下一篇

猜你喜欢

热点阅读