From 718f31c92e2029d05260810435a2c70cef6e6ce5 Mon Sep 17 00:00:00 2001 From: lmw <125975490@qq.com> Date: 星期四, 24 四月 2025 10:45:55 +0800 Subject: [PATCH] save --- app/src/main/java/com/sinata/xqmuse/ui/tree/TreeFragment.kt | 184 ++++++++++++++++++++++++++++++++++++--------- 1 files changed, 147 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/sinata/xqmuse/ui/tree/TreeFragment.kt b/app/src/main/java/com/sinata/xqmuse/ui/tree/TreeFragment.kt index 0ff6077..90bd32c 100644 --- a/app/src/main/java/com/sinata/xqmuse/ui/tree/TreeFragment.kt +++ b/app/src/main/java/com/sinata/xqmuse/ui/tree/TreeFragment.kt @@ -8,9 +8,9 @@ import cn.sinata.xldutils.fragment.BaseFragment import cn.sinata.xldutils.gone import cn.sinata.xldutils.visible +import com.danikula.videocache.CacheListener import com.github.penfeizhou.animation.apng.APNGDrawable import com.google.android.material.bottomsheet.BottomSheetBehavior -import com.luck.picture.lib.tools.SPUtils import com.sinata.xqmuse.MainActivity import com.sinata.xqmuse.R import com.sinata.xqmuse.dialog.TreeTipDialog @@ -21,15 +21,27 @@ import com.sinata.xqmuse.utils.AudioUtils import com.sinata.xqmuse.utils.Const import com.sinata.xqmuse.utils.ScreenUtil +import com.sinata.xqmuse.utils.cache.ProxyVideoCacheManager import com.sinata.xqmuse.utils.event.EmptyEvent import com.sinata.xqmuse.utils.extention.checkLogin import com.sinata.xqmuse.utils.extention.clickDelay +import com.sinata.xqmuse.utils.interfaces.StringCallback import kotlinx.android.synthetic.main.fragment_tree.* +import okhttp3.* import org.greenrobot.eventbus.EventBus import org.jetbrains.anko.support.v4.dip +import org.jetbrains.anko.support.v4.runOnUiThread import org.jetbrains.anko.support.v4.startActivity import org.jetbrains.anko.support.v4.toast +import retrofit2.Retrofit +import java.io.File +import java.io.FileOutputStream +import java.io.IOException +import java.io.InputStream +import java.net.HttpURLConnection +import java.net.URL import kotlin.math.max + class TreeFragment : BaseFragment() { override fun contentViewId() = R.layout.fragment_tree @@ -40,6 +52,7 @@ private val audioPlayer by lazy { AudioUtils() } //音频播放 private var tree:TreeInfo? = null + private val cacheDir by lazy { requireActivity().cacheDir } //常量 val GROWTH_ANIM_DURATION = 500L @@ -56,20 +69,24 @@ tv_rule.setOnClickListener { HttpManager.getH5(6).requestByF(this){ _, data-> data?.let { - startActivity<H5Activity>("title" to "规则说明","url" to it.content,"showClose" to false) + startActivity<H5Activity>( + "title" to "规则说明", + "url" to it.content, + "showClose" to false + ) } } } tv_sign.clickDelay { - HttpManager.sign().requestByF(this){_,data-> + HttpManager.sign().requestByF(this){ _, data-> tv_sign.isEnabled = false tv_sign.text = "已签到" tree?.energyValue = (tree?.energyValue?:0)+10 tree?.totalEnergyValue = (tree?.totalEnergyValue?:0)+10 tv_power.text = "当前能量值:${(tree?.energyValue?:0)}" signed.visible() - signed.postDelayed({signed.gone()},1500) + signed.postDelayed({ signed.gone() }, 1500) } } tv_to_think.setOnClickListener { @@ -79,7 +96,8 @@ EventBus.getDefault().post(EmptyEvent(Const.EventCode.SWITCH_HOME)) } iv_water.clickDelay { - showWater() +// showWater() +// return@clickDelay // tree?.energyValue = 0 // tree!!.treeLevelType++ // showTreeAnim(tree!!.getTreeApng(),true) @@ -92,14 +110,14 @@ else if (tree?.sowAgain == 1) toast("树苗已成熟,请重新播种") else - HttpManager.watering().requestByF(this){_,data-> + HttpManager.watering().requestByF(this){ _, data-> data?.apply { EventBus.getDefault().post(EmptyEvent(Const.EventCode.USER_INFO_CHANGED)) //刷新成长值 tv_max.text = "/$nextLevel" tv_growth.text = growthValue.toString() val targetHeight = growthValue.toDouble()/nextLevel*dip(155) val layoutParams = progress.layoutParams - showGrowthAnim(layoutParams.height, max(1,targetHeight.toInt())) + showGrowthAnim(layoutParams.height, max(1, targetHeight.toInt())) showWater() tree?.energyValue = energyValue tv_power.text = "当前能量值:${(tree?.energyValue?:0)}" @@ -107,7 +125,7 @@ showGrowUpDialog(data.treeLevelType) }else if (tree!!.status != 2){ tree!!.status = 2 - showTreeAnim(tree!!.getTreeApng(),tree!!.treeLevelType != 1) + showTreeAnim(tree!!.getTreeApng(), tree!!.treeLevelType != 1) } } } @@ -122,7 +140,7 @@ } tv_again.setOnClickListener { - HttpManager.restart().requestByF(this){_,_-> + HttpManager.restart().requestByF(this){ _, _-> getTree() } } @@ -148,7 +166,7 @@ private fun checkFirst() { if (checkLogin()) - HttpManager.isFirst().requestByF(this){_,data-> + HttpManager.isFirst().requestByF(this){ _, data-> if (data == true) showFirst() } @@ -157,12 +175,12 @@ /** * 依次弹窗升级和播放语音 */ - private fun showGrowUpDialog(targetLevel:Int){ + private fun showGrowUpDialog(targetLevel: Int){ tree!!.treeLevelType++ - showTreeAnim(tree!!.getTreeApng(),true) - audioPlayer.startPlayMusic(requireContext(),tree!!.getLevelUpAudio()) - val dialog = TreeTipDialog.show(childFragmentManager,"生命之树",tree!!.getLevelName()) - audioPlayer.setOnAudioStatusUpdateListener(object :AudioUtils.OnAudioStatusUpdateListener{ + showTreeAnim(tree!!.getTreeApng(), true) + audioPlayer.startPlayMusic(requireContext(), tree!!.getLevelUpAudio()) + val dialog = TreeTipDialog.show(childFragmentManager, "生命之树", tree!!.getLevelName()) + audioPlayer.setOnAudioStatusUpdateListener(object : AudioUtils.OnAudioStatusUpdateListener { override fun onUpdate(db: Double, time: Long) { } @@ -191,7 +209,7 @@ } fun getTree(){ - HttpManager.getUserTree().requestByF(this){_,data-> + HttpManager.getUserTree().requestByF(this){ _, data-> val changed = data?.treeLevelType != tree?.treeLevelType //等级发生变化 tree = data data?.apply { @@ -200,14 +218,14 @@ tv_growth.text = growthValue.toString() val targetHeight = growthValue.toDouble()/nextLevel*dip(155) val layoutParams = progress.layoutParams - showGrowthAnim(layoutParams.height, max(1,targetHeight.toInt())) + showGrowthAnim(layoutParams.height, max(1, targetHeight.toInt())) tv_sign.isEnabled = isSign == 2 tv_sign.text = if (tv_sign.isEnabled) "打卡签到" else "已签到" tv_to_think.isEnabled = taskOne == 2 tv_to_think_2.isEnabled = taskTwo == 2 if (status == 2){ if (changed) - showTreeAnim(getTreeApng(),treeLevelType != 1) + showTreeAnim(getTreeApng(), treeLevelType != 1) } else showTreeDead() } @@ -220,7 +238,7 @@ fun showFirst(){ if (!(activity as MainActivity).hasTreeFirstShow){ TreeTipDialog.show(childFragmentManager) - audioPlayer.startPlayMusic(requireContext(),Const.TREE.first) + audioPlayer.startPlayMusic(requireContext(), Const.VOICE_TREE.first) } } @@ -232,7 +250,7 @@ /** * 成长值动画 */ - private fun showGrowthAnim(start:Int,end:Int){ + private fun showGrowthAnim(start: Int, end: Int){ val ofInt = ValueAnimator.ofInt(start, end) ofInt.duration = GROWTH_ANIM_DURATION ofInt.addUpdateListener { @@ -244,31 +262,123 @@ } private fun showWater(){ - val apngDrawable = APNGDrawable.fromAsset(requireContext(),"apngb_water.png") - iv_water_anim.setImageDrawable(apngDrawable) - apngDrawable.setLoopLimit(2) - apngDrawable.registerAnimationCallback(object :Animatable2Compat.AnimationCallback(){ - override fun onAnimationEnd(drawable: Drawable?) { - super.onAnimationEnd(drawable) - iv_water_anim.setImageResource(0) +// val apngDrawable = APNGDrawable.fromAsset(requireContext(),"apngb_water.png") +// iv_water_anim.setImageDrawable(apngDrawable) +// apngDrawable.setLoopLimit(2) +// apngDrawable.registerAnimationCallback(object : Animatable2Compat.AnimationCallback(){ +// override fun onAnimationEnd(drawable: Drawable?) { +// super.onAnimationEnd(drawable) +// iv_water_anim.setImageResource(0) +// } +// }) + showOrDownApng(Const.APNG_TREE.WATER,object :StringCallback{ + override fun onResult(rst: String) { + waterAnim() + } + }) + } + + private fun showOrDownApng(url:String,callback: StringCallback){ + if (isFileCached(url)){ + callback.onResult("") + }else + downloadFileToCache(url,callback) + } + + private fun waterAnim(){ + val apngDrawable = APNGDrawable.fromFile(getCachedFile(Const.APNG_TREE.WATER)?.absolutePath) + runOnUiThread { + iv_water_anim.setImageDrawable(apngDrawable) + apngDrawable.setLoopLimit(2) + apngDrawable.registerAnimationCallback(object : Animatable2Compat.AnimationCallback(){ + override fun onAnimationEnd(drawable: Drawable?) { + super.onAnimationEnd(drawable) + iv_water_anim.setImageResource(0) + } + }) + } + } + + // 获取缓存文件路径 + fun getCachedFile(url: String): File? { + val cacheDir = requireActivity().cacheDir + val file = File(cacheDir, url.substring(url.lastIndexOf("/"))) + return if (file.exists()) file else null + } + + // 检查文件是否已缓存 + fun isFileCached(url: String): Boolean { + return getCachedFile(url) != null + } + + fun downloadFileToCache(url: String,callback: StringCallback) { + val client = OkHttpClient() + val request = Request.Builder().url(url).build() + + client.newCall(request).enqueue(object : okhttp3.Callback { + override fun onFailure(call: okhttp3.Call, e: IOException) { + // 下载失败处理 + e.printStackTrace() + } + + override fun onResponse(call: Call, response: Response) { + if (!response.isSuccessful) { + throw IOException("下载失败: ${response.code()}") + } + + // 获取内部缓存目录 + val cacheDir = requireActivity().cacheDir + val outputFile = File(cacheDir, url.substring(url.lastIndexOf("/") + 1)) + if (outputFile.exists() && outputFile.isDirectory) { + // 删除目录或调整文件名 + outputFile.delete() + } + try { + // 将文件写入缓存 + val inputStream = response.body()?.byteStream() + val outputStream = FileOutputStream(outputFile) + inputStream?.use { input -> + outputStream.use { output -> + input.copyTo(output) + } + } + // 下载成功,文件路径为 outputFile.absolutePath + callback.onResult("") + } catch (e: Exception) { + e.printStackTrace() + } } }) } private fun showSunshine(){ - val apngDrawable = APNGDrawable.fromAsset(requireContext(),"sunshine.png") - iv_sunshine.setImageDrawable(apngDrawable) + showOrDownApng(Const.APNG_TREE.SUNSHINE,object :StringCallback{ + override fun onResult(rst: String) { + runOnUiThread { + val apngDrawable = APNGDrawable.fromFile(getCachedFile(Const.APNG_TREE.SUNSHINE)?.absolutePath) + iv_sunshine.setImageDrawable(apngDrawable) + } + } + }) +// val apngDrawable = APNGDrawable.fromAsset(requireContext(), "sunshine.png") +// iv_sunshine.setImageDrawable(apngDrawable) // apngDrawable.setLoopLimit(5) } - private fun showTreeAnim(resStr:String,isLoop:Boolean){ - val apngDrawable = APNGDrawable.fromAsset(requireContext(),resStr) - iv_tree.setImageDrawable(apngDrawable) - apngDrawable.setLoopLimit(if (isLoop) -1 else 1) - if (tree?.treeLevelType?:0 >= 10) - tv_again.visible() - else - tv_again.gone() + private fun showTreeAnim(resStr: String, isLoop: Boolean){ + showOrDownApng(resStr,object :StringCallback{ + override fun onResult(rst: String) { + runOnUiThread { + val apngDrawable = APNGDrawable.fromFile(getCachedFile(resStr)?.absolutePath) + iv_tree.setImageDrawable(apngDrawable) + apngDrawable.setLoopLimit(if (isLoop) -1 else 1) + if (tree?.treeLevelType?:0 >= 10) + tv_again.visible() + else + tv_again.gone() + } + } + }) } override fun onPause() { -- Gitblit v1.7.1