MapContainer 上的 URLImage 未在实际设备上显示并在模拟器中闪烁
URLImage on MapContainer not displayed on actual device and flickering in simulator
我的应用有一张地图,用户的头像显示在中央,用户移动地图时应在其中添加包括照片在内的标记。
在模拟器上,添加了标记,但一旦我释放指针,图像就会消失,然后只剩下占位符(这就是我所说的闪烁)。在设备上,除了用户的头像外,什么也没有显示。
如您所见,图像不会保留在地图上,只有占位符会保留。用户图标在地图上位于南部,但已显示。
请注意:我没有收到 404 错误,地图上只有一个侦听器(见下文):
这是我触发地图更新的方式:
googleMap.addMapListener((source, zoom, center) -> {
showReportsOnMap(googleMap, center, theme, currentForm, selectCategoryButton.getWidth());
});
这是我在地图上添加报告的方式:
public void showReportsOnMap(
MapContainer currentMap,
Coord center,
Resources theme,
Form f,
int reportImageWidth) {
/**
* Get the map borders (CAUTION : it can be NaN)
*/
Coord NE = currentMap.getCoordAtPosition(currentMap.getAbsoluteX() + currentMap.getWidth(), currentMap.getAbsoluteY());
Coord SW = currentMap.getCoordAtPosition(currentMap.getAbsoluteX(), currentMap.getAbsoluteY() + currentMap.getHeight());
boolean bordersKnownAndValid = false;
// Checks that the borders does not contain NaN as longitudes and latitudes
if (!Double.isNaN(NE.getLatitude())
&& !Double.isNaN(NE.getLongitude())
&& !Double.isNaN(SW.getLatitude())
&& !Double.isNaN(SW.getLongitude())) {
// The borders can be used
bordersKnownAndValid = true;
}
if (bordersKnownAndValid) {
ArrayList<Report> localReports = (ArrayList<Report>) (Report.getReportsWithinBoundingBounds(NE, SW, selectedCategoryIdToBeShownOnMap).get(1));
// Revalidate only if we have something new to show
if (localReports.size() > 0) {
currentMap.clearMapLayers();
currentMap.addMarker(ParametresGeneraux.getCurrentUser().getUserIcon(),
new Coord(ParametresGeneraux.getCurrentUser().getCurrentUserLocation().getLatitude(),
ParametresGeneraux.getCurrentUser().getCurrentUserLocation().getLongitude()),
ParametresGeneraux.getCurrentUser().getUserNickname(), "", null);
Image tempPlaceholder = Image.createImage(
reportImageWidth,
reportImageWidth,
ParametresGeneraux.accentColor);
Graphics gr = tempPlaceholder.getGraphics();
gr.setAntiAliased(true);
gr.setColor(ParametresGeneraux.accentColor);
gr.fillArc(0, 0, reportImageWidth, reportImageWidth, 0, 360);
EncodedImage roundPlaceholder = EncodedImage.createFromImage(tempPlaceholder, true);
// Add the report on the map
for (Report report : localReports) {
String photoFilenameInStorage = Report.getFilename(report.getPhotoPath())
+ ParametresGeneraux.SUFFIX_ON_MAP_IMAGE;
EncodedImage reportIcon = EncodedImage.createFromImage(URLImage.createToStorage(roundPlaceholder,
photoFilenameInStorage,
report.getPhotoPath(),
ParametresGeneraux.RESIZE_SCALE_WITH_ROUND_MASK
),
false); // we want transparency png otherwise it shows black edges
currentMap.addMarker(reportIcon,
new Coord(report.getLocation().getLatitude(), report.getLocation().getLongitude()
),
report.getCategory().getName(), "",
(evt) -> {
// Opens the detail form about this report
new ReportDetailsForm(theme, report, f.getClass()).show();
});
}
currentMap.setCameraPosition(new Coord(center.getLatitude(), center.getLongitude()));
currentMap.zoom(new Coord(center.getLatitude(),
center.getLongitude()),
ParametresGeneraux.getUserZoomLevelOnMap());
currentMap.animate();
//f.forceRevalidate();
}
}
}
所以我猜模拟器中的闪烁是设备上发生的一种慢动作,尽管设备不显示占位符。
如何使标记与图像一起出现?
编辑 2017 年 3 月 8 日
在模拟器上,如果我在使用以下代码将标记添加到地图之前显示一个对话框:
Dialog.show("Photo", report.getAddress(), Dialog.TYPE_INFO, reportIcon, "OK", null);
图标在对话框中显示良好(请参见下面的屏幕截图)
然后图像出现在地图上,不再闪烁,如下所示:
但是在实际的 Android 设备上甚至不会出现对话框。
最后我不知道为什么 Dialog 使标记在模拟器上表现得像预期的那样,但在设备上却没有,所以我有点迷茫!
任何帮助都是宝贵的。
问题是 URLImage 在您将其添加为标记时可能尚未完成下载。如果您在 URLImage 完成下载之前调用 EncodedImage.createFromImage(urlImage)
,那么您将创建 urlImage 占位符的编码图像。
com.codename1.io.Util
class 包括很多从 URL 下载图像的方法。有些是阻塞的,有些使用回调。无论哪种方式,您只需要确保在将图像添加到地图之前实际下载图像。
注意:通常这不是 URLImage 的问题 - 例如如果您要将它添加到按钮或标签。这里只是一个问题,因为MapContainer是原生的,它实际上需要在调用setMarker()
时将图像数据传递给原生层。
我的应用有一张地图,用户的头像显示在中央,用户移动地图时应在其中添加包括照片在内的标记。
在模拟器上,添加了标记,但一旦我释放指针,图像就会消失,然后只剩下占位符(这就是我所说的闪烁)。在设备上,除了用户的头像外,什么也没有显示。
如您所见,图像不会保留在地图上,只有占位符会保留。用户图标在地图上位于南部,但已显示。
请注意:我没有收到 404 错误,地图上只有一个侦听器(见下文):
这是我触发地图更新的方式:
googleMap.addMapListener((source, zoom, center) -> {
showReportsOnMap(googleMap, center, theme, currentForm, selectCategoryButton.getWidth());
});
这是我在地图上添加报告的方式:
public void showReportsOnMap(
MapContainer currentMap,
Coord center,
Resources theme,
Form f,
int reportImageWidth) {
/**
* Get the map borders (CAUTION : it can be NaN)
*/
Coord NE = currentMap.getCoordAtPosition(currentMap.getAbsoluteX() + currentMap.getWidth(), currentMap.getAbsoluteY());
Coord SW = currentMap.getCoordAtPosition(currentMap.getAbsoluteX(), currentMap.getAbsoluteY() + currentMap.getHeight());
boolean bordersKnownAndValid = false;
// Checks that the borders does not contain NaN as longitudes and latitudes
if (!Double.isNaN(NE.getLatitude())
&& !Double.isNaN(NE.getLongitude())
&& !Double.isNaN(SW.getLatitude())
&& !Double.isNaN(SW.getLongitude())) {
// The borders can be used
bordersKnownAndValid = true;
}
if (bordersKnownAndValid) {
ArrayList<Report> localReports = (ArrayList<Report>) (Report.getReportsWithinBoundingBounds(NE, SW, selectedCategoryIdToBeShownOnMap).get(1));
// Revalidate only if we have something new to show
if (localReports.size() > 0) {
currentMap.clearMapLayers();
currentMap.addMarker(ParametresGeneraux.getCurrentUser().getUserIcon(),
new Coord(ParametresGeneraux.getCurrentUser().getCurrentUserLocation().getLatitude(),
ParametresGeneraux.getCurrentUser().getCurrentUserLocation().getLongitude()),
ParametresGeneraux.getCurrentUser().getUserNickname(), "", null);
Image tempPlaceholder = Image.createImage(
reportImageWidth,
reportImageWidth,
ParametresGeneraux.accentColor);
Graphics gr = tempPlaceholder.getGraphics();
gr.setAntiAliased(true);
gr.setColor(ParametresGeneraux.accentColor);
gr.fillArc(0, 0, reportImageWidth, reportImageWidth, 0, 360);
EncodedImage roundPlaceholder = EncodedImage.createFromImage(tempPlaceholder, true);
// Add the report on the map
for (Report report : localReports) {
String photoFilenameInStorage = Report.getFilename(report.getPhotoPath())
+ ParametresGeneraux.SUFFIX_ON_MAP_IMAGE;
EncodedImage reportIcon = EncodedImage.createFromImage(URLImage.createToStorage(roundPlaceholder,
photoFilenameInStorage,
report.getPhotoPath(),
ParametresGeneraux.RESIZE_SCALE_WITH_ROUND_MASK
),
false); // we want transparency png otherwise it shows black edges
currentMap.addMarker(reportIcon,
new Coord(report.getLocation().getLatitude(), report.getLocation().getLongitude()
),
report.getCategory().getName(), "",
(evt) -> {
// Opens the detail form about this report
new ReportDetailsForm(theme, report, f.getClass()).show();
});
}
currentMap.setCameraPosition(new Coord(center.getLatitude(), center.getLongitude()));
currentMap.zoom(new Coord(center.getLatitude(),
center.getLongitude()),
ParametresGeneraux.getUserZoomLevelOnMap());
currentMap.animate();
//f.forceRevalidate();
}
}
}
所以我猜模拟器中的闪烁是设备上发生的一种慢动作,尽管设备不显示占位符。
如何使标记与图像一起出现?
编辑 2017 年 3 月 8 日
在模拟器上,如果我在使用以下代码将标记添加到地图之前显示一个对话框:
Dialog.show("Photo", report.getAddress(), Dialog.TYPE_INFO, reportIcon, "OK", null);
图标在对话框中显示良好(请参见下面的屏幕截图)
然后图像出现在地图上,不再闪烁,如下所示:
但是在实际的 Android 设备上甚至不会出现对话框。
最后我不知道为什么 Dialog 使标记在模拟器上表现得像预期的那样,但在设备上却没有,所以我有点迷茫!
任何帮助都是宝贵的。
问题是 URLImage 在您将其添加为标记时可能尚未完成下载。如果您在 URLImage 完成下载之前调用 EncodedImage.createFromImage(urlImage)
,那么您将创建 urlImage 占位符的编码图像。
com.codename1.io.Util
class 包括很多从 URL 下载图像的方法。有些是阻塞的,有些使用回调。无论哪种方式,您只需要确保在将图像添加到地图之前实际下载图像。
注意:通常这不是 URLImage 的问题 - 例如如果您要将它添加到按钮或标签。这里只是一个问题,因为MapContainer是原生的,它实际上需要在调用setMarker()
时将图像数据传递给原生层。