From 442124baa483f8d1c4aaca7ff81e15dd3f122363 Mon Sep 17 00:00:00 2001
From: 罗明文 <125975490@qq.com>
Date: 星期四, 22 五月 2025 13:14:36 +0800
Subject: [PATCH] save

---
 app/src/main/java/com/dollearn/student/ui/home/SuperListenActivity.kt |  333 ++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 256 insertions(+), 77 deletions(-)

diff --git a/app/src/main/java/com/dollearn/student/ui/home/SuperListenActivity.kt b/app/src/main/java/com/dollearn/student/ui/home/SuperListenActivity.kt
index e3332e5..0b82f27 100644
--- a/app/src/main/java/com/dollearn/student/ui/home/SuperListenActivity.kt
+++ b/app/src/main/java/com/dollearn/student/ui/home/SuperListenActivity.kt
@@ -1,13 +1,20 @@
 package com.dollearn.student.ui.home
 
+import android.R.attr.animation
+import android.R.attr.max
+import android.animation.Animator
+import android.animation.ObjectAnimator
+import android.animation.PropertyValuesHolder
+import android.animation.ValueAnimator
 import android.os.Handler
 import android.os.Looper
 import android.os.Message
 import android.util.Log
 import android.view.View
+import android.view.animation.LinearInterpolator
 import androidx.recyclerview.widget.GridLayoutManager
 import cn.sinata.xldutils.gone
-import cn.sinata.xldutils.utils.myToast
+import cn.sinata.xldutils.utils.SPUtils
 import cn.sinata.xldutils.visible
 import com.dollearn.student.R
 import com.dollearn.student.dialog.CountdownDialog
@@ -19,100 +26,122 @@
 import com.dollearn.student.ui.TransparentStatusBarActivity
 import com.dollearn.student.ui.home.adapter.GameAdapter
 import com.dollearn.student.utils.AudioUtils
+import com.dollearn.student.utils.Const
+import com.dollearn.student.utils.event.EmptyEvent
 import com.dollearn.student.utils.interfaces.StringCallback
 import kotlinx.android.synthetic.main.activity_super_listen.*
+import kotlinx.android.synthetic.main.fragment_q_a.*
 import kotlinx.android.synthetic.main.fragmetn_look_img.*
+import kotlinx.android.synthetic.main.item_game_1.view.*
+import org.greenrobot.eventbus.EventBus
+import org.jetbrains.anko.dip
+import kotlin.math.abs
+import kotlin.math.max
+import kotlin.math.min
+import kotlin.math.sqrt
+
 
 class SuperListenActivity : TransparentStatusBarActivity(), AudioUtils.OnAudioStatusUpdateListener {
     override fun setContentView() = R.layout.activity_super_listen
 
-
+    val level by lazy { //0就只能点入门,1就是入门和中级都能点,2就是入门、中级高级三个难度都可以点
+        intent.getIntExtra("level", 0)
+    }
     private val week by lazy {
-        intent.getIntExtra("week",0)
+        intent.getIntExtra("week", 0)
     }
     private val season by lazy {
-        intent.getIntExtra("season",0)
+        intent.getIntExtra("season", 0)
     }
-    private var data:GameBean? = null
-    private var index = 0
-    private var handler:Handler? = null
+    var data:GameBean? = null
+    var index = 0
+    var handler:Handler? = null
 
     private var difficulty = 0 //难度
 
-    private val TAG = "Listen====>"
+    val TAG = "Listen====>"
 
-    private val list = arrayListOf<Subject>()
+    var list = arrayListOf<Subject>()
     private val adapter = GameAdapter(list)
 
-    private val PLAY_VOICE = 1
-    private val COUNT_DOWN = 2
+    val PLAY_VOICE = 1
+    val COUNT_DOWN = 2
     private val STUDY_TIME = 3
+
+    val PLAY_RIGHT = 4
+    val PLAY_ERROR = 5
+
+    private val errorVoice by lazy { SPUtils.instance().getString(Const.EV) }
+    private val rightVoice by lazy { SPUtils.instance().getString(Const.RV) }
+
+    private var rightPlaying = false
+    private var errorPlaying = false
 
     private val player by lazy { AudioUtils() }
 
-    private val voiceList = arrayListOf<String>() //声音按顺序播放
+    val voiceList = arrayListOf<String>() //声音按顺序播放
 
     private var TIME = 10 //每题答题时间
-    private var countTime = 10 //倒计时计数
+    private var countTime = 0 //倒计时计数
 
-    var totalCount = 0 //总答题次数
     var rightCount = 0 //正确答题次数
     var time = 0 //学习秒数
 
+    var playing = false
+
+    var state = 0 //0:准备听题 1:听题中 2:请作答 3:结束答题
+
+    var showFullImage = false
+    var paused = false
+
     override fun initClick() {
-        adapter.setOnItemClickListener { view, position ->
-            Log.e(TAG,"点击图片:${list[position].name}")
-            Log.e(TAG,"音频position:${index}")
-            Log.e(TAG,"音频路径:${voiceList[index]}")
-
-            val subject = data!!.subjectList[data!!.subjectList.map { it.correct }.indexOf(voiceList[index])] //当前音频对应题目
-            Log.e(TAG,"正确答案:${subject.name}")
-
-            totalCount++
-
-            handler?.removeMessages(COUNT_DOWN) //选择答案后,停止倒计时
-            if (list[position].id == subject.id){
-                rightCount++
-                subject.completed = true
-                subject.right = true
-                handler?.sendEmptyMessage(PLAY_VOICE)
-                adapter.notifyItemChanged(position)
-            }else{
-                subject.completed = true
-                subject.right = false
-                index++
-                startGame()
-            }
-        }
-
         tv_exit.setOnClickListener {
             if (tv_exit.text == "提交"){
-                ResultActivity.startResult(this,0,0,0,6,totalCount,rightCount,list.filter { it.right }.sumBy { 1 },time,data!!.data.id)
+                ResultActivity.startResult(
+                    this,
+                    0,
+                    0,
+                    0,
+                    6,
+                    list.size,
+                    rightCount,
+                    list.filter { it.right }.sumBy { 1 },
+                    time,
+                    data!!.data.id,
+                    difficulty
+                )
                 finish()
             }else
-                finish()
+                onBackPressed()
+        }
+
+        cl_voice.setOnClickListener {
+            if (!playing){
+                handler?.sendEmptyMessage(PLAY_VOICE)
+            }
         }
     }
 
     override fun initView() {
         tv_sort.postDelayed({
-             val difficultyDialog = DifficultyDialog()
-            difficultyDialog.setCallback(object :DifficultyDialog.OnClickCallback{
+            val difficultyDialog = DifficultyDialog()
+            difficultyDialog.setCallback(object : DifficultyDialog.OnClickCallback {
                 override fun onOk(d: Int) {
                     difficulty = d
-                    HttpManager.gameHearing(season,week,difficulty).request(this@SuperListenActivity){_,data->
-                        difficultyDialog.dismissAllowingStateLoss()
-                        this@SuperListenActivity.data = data
-                        refreshUi()
-                    }
+                    HttpManager.gameHearing(season, week, difficulty)
+                        .request(this@SuperListenActivity) { _, data ->
+                            difficultyDialog.dismissAllowingStateLoss()
+                            this@SuperListenActivity.data = data
+                            refreshUi()
+                        }
                 }
 
                 override fun onCancel() {
                     finish()
                 }
             })
-            difficultyDialog.show(supportFragmentManager,"dif")
-        },500)
+            difficultyDialog.show(supportFragmentManager, "dif")
+        }, 500)
 
         player.setOnAudioStatusUpdateListener(this)
         player.stopPlayMusic()
@@ -120,66 +149,170 @@
             override fun handleMessage(msg: Message) {
                 super.handleMessage(msg)
                 when(msg.what){
-                    STUDY_TIME->{
+                    STUDY_TIME -> {
                         time++
-                        sendEmptyMessageDelayed(STUDY_TIME,1000)
+                        sendEmptyMessageDelayed(STUDY_TIME, 1000)
                     }
-                    PLAY_VOICE->{
-                        if (index<voiceList.size)
-                            player.startPlayMusic(this@SuperListenActivity,voiceList[index])
-                    }
-                    COUNT_DOWN->{
-                        countTime --
-                        tv_tip.text = "请在${countTime}s内选择答案!"
-                        if ( countTime == 0){
-                            index++
-                            startGame()
-                        }else{
-                            sendEmptyMessageDelayed(COUNT_DOWN,1000)
+                    PLAY_VOICE -> {
+                        if (!paused&&!playing&&index < voiceList.size) {
+                            playing = true
+                            player.startPlayMusic(this@SuperListenActivity, voiceList[index])
                         }
+                    }
+                    COUNT_DOWN -> {
+                        if (!playing) {
+                            countTime--
+                            state = 2
+                        }
+                        tv_tip.text = "请在${countTime}s内选择答案!"
+                        if (countTime == 0) {
+                            index++
+                            startGame(true)
+                        } else {
+                            sendEmptyMessageDelayed(COUNT_DOWN, 1000)
+                        }
+                    }
+                    PLAY_RIGHT -> {
+                        playing = true
+                        rightPlaying = true
+                        player.startPlayMusic(this@SuperListenActivity, rightVoice)
+                    }
+                    PLAY_ERROR -> {
+                        playing = true
+                        errorPlaying = true
+                        player.startPlayMusic(this@SuperListenActivity, errorVoice)
                     }
                 }
             }
         }
+        handler?.sendEmptyMessageDelayed(STUDY_TIME, 1000)
     }
 
     private fun refreshUi() {
-        rv_list.layoutManager = GridLayoutManager(this,5)
+        cl_voice.visible()
+        tv_sort.visible()
+        tv_exit.visible()
+        tv_tip.text = "准备听题"
         list.clear()
-        list.addAll(data?.subjectList?: arrayListOf())
+        list.addAll(data?.subjectList ?: arrayListOf())
+        initRecycler(list.size)
         voiceList.clear()
         voiceList.addAll(list.map { it.correct }) //声音顺序
-        Log.e(TAG,"声音顺序:${voiceList.joinToString(",,,") { it }}")
+        Log.e(TAG, "声音顺序:${voiceList.joinToString(",,,") { it }}")
         list.shuffle() //图片随机顺序
         rv_list.adapter = adapter
-        Log.e(TAG,"图片打乱后顺序:${list.joinToString(",,,") { it.name }}")
-
+        Log.e(TAG, "图片打乱后顺序:${list.joinToString(",,,") { it.name }}")
+        TIME = data!!.data.time.toInt()
         val countdownDialog = CountdownDialog()
         countdownDialog.callback = object :StringCallback{
             override fun onResult(rst: String) {
                 index = 0
-                startGame()
+                startGame(true)
             }
         }
-        countdownDialog.show(supportFragmentManager,"timer")
+        countdownDialog.show(supportFragmentManager, "timer")
     }
 
-    private fun startGame() {
+    /**
+     * 需要计算行列数
+     */
+    private fun initRecycler(total: Int){
+        var bestRows = 1
+        var bestColumns: Int = total
+        var i = 1
+        while (i <= sqrt(total.toDouble())) {
+            val rows = i
+            val columns: Int = if (total%i>0) (total / i)+1 else total / i
+            // Calculate the absolute difference between rows and columns
+            val diff = abs(rows - columns)
+            // Update the best rows and columns if this pair has a smaller difference
+            if (diff < abs(bestRows - bestColumns)) {
+                bestRows = rows
+                bestColumns = columns
+            }
+            i++
+        }
+        Log.e(TAG, "总数:$total,计算得到行数:${min(bestColumns, bestRows)},列数:${max(bestColumns, bestRows)}")
+        val lineHeight = rv_list.height.toDouble() / min(bestColumns, bestRows)
+        Log.e(TAG, "高度:${rv_list.height},计算得到行高:${lineHeight}")
+        rv_list.layoutManager = GridLayoutManager(this, max(bestColumns, bestRows))
+        adapter.height = lineHeight.toInt()
+        adapter.notifyDataSetChanged()
+    }
+
+    /**
+     * 切题
+     * @param playNow true:表示立即播放下一题  false:3秒后播放下一题
+     */
+    fun startGame(playNow: Boolean = false) {
         if (index < voiceList.size){
-            Log.e(TAG,"开始答题:index=${index}")
+            Log.e(TAG, "开始答题:index=${index}")
             tv_sort.text = (index+1).toString()
             handler?.removeMessages(COUNT_DOWN)
             countTime = TIME //重置答题时间
             tv_tip.text = "准备听题"
-            handler?.sendEmptyMessageDelayed(PLAY_VOICE,3000)
+            state = 0
+            handler?.sendEmptyMessageDelayed(PLAY_VOICE, if (playNow) 200 else 1000)
         }else{
             tv_sort.visibility = View.INVISIBLE
+            cl_voice.visibility = View.INVISIBLE
             tv_tip.text = ""
+            state = 3
             tv_end.text = "已完成全部问题"
             tv_exit.text = "提交"
             handler?.removeMessages(STUDY_TIME)
         }
     }
+
+    fun transAnimation(endView: View){
+        val offx = getScreenX(endView) - getScreenX(cl_voice)
+        val offy = getScreenY(endView) - getScreenY(cl_voice)
+        val x = PropertyValuesHolder.ofFloat("translationX", 0f, offx.toFloat())
+        val y = PropertyValuesHolder.ofFloat("translationY", 0f, offy.toFloat())
+        val animator = ObjectAnimator.ofPropertyValuesHolder(cl_voice, x, y)
+        animator.duration = 500
+        animator.interpolator = LinearInterpolator()
+        val withAnim = ValueAnimator.ofInt(cl_voice.width, endView.width).setDuration(500) //会影响结束坐标
+        withAnim.addUpdateListener {
+            cl_voice.layoutParams.width = it.animatedValue as Int
+            cl_voice.requestLayout()
+        }
+        val heightAnim = ValueAnimator.ofInt(cl_voice.height, endView.height).setDuration(500)
+        heightAnim.addUpdateListener {
+            cl_voice.layoutParams.height = it.animatedValue as Int
+            cl_voice.requestLayout()
+        }
+        withAnim.start()
+        heightAnim.start()
+        animator.start()
+        animator.addListener(object : Animator.AnimatorListener {
+            override fun onAnimationStart(animation: Animator?) {
+
+            }
+
+            override fun onAnimationEnd(animation: Animator?) {
+                endView.visible()
+            }
+
+            override fun onAnimationCancel(animation: Animator?) {
+            }
+
+            override fun onAnimationRepeat(animation: Animator?) {
+            }
+        })
+    }
+
+    private fun getScreenY(v: View):Int{
+        val xy = IntArray(2)
+        v.getLocationOnScreen(xy)
+        return xy[1]
+    }
+    private fun getScreenX(v: View):Int{
+        val xy = IntArray(2)
+        v.getLocationOnScreen(xy)
+        return xy[0]
+    }
+
 
     override fun onUpdate(db: Double, time: Long) {
     }
@@ -188,9 +321,14 @@
     }
 
     override fun onStartPlay() {
-        if (!data!!.subjectList[data!!.subjectList.map { it.correct }.indexOf(voiceList[index])].completed){//首次播放
+        playing = true
+        if (errorPlaying||rightPlaying)
+            return
+//        if (!data!!.subjectList[data!!.subjectList.map { it.correct }.indexOf(voiceList[index])].completed){//首次播放
+        if (handler?.hasMessages(COUNT_DOWN) == false){//首次播放
+            state = 1
             tv_tip.text = "请在${countTime}s内选择答案!"
-            handler?.sendEmptyMessageDelayed(COUNT_DOWN,1000)
+            handler?.sendEmptyMessageDelayed(COUNT_DOWN, 1000)
         }
         iv1.gone()
         iv2.gone()
@@ -198,13 +336,54 @@
     }
 
     override fun onFinishPlay() {
+        playing = false
         iv1.visible()
         iv2.visible()
         iv_playing.gone()
-        if (data!!.subjectList[data!!.subjectList.map { it.correct }.indexOf(voiceList[index])].completed){ //当前题目已作答,3秒后进入下一题
+        if (data!!.subjectList[data!!.subjectList.map { it.correct }.indexOf(voiceList[min(index,voiceList.lastIndex)])].completed){ //当前题目已作答,3秒后进入下一题
             index++
             startGame()
         }
+        if (errorPlaying)
+            errorPlaying = false
+        else if (rightPlaying){
+            rightPlaying = false
+            cl_voice.translationX = 0f
+            cl_voice.translationY = 0f
+            cl_voice.layoutParams.width = dip(159)
+            cl_voice.layoutParams.height = dip(52)
+            cl_voice.requestLayout()
+        }else{
+
+        }
     }
 
+    override fun onBackPressed() {
+        HttpManager.exitGameOrStory(time).request(this){ _, _->
+            super.onBackPressed()
+        }
+    }
+
+    override fun onDestroy() {
+        super.onDestroy()
+        handler?.removeCallbacksAndMessages(null)
+        EventBus.getDefault().post(EmptyEvent(Const.EventCode.STOP_TIMER))
+    }
+
+    override fun onResume() {
+        super.onResume()
+        if (paused){
+            paused = false
+            handler?.sendEmptyMessageDelayed(PLAY_VOICE, 200)
+        }
+    }
+
+    override fun onPause() {
+        super.onPause()
+        if (!showFullImage){
+            player.stopPlayMusic()
+            paused = true
+        }
+        showFullImage = false
+    }
 }

--
Gitblit v1.7.1