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
相关产品推荐
相关产品推荐

