You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fragment实现侧边菜单抽屉及Activity折线图代码迁移适配求助

适配完成的ChartFragment完整代码
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.view.GravityCompat
import androidx.fragment.app.Fragment
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
import com.github.mikephil.charting.utils.Easing
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStreamReader
import java.util.Collections

// 替换为你自己项目的FragmentChartBinding包路径
import com.yourpackage.databinding.FragmentChartBinding

class ChartFragment : Fragment() {
    private var _binding: FragmentChartBinding? = null
    private val binding get() = _binding!!

    // Activity Result必须注册为类成员,不可写在onCreateView内
    private val getContent = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
        val lines = readCSV(uri)
        val newEntries = lines.map { line -> toEntry(line) }
            .groupingBy { entry -> entry.x }
            .reduce { _, accumulator, element ->
                if (accumulator.y > element.y) accumulator else element
            }.values
        val vl = LineDataSet(newEntries.toList().take(4000), "cost")
        vl.setDrawValues(false)
        vl.setDrawFilled(true)
        vl.lineWidth = 1.5f
        vl.fillColor = R.color.gray
        vl.fillAlpha = R.color.red
        vl.setDrawCircles(false)
        binding.lineChart.data = LineData(vl)
        binding.lineChart.notifyDataSetChanged()
        binding.lineChart.animateX(1800, Easing.EaseInExpo)
        binding.lineChart.description.isEnabled = false
        binding.lineChart.isHighlightPerDragEnabled = false
        binding.lineChart.isScaleYEnabled = false
        binding.lineChart.axisRight.isEnabled = false
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?,
    ): View {
        _binding = FragmentChartBinding.inflate(inflater, container, false)

        // CSV加载按钮点击逻辑
        binding.btnLoadCsv.setOnClickListener {
            val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
            intent.addCategory(Intent.CATEGORY_OPENABLE)
            intent.type = "text/*"
            getContent.launch("text/*")
        }

        // 折线图标记初始化
        val markerView = CustomMarker(requireContext(), R.layout.marker_view)
        binding.lineChart.marker = markerView

        // 如需在Fragment内打开侧边抽屉,添加如下逻辑(宿主Activity需已实现DrawerLayout)
        // binding.btnOpenDrawer.setOnClickListener {
        //     (requireActivity() as MainActivity).drawerLayout.openDrawer(GravityCompat.START)
        // }

        return binding.root
    }

    override fun onDestroyView() {
        super.onDestroyView()
        // 调整Binding回收时机到View销毁时,避免内存泄漏
        _binding = null
    }

    @Throws(IOException::class)
    fun readCSV(uri: Uri?): List<String> {
        if (uri != null) {
            val csvFile = requireContext().contentResolver.openInputStream(uri)
            val isr = InputStreamReader(csvFile)
            return BufferedReader(isr).readLines()
        }
        return Collections.emptyList()
    }

    private fun toEntry(line: String): Entry {
        val split = line.split(";")
        val time = split[1]
        val secondsStartIdx = time.length - 2
        val minutesStartIdx = time.length - 4
        val hoursStartIdx = (time.length - 6).coerceAtLeast(0)

        val hour = time.substring(hoursStartIdx, hoursStartIdx + time.length - 4)
        val minutest = time.substring(minutesStartIdx, minutesStartIdx + 2)
        val seconds = time.substring(secondsStartIdx, secondsStartIdx + 2)

        val newTime =
            hour.toFloat() * 10000 + (minutest.toFloat() * 100 / 60).toInt() * 100 + (seconds.toFloat() * 100 / 60).toInt()
        return Entry(newTime, split[2].toFloat())
    }
}
核心适配说明
  • 你提供的XML布局文件无需任何改动,控件ID与代码完全匹配
  • 调整了Activity Result的注册位置,符合Fragment的API规范,避免运行时崩溃
  • 所有Context相关调用替换为requireContext()获取的合法宿主上下文
  • 调整ViewBinding的回收时机为onDestroyView,符合Fragment生命周期规范,避免内存泄漏
  • 保留原Activity全部业务逻辑,功能与原有实现完全一致
  • 侧边抽屉默认由宿主Activity的DrawerLayout实现,代码中已给出Fragment内调用打开抽屉的示例,取消注释并补充对应按钮即可使用

内容的提问来源于stack exchange,提问作者MaksChojniak1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 12:18:04