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