android ImageView.getDrawingCache return NULL

本文探讨了在Android开发中遇到的View getDrawingCache返回null的原因及解决方法,包括检查willNotCacheDrawing、isDrawingCacheEnabled,以及判断是否由于DrawingCache大小超过最大Cache导致。提供了一个初步诊断步骤来确定问题所在。

情况如:http://www.oschina.net/question/6530_44340

模拟器上面getDrawingCache可以返回值,而在真机上面返回null

当我们需要获取某个View的DrawingCache时回去调用getDrawingCache方法,有同学说可以使用getDrawable;但这两个是不一样的,根本上的不一样暂时还没去研究,至少getDrawable获取的是原图(至少大小是跟原图一样大),而getDrawingCache返回的Image是ImageView控件显示的一个截屏

那么当getDrawingCache返回null时我们怎么解决

http://stackoverflow.com/questions/2339429/android-view-getdrawingcache-returns-null-only-null,这篇blog说添加如下代码:

// this is the important code :)

// Without it the view will have a dimension of 0,0 and the bitmap will be null

v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));

v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());

后面我发现,如果是你的DrawingCache超过最大Cache,这招管用,如果不是,这招不管用。

现在网上很多遇到的getDrawingCache返回为null都是DrawingCache大小超过Cache大小导致的,但我这里不是这个问题导致。

我看了下View源码,getDrawingCache是这样实现的:

public Bitmap getDrawingCache() {

return getDrawingCache(false);

}

我们接着看getDrawingCache(false):

public Bitmap getDrawingCache(boolean autoScale) {

if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {

return null;

}

if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {

buildDrawingCache(autoScale);

}

return autoScale ? (mDrawingCache == null ? null : mDrawingCache.get()) :

(mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get());

}

如果getDrawingCache返回null,大体两种可能

1) (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING 这个值为true

2) (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED 为false,buildDrawingCache没执行

3) buildDrawingCache执行失败

我们怎么去粗略的估计是那种原因导致的呢

后面我发现View的willNotCacheDrawing这个方法,代码如下

public boolean willNotCacheDrawing() {

return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;

}

他返回的就是刚才的第一种情况的那个boolean值,我们可以直接debug查看是否为true,如果该值为true,可以强行转成false,View.setWillNotCacheDrawing( Boolean.FALSE).

第二种情况可以看View的 isDrawingCacheEnabled方法

public boolean isDrawingCacheEnabled() {

return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;

}

如果这个方法为false,那就是之前忘记调用setDrawingCacheEnabled(Boolean.TRUE)方法了。

至于第三种,zartzwjhttp://www.iteye.com/topic/1098839』同学有分析,

在buildDrawingCache(boolean)方法中有这样一段代码

if (width <= 0 || height <= 0 ||

// Projected bitmap size in bytes

(width * height * (opaque && !translucentWindow ? 2 : 4) >

ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {

destroyDrawingCache();

return;

}

很多同学遇到的可能都是这种, (width * height * (opaque && !translucentWindow ? 2 : 4) 大于 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize()导致buildDrawingCache失败。

怎么判断是否这里导致的呢,如果你在前面没有对View的layout自行设置,是程序默认,并且调用的是view.getDrawingCache()或者是view.getDrawingCache(false);

view.getHidth的值就是这儿的width值

view.getHeight的值就是这儿的height

将这两个值乘以4如果还没大于ViewConfiguration.get(Context).getScaledMaximumDrawingCacheSize(),那么就不可能是是DrawingCache大于最大Cache所导致的,

如果乘以4大于了,也不一定就是,因为(width * height * (opaque && !translucentWindow ? 2 : 4)有这个变数。

我遇到的是第一种情况,willNotCacheDrawing我没有调用,使用的默认值,但为什么在模拟器上面为false,而在真机上就是true了呢?现在还不是很清楚

刚接触android不久,对API不是很熟,各位大牛轻拍

package com.QingFeng.FamilyLocation.act; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.lifecycle.Observer; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.PagerSnapHelper; import androidx.recyclerview.widget.RecyclerView; import android.animation.ValueAnimator; import android.graphics.Color; import android.os.Build; import android.os.Bundle; import android.util.Log; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.animation.LinearInterpolator; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.QingFeng.FamilyLocation.Constants; import com.QingFeng.FamilyLocation.R; import com.QingFeng.FamilyLocation.adapter.TimeAdapter; import com.QingFeng.FamilyLocation.adapter.ZuJiWeekAdapter; import com.QingFeng.FamilyLocation.base.BaseActivity; import com.QingFeng.FamilyLocation.bean.MainFriendBean; import com.QingFeng.FamilyLocation.bean.UserTrack; import com.QingFeng.FamilyLocation.databinding.ActivityFootprintsctivityBinding; import com.QingFeng.FamilyLocation.dialog.CustomBottomDialog; import com.QingFeng.FamilyLocation.group.bean.GroupListBean; import com.QingFeng.FamilyLocation.http.ApiManager; import com.QingFeng.FamilyLocation.http.BaseObserver; import com.QingFeng.FamilyLocation.ui.CircleImageView; import com.QingFeng.FamilyLocation.utils.HorizontalSpaceItemDecoration; import com.QingFeng.FamilyLocation.utils.StatusBarUtils; import com.amap.api.maps.AMap; import com.amap.api.maps.CameraUpdateFactory; import com.amap.api.maps.model.BitmapDescriptor; import com.amap.api.maps.model.BitmapDescriptorFactory; import com.amap.api.maps.model.CircleOptions; import com.amap.api.maps.model.LatLng; import com.amap.api.maps.model.Marker; import com.amap.api.maps.model.MarkerOptions; import com.amap.api.maps.model.Polyline; import com.amap.api.maps.model.PolylineOptions; import com.amap.api.services.core.AMapException; import com.amap.api.services.core.LatLonPoint; import com.amap.api.services.geocoder.GeocodeResult; import com.amap.api.services.geocoder.GeocodeSearch; import com.amap.api.services.geocoder.RegeocodeQuery; import com.amap.api.services.geocoder.RegeocodeResult; import com.bumptech.glide.Glide; import com.chad.library.adapter4.viewholder.QuickViewHolder; import com.jeremyliao.liveeventbus.LiveEventBus; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.Duration; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; public class Footprintsctivity extends BaseActivity<ActivityFootprintsctivityBinding> implements View.OnLayoutChangeListener { private AMap aMap; private TimeAdapter timeAdapter; private LinearLayoutManager layoutManager; private PagerSnapHelper snapHelper; private int centerPosition = 0; private List<String> dataList = new ArrayList<>(); private int itemWidth = 0; private int recyclerViewWidth = 0; private boolean isInitialized = false; // 地址解析相关 private GeocodeSearch geocodeSearch; private Map<String, String> addressCache = new HashMap<>(); private static final String TAG = "FootprintsActivity"; // 轨迹相关(核心新增:头像移动逻辑) private Marker avatarMarker; // 移动的头像Marker private List<LatLng> trackPoints = new ArrayList<>(); // 轨迹点坐标列表 private List<String> trackTimeList = new ArrayList<>(); // 轨迹点时间列表 private List<Marker> trackMarkers = new ArrayList<>(); // 轨迹节点标记(起点/终点) private Polyline trackPolyline; // 轨迹线 private Map<String, List<UserTrack>> trackCache = new HashMap<>(); private String date; private String userName; private String hread; private String selectId; private String gid; @Override protected ActivityFootprintsctivityBinding createBinding() { StatusBarUtils.setTransparentSystemBars(this); return ActivityFootprintsctivityBinding.inflate(getLayoutInflater()); } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); binding.mapView.onCreate(savedInstanceState); } @Override protected void initWidget() { super.initWidget(); initMap(); initGeocodeSearch(); // 接收用户选择事件 LiveEventBus.get("friendBean", Bundle.class) .observe(this, bundle -> { if (bundle != null) { hread = bundle.getString("hread"); userName = bundle.getString("userName"); selectId = bundle.getString("selectId"); gid = bundle.getString("gid"); getUserTrack(); } }); // 选择用户按钮 binding.ivRight.setOnClickListener(v -> getList()); // 日期选择RecyclerView binding.recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)); int spacing = getResources().getDimensionPixelSize(R.dimen.recycler_view_horizontal_spacing); binding.recyclerView.addItemDecoration(new HorizontalSpaceItemDecoration(spacing)); ZuJiWeekAdapter zuJiWeekAdapter = new ZuJiWeekAdapter(); binding.recyclerView.setAdapter(zuJiWeekAdapter); // 时间选择RecyclerView(每5分钟一个间隔) setupRecyclerView(); // 日期选择事件 zuJiWeekAdapter.setOnItemClickListener((adapter, view, position) -> { for (int i = 0; i < adapter.getItems().size(); i++) { adapter.getItem(i).setSelcet(false); } adapter.getItem(position).setSelcet(true); date = adapter.getItem(position).getDate(); adapter.notifyDataSetChanged(); if (isReq()) { getUserTrack(); } }); } private void initMap() { if (aMap == null) { aMap = binding.mapView.getMap(); aMap.moveCamera(CameraUpdateFactory.zoomTo(10)); aMap.getUiSettings().setZoomControlsEnabled(true); aMap.getUiSettings().setScaleControlsEnabled(true); aMap.setMyLocationEnabled(false); aMap.showBuildings(false); aMap.showIndoorMap(false); } } private void initGeocodeSearch() { if (geocodeSearch == null) { try { geocodeSearch = new GeocodeSearch(this); } catch (AMapException e) { throw new RuntimeException(e); } geocodeSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { @Override public void onRegeocodeSearched(RegeocodeResult result, int code) { } @Override public void onGeocodeSearched(GeocodeResult result, int code) { } }); } } @Override protected void initData() { super.initData(); // 生成从00:00到23:55,每5分钟一个间隔的时间列表 for (int hour = 0; hour < 24; hour++) { for (int minute = 0; minute < 60; minute += 5) { // 格式化时间为"HH:mm"格式(如"00:00", "00:05", ..., "23:55") String timeStr = String.format(Locale.getDefault(), "%02d:%02d", hour, minute); dataList.add(timeStr); } } timeAdapter.submitList(dataList); } private void setupRecyclerView() { layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false); layoutManager.setInitialPrefetchItemCount(5); // 预加载5个item binding.recyclertime.setLayoutManager(layoutManager); binding.recyclertime.setClipToPadding(false); timeAdapter = new TimeAdapter(); binding.recyclertime.setAdapter(timeAdapter); timeAdapter.submitList(dataList); // 优化:增加缓存减少创建开销 binding.recyclertime.setItemViewCacheSize(20); binding.recyclertime.setHasFixedSize(true); snapHelper = new PagerSnapHelper(); snapHelper.attachToRecyclerView(binding.recyclertime); // 布局完成后初始化 binding.recyclertime.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { binding.recyclertime.removeOnLayoutChangeListener(this); recyclerViewWidth = right - left; measureItemWidth(); // 设置padding使首尾item可居中 int padding = (recyclerViewWidth - itemWidth) / 2; binding.recyclertime.setPadding(padding, 0, padding, 0); if (!isInitialized) { isInitialized = true; binding.recyclertime.post(() -> { layoutManager.scrollToPositionWithOffset(0, 0); }); } }); // 滑动停止后移动头像 binding.recyclertime.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { if (newState == RecyclerView.SCROLL_STATE_IDLE) { updateCenterPosition(); } } }); // 左右箭头点击事件 binding.btnLeft2.setOnClickListener(v -> { if (centerPosition > 0) { int target = centerPosition - 1; layoutManager.scrollToPositionWithOffset(target, 0); updateCenterPosition2(target); } }); binding.btnRight2.setOnClickListener(v -> { if (centerPosition < dataList.size() - 1) { int target = centerPosition + 1; layoutManager.scrollToPositionWithOffset(target, 0); updateCenterPosition2(target); } }); } private void measureItemWidth() { View itemView = LayoutInflater.from(this).inflate(R.layout.item_horzontil, binding.recyclertime, false); QuickViewHolder holder = new QuickViewHolder(itemView); timeAdapter.onBindViewHolder(holder, 0); int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); int heightSpec = View.MeasureSpec.makeMeasureSpec(dp2px(40), View.MeasureSpec.EXACTLY); itemView.measure(widthSpec, heightSpec); itemWidth = itemView.getMeasuredWidth(); } // 滑动后更新选中位置并移动头像 private void updateCenterPosition() { View snapView = snapHelper.findSnapView(layoutManager); if (snapView == null) return; int newPosition = layoutManager.getPosition(snapView); if (newPosition != centerPosition) { centerPosition = newPosition; timeAdapter.setSelectedPosition(centerPosition); // 核心:根据选中时间移动头像 moveAvatarToMatchedPoint(dataList.get(centerPosition)); } } // 按钮点击后更新位置并移动头像 private void updateCenterPosition2(int targetPosition) { if (targetPosition < 0 || targetPosition >= dataList.size()) return; centerPosition = targetPosition; timeAdapter.setSelectedPosition(centerPosition); // 核心:移动头像 moveAvatarToMatchedPoint(dataList.get(centerPosition)); } private int dp2px(int dp) { return (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics() ); } private void getList() { ApiManager.groupList(1).subscribe(new BaseObserver<GroupListBean>(this) { @Override protected void onSuccess(GroupListBean bean) { if (bean.getList() != null && !bean.getList().isEmpty()) { bean.getList().get(0).setCheck(true); getFriend(bean.getList(), bean.getList().get(0).getId()); } } }); } private void getFriend(List<GroupListBean.ListBean> list, String id) { ApiManager.getGroupMembers(list.get(0).getId()) .subscribe(new BaseObserver<MainFriendBean>(this, true) { @Override protected void onSuccess(MainFriendBean bean) { CustomBottomDialog dialog = new CustomBottomDialog(list, bean.getMembers()); dialog.setSelectGid(id); dialog.show(); } }); } private void getUserTrack() { ApiManager.getUserTrack(selectId, gid, date).subscribe(new BaseObserver<ArrayList<UserTrack>>(this) { @Override protected void onSuccess(ArrayList<UserTrack> trackList) { trackCache.put(date, trackList); updateTrackUI(trackList); // 更新轨迹并初始化头像 } }); } private boolean isReq() { return date != null && hread != null && selectId != null && gid != null; } // 更新轨迹UI(核心:初始化轨迹和头像) private void updateTrackUI(List<UserTrack> trackList) { clearOldTrack(); // 清除旧数据 trackPoints.clear(); trackTimeList.clear(); if (trackList == null || trackList.isEmpty()) { showToast("该日期没有轨迹数据"); return; } // 收集轨迹点和时间 for (int i = 0; i < trackList.size(); i++) { UserTrack track = trackList.get(i); try { double lat = Double.parseDouble(track.getLatitude()); double lng = Double.parseDouble(track.getLongitude()); LatLng point = new LatLng(lat, lng); trackPoints.add(point); trackTimeList.add(track.getTime()); // 保存时间(格式:HH:mm:ss) // 创建起点和终点标记 boolean isStart = (i == 0); boolean isEnd = (i == trackList.size() - 1); if (isStart || isEnd) { createTrackMarker(track, point, isStart, isEnd); } } catch (Exception e) { Log.e(TAG, "解析经纬度失败: " + e.getMessage()); } } // 绘制轨迹线 if (trackPoints.size() > 1) { trackPolyline = aMap.addPolyline(new PolylineOptions() .addAll(trackPoints) .width(10) .color(getResources().getColor(R.color.black)) .geodesic(true)); } // 初始化移动的头像Marker initAvatarMarker(); // 移动地图到起点 aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(trackPoints.get(0), 10)); } // 初始化移动的头像Marker private void initAvatarMarker() { // 移除旧头像 if (avatarMarker != null && !avatarMarker.isRemoved()) { avatarMarker.remove(); } // 加载自定义头像布局 View avatarView = LayoutInflater.from(this).inflate(R.layout.item_avatar_marker, null); CircleImageView ivAvatar = avatarView.findViewById(R.id.iv_avatar); // 设置头像图片 if (hread != null && !hread.isEmpty()) { Glide.with(this).load(hread).placeholder(R.mipmap.logo).into(ivAvatar); } else { ivAvatar.setImageResource(R.mipmap.logo); } // 转换为Marker图标 BitmapDescriptor descriptor = BitmapDescriptorFactory.fromView(avatarView); // 创建头像Marker(初始位置为起点) avatarMarker = aMap.addMarker(new MarkerOptions() .position(trackPoints.get(0)) .icon(descriptor) .anchor(0.5f, 0.5f) // 锚点居中 .zIndex(3.0f)); // 优先级最高,避免被遮挡 } // 根据选中时间移动头像到对应轨迹点 private void moveAvatarToMatchedPoint(String selectedTime) { if (trackPoints.isEmpty() || trackTimeList.isEmpty() || avatarMarker == null) { return; } selectedTime = "16:14"; // 找到匹配的轨迹点索引 int matchedIndex = findMatchedTimeIndex(selectedTime); if (matchedIndex == -1) { showToast("未找到对应时间的位置"); return; } // 平滑移动到目标点 LatLng targetPoint = trackPoints.get(matchedIndex); smoothMoveAvatar(avatarMarker.getPosition(), targetPoint, 1000); // 地图视角跟随 aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(targetPoint, 10)); } // 找到与选中时间最接近的轨迹点索引 // 找到与选中时间最接近的轨迹点索引 /** * 找到与选中时间最接近且相差不超过5分钟的轨迹点索引 * 如果没有找到相差在5分钟内的点,则返回-1 */ /** * 找到与选中时间最接近且相差不超过5分钟的轨迹点索引 * 如果没有找到相差在5分钟内的点,则返回最接近的点索引 */ /** * 找到与选中时间最接近且相差不超过5分钟的轨迹点索引 * 如果没有找到相差在5分钟内的点,则返回最接近的点索引 */ private int findMatchedTimeIndex(String selectedTime) { selectedTime = "11:30"; // 定义时间格式 DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm", Locale.getDefault()); final long FIVE_MINUTES_IN_SECONDS = 5 * 60; // 5分钟对应的秒数 try { // 清理并验证选中时间 String cleanedSelectedTime = selectedTime.trim() .replaceAll("\\p{C}", ""); if (!cleanedSelectedTime.matches("\\d{2}:\\d{2}")) { Log.e(TAG, "选中时间格式不符合 HH:mm: " + cleanedSelectedTime); return -1; } LocalTime selectedTimeObj = LocalTime.parse(cleanedSelectedTime, timeFormatter); // 遍历轨迹点时间列表 int closestIndex = -1; long minDiff = Long.MAX_VALUE; for (int i = 0; i < trackTimeList.size(); i++) { String trackTimeStr = trackTimeList.get(i); String cleanedTrackTime = trackTimeStr.trim() .replaceAll("\\p{C}", ""); LocalTime trackTimeObj = null; // 尝试按不同格式解析轨迹时间 try { // 优先尝试 HH:mm:ss 格式 trackTimeObj = LocalTime.parse(cleanedTrackTime, DateTimeFormatter.ofPattern("HH:mm:ss", Locale.getDefault())); } catch (DateTimeParseException e) { try { // 尝试 HH:mm 格式 trackTimeObj = LocalTime.parse(cleanedTrackTime, DateTimeFormatter.ofPattern("HH:mm", Locale.getDefault())); // 补齐秒部分为 00 trackTimeObj = trackTimeObj.withSecond(0); } catch (DateTimeParseException ex) { Log.w(TAG, "轨迹时间格式无法解析: " + cleanedTrackTime); continue; // 跳过无法解析的时间 } } // 计算时间差 long diffSeconds = Math.abs( Duration.between(selectedTimeObj, trackTimeObj).getSeconds() ); // 记录最接近的点 if (diffSeconds < minDiff) { minDiff = diffSeconds; closestIndex = i; } // 找到符合5分钟内的点,立即返回 if (diffSeconds <= FIVE_MINUTES_IN_SECONDS) { return i; } } return closestIndex; } catch (DateTimeParseException e) { Log.e(TAG, "选中时间解析失败: " + selectedTime, e); return -1; } catch (Exception e) { Log.e(TAG, "时间匹配过程发生异常", e); return -1; } } // 平滑移动头像到目标位置 private void smoothMoveAvatar(LatLng start, LatLng end, long duration) { // 计算经纬度差值 double latDiff = end.latitude - start.latitude; double lngDiff = end.longitude - start.longitude; // 创建属性动画 ValueAnimator animator = ValueAnimator.ofFloat(0, 1); animator.setDuration(duration); animator.setInterpolator(new LinearInterpolator()); animator.addUpdateListener(animation -> { float fraction = (float) animation.getAnimatedValue(); // 计算当前位置 double currentLat = start.latitude + latDiff * fraction; double currentLng = start.longitude + lngDiff * fraction; // 更新头像位置 avatarMarker.setPosition(new LatLng(currentLat, currentLng)); // 更新头像方向(朝向移动方向) if (fraction < 1) { float bearing = calculateBearing( new LatLng(currentLat, currentLng), new LatLng(currentLat + latDiff * 0.1, currentLng + lngDiff * 0.1) ); avatarMarker.setRotateAngle(bearing); } }); animator.start(); } // 计算两点之间的方位角 private float calculateBearing(LatLng start, LatLng end) { double dLon = end.longitude - start.longitude; double y = Math.sin(dLon) * Math.cos(end.latitude); double x = Math.cos(start.latitude) * Math.sin(end.latitude) - Math.sin(start.latitude) * Math.cos(end.latitude) * Math.cos(dLon); double bearing = Math.atan2(y, x); return (float) Math.toDegrees(bearing); } private void createTrackMarker(UserTrack track, LatLng position, boolean isStart, boolean isEnd) { // 异步获取地址后更新标记 getAddressByLatLng(track, position, isStart, isEnd); } private void getAddressByLatLng(UserTrack track, LatLng position, boolean isStart, boolean isEnd) { try { double lat = Double.parseDouble(track.getLatitude()); double lng = Double.parseDouble(track.getLongitude()); LatLonPoint point = new LatLonPoint(lat, lng); RegeocodeQuery query = new RegeocodeQuery(point, 200, GeocodeSearch.AMAP); geocodeSearch.getFromLocationAsyn(query); geocodeSearch.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() { @Override public void onRegeocodeSearched(RegeocodeResult result, int code) { runOnUiThread(() -> { if (code == 1000 && result != null && result.getRegeocodeAddress() != null) { String address = result.getRegeocodeAddress().getFormatAddress(); addressCache.put(lat + "," + lng, address); // 加载自定义布局 View markerView = LayoutInflater.from(Footprintsctivity.this).inflate(R.layout.item_zuji, null); // 设置用户名 TextView tvUserName = markerView.findViewById(R.id.tvUserName); tvUserName.setText(userName); // 处理头像显示逻辑 CircleImageView imgAvatar = markerView.findViewById(R.id.imgAvatar); ImageView imgStatus = markerView.findViewById(R.id.imgOnlineStatus); View ff = markerView.findViewById(R.id.ff); ff.setVisibility(View.INVISIBLE); if (isEnd) { // 终点:显示头像和在线状态 imgAvatar.setVisibility(View.VISIBLE); // ff.setVisibility(View.VISIBLE); imgStatus.setVisibility(View.VISIBLE); imgStatus.setImageResource(R.drawable.status_online); if (hread != null && !hread.isEmpty()) { Glide.with(Footprintsctivity.this).load(hread).placeholder(R.mipmap.logo).into(imgAvatar); } else { imgAvatar.setImageResource(R.mipmap.logo); } } else if (isStart) { // 起点:显示起点图标 imgAvatar.setVisibility(View.INVISIBLE); ff.setVisibility(View.INVISIBLE); imgStatus.setVisibility(View.VISIBLE); imgStatus.setImageResource(R.drawable.status_offline); } else { // 普通点:隐藏头像 imgAvatar.setVisibility(View.INVISIBLE); ff.setVisibility(View.INVISIBLE); imgStatus.setVisibility(View.INVISIBLE); } // 设置地址和时间 TextView tvAddress = markerView.findViewById(R.id.txt_address); tvAddress.setText(address); // 创建标记 BitmapDescriptor descriptor = BitmapDescriptorFactory.fromView(markerView); MarkerOptions options = new MarkerOptions() .position(position) .icon(descriptor) .anchor(0.5f, 0.5f); // 起点/终点z轴优先级更高 if (isStart || isEnd) { options.zIndex(2.0f); } Marker marker = aMap.addMarker(options); marker.setObject(track); trackMarkers.add(marker); } }); } @Override public void onGeocodeSearched(GeocodeResult result, int code) { } }); } catch (Exception e) { Log.e(TAG, "地址解析失败: " + e.getMessage()); } } // 清除旧轨迹和标记 private void clearOldTrack() { // 移除轨迹标记 for (Marker marker : trackMarkers) { if (marker != null && !marker.isRemoved()) { marker.remove(); } } trackMarkers.clear(); // 移除轨迹线 if (trackPolyline != null) { trackPolyline.remove(); trackPolyline = null; } // 移除头像标记 if (avatarMarker != null && !avatarMarker.isRemoved()) { avatarMarker.remove(); } } @Override protected void onResume() { super.onResume(); binding.mapView.onResume(); } @Override protected void onPause() { super.onPause(); binding.mapView.onPause(); } @Override protected void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); binding.mapView.onSaveInstanceState(outState); } @Override protected void onDestroy() { super.onDestroy(); binding.mapView.onDestroy(); } @Override public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7) { } }这是我的代码
07-11
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值