如何从Map<String, List<String>>中获取数组值并传入setOnMarkerClickListener
问题1:读取图片数组第0项替换Marker自定义图标
你存储在CamperSiteImages字段的是标准的HTTP图片链接,不是Base64编码内容,所以不需要用Base64解码,直接从Map中取出数组后取下标0的值即可,再通过图片加载库(比如Glide)将网络图片转成Bitmap设置为Marker图标即可。
取值方式:
// 取出图片数组 List<String> imageList = (List<String>) map.get("CamperSiteImages"); // 取第0项,加判空避免崩溃 String firstImageUrl = imageList != null && !imageList.isEmpty() ? imageList.get(0) : "";
问题2:点击Marker获取对应PostID
谷歌地图的Marker支持存储任意类型的Tag,你可以在创建Marker的时候把PostID设置为Marker的Tag,点击事件中直接读取Tag就能拿到对应的PostID。另外不要在循环里重复设置setOnMarkerClickListener,全局只需要设置一次监听器即可。
修正后的完整代码
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Campsite"); // 先全局设置Marker点击监听器,只设置一次 mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() { @Override public boolean onMarkerClick(Marker marker) { // 读取Tag获取PostID String postId = (String) marker.getTag(); if(postId != null) { Toast.makeText(getContext(), postId, Toast.LENGTH_SHORT).show(); } // 返回false会继续弹出Marker的title,返回true则不会 return false; } }); // 注意:你的Firebase字段名是拼写错误的Counrty,不是country,这里要和字段名一致才能查到数据 Query query = reference.orderByChild("Counrty").equalTo(country); query.addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String previousChildName) { Map<String, Object> map = (Map<String, Object>) dataSnapshot.getValue(); if(map == null) return; Double lat = (Double)map.get("CamperSiteLatitude"); Double lng = (Double)map.get("CamperSiteLongitude"); if(lat == null || lng == null) return; LatLng newLocation = new LatLng(lat, lng); String campSiteName = String.valueOf(map.get("CamperSiteName")); String campSitePostID = (String) map.get("CamperSiteID"); // 取第0张图片链接 List<String> imageList = (List<String>) map.get("CamperSiteImages"); String firstImageUrl = imageList != null && !imageList.isEmpty() ? imageList.get(0) : ""; progressDialog.dismiss(); // 先添加Marker,保存返回的Marker对象 Marker marker = mMap.addMarker(new MarkerOptions() .position(newLocation) .title(campSiteName) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE))); // 给Marker设置Tag存储PostID if(marker != null) { marker.setTag(campSitePostID); } // 用Glide加载网络图片替换Marker图标,需要先导入Glide依赖 if(!TextUtils.isEmpty(firstImageUrl) && marker != null) { Glide.with(getContext()) .asBitmap() .load(firstImageUrl) .override(100, 100) // 自定义Marker图标大小 .into(new CustomTarget<Bitmap>() { @Override public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) { marker.setIcon(BitmapDescriptorFactory.fromBitmap(resource)); } @Override public void onLoadCleared(@Nullable Drawable placeholder) { } }); } } // 其余ChildEventListener的空实现方法按需补全即可 @Override public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {} @Override public void onChildRemoved(@NonNull DataSnapshot snapshot) {} @Override public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {} @Override public void onCancelled(@NonNull DatabaseError error) {} });
注意事项
- 需要在模块级
build.gradle中引入Glide依赖:implementation 'com.github.bumptech.glide:glide:4.15.1' annotationProcessor 'com.github.bumptech.glide:compiler:4.15.1' - 你的Firebase中存储国家的字段拼写为
Counrty,代码中查询的时候要和字段名完全一致,否则会查询不到数据。 - 原有代码中每次
onChildAdded就清空列表、循环列表的逻辑是冗余的,onChildAdded每次回调只会返回一条营地数据,不需要循环处理。
内容的提问来源于stack exchange,提问作者user16489264
相关产品推荐
相关产品推荐

