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

Kotlin+Firebase:点击地图Marker时在BottomSheet展示对应数据

实现方案

核心思路

通过Google Map Marker自带的tag属性绑定对应任务的唯一标识postid,点击Marker时将postid传入BottomSheet,再通过该标识查询Firebase对应数据渲染UI即可。

步骤1:修正导包错误

你当前代码导入了错误的Marker类,先替换导包:

// 删除错误导包
// import com.airbnb.lottie.model.Marker
// 导入地图Marker类
import com.google.android.gms.maps.model.Marker

步骤2:给Marker绑定postid

在添加Marker的逻辑中,将任务的postid存入Marker的tag属性:

dbref.addValueEventListener(object : ValueEventListener {
    override fun onDataChange(snapshot: DataSnapshot) {
        if (snapshot.exists()) {
            for (missionSnapshot in snapshot.children) {
                val lat: String = missionSnapshot.child("latitude").value.toString()
                val lng: String = missionSnapshot.child("longitude").value.toString()
                val latitude = lat.toDouble()
                val longitude = lng.toDouble()
                val loc = LatLng(latitude, longitude)
                val idMission = missionSnapshot.child("postid").value.toString()
                // 接收addMarker返回的Marker对象
                val marker = googleMap.addMarker(
                    MarkerOptions().position(loc)
                        .title(idMission).icon(
                            BitmapDescriptorFactory.fromResource(R.drawable.pinroll))
                )
                // 绑定postid到Marker
                marker?.tag = idMission
            }
        }
    }
    override fun onCancelled(error: DatabaseError) {
        TODO("Not yet implemented")
    }
})

步骤3:点击Marker时传参到BottomSheet

修改Marker点击监听逻辑,将绑定的postid传入BottomSheet:

googleMap.setOnMarkerClickListener(GoogleMap.OnMarkerClickListener { marker ->
    // 取出Marker绑定的postid
    val postId = marker.tag?.toString() ?: return@OnMarkerClickListener false
    // 通过newInstance方法传参创建BottomSheet实例
    val bottomSheet = BottomsheetMissionMap.newInstance(postId)
    bottomSheet.show(requireFragmentManager(), "BottomSheet")
    false
})

步骤4:BottomSheet接收参数并查询渲染数据

你的BottomsheetMissionMap实现参考如下:

class BottomsheetMissionMap : BottomSheetDialogFragment() {
    private lateinit var dbRef: DatabaseReference

    companion object {
        // 传参key常量
        private const val ARG_POST_ID = "post_id"
        
        // 统一实例创建方法,封装传参逻辑
        fun newInstance(postId: String): BottomsheetMissionMap {
            val args = Bundle()
            args.putString(ARG_POST_ID, postId)
            val fragment = BottomsheetMissionMap()
            fragment.arguments = args
            return fragment
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, 
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // 替换为你自己的BottomSheet布局id
        return inflater.inflate(R.layout.bottom_sheet_mission, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 获取传入的postid
        val postId = arguments?.getString(ARG_POST_ID) ?: return
        dbRef = FirebaseDatabase.getInstance().getReference("Mission")
        
        // 查询对应postid的任务数据
        dbRef.orderByChild("postid").equalTo(postId)
            .addListenerForSingleValueEvent(object : ValueEventListener {
                override fun onDataChange(snapshot: DataSnapshot) {
                    if (snapshot.exists()) {
                        for (missionSnap in snapshot.children) {
                            // 取出字段赋值到布局控件,示例如下,替换为你自己的字段和控件id
                            val missionTitle = missionSnap.child("title").value.toString()
                            val missionDesc = missionSnap.child("description").value.toString()
                            val missionPoint = missionSnap.child("point").value.toString()
                            
                            view.findViewById<TextView>(R.id.tv_mission_title).text = missionTitle
                            view.findViewById<TextView>(R.id.tv_mission_desc).text = missionDesc
                            view.findViewById<TextView>(R.id.tv_mission_point).text = "${missionPoint}积分"
                            // 其余字段同理赋值即可
                        }
                    }
                }

                override fun onCancelled(error: DatabaseError) {
                    // 按需添加查询失败的处理逻辑
                }
            })
    }
}

可选优化

如果不想每次点击Marker都查询数据库,可以提前在MapFragment中定义一个mutableMapOf<String, Mission>(),遍历Firebase数据时将所有任务数据存入Map,点击时直接取出对应Mission对象,通过Parcelable序列化后传给BottomSheet,减少数据库请求次数。

参考图示

  • Mission数据库结构:
    Mission数据库结构
  • BottomSheet展示效果:
    BottomSheet展示效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 09:45:03