lmw
2025-04-24 718f31c92e2029d05260810435a2c70cef6e6ce5
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,7 +69,11 @@
        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
                    )
                }
            }
        }
@@ -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)
@@ -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)
        }
    }
@@ -244,7 +262,32 @@
    }
    private fun showWater(){
        val apngDrawable = APNGDrawable.fromAsset(requireContext(),"apngb_water.png")
//        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(){
@@ -254,15 +297,79 @@
            }
        })
    }
    }
    // 获取缓存文件路径
    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")
        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)
        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)
@@ -270,6 +377,9 @@
        else
            tv_again.gone()
    }
            }
        })
    }
    override fun onPause() {
        super.onPause()