将 Android Google Maps v2 与自定义 View 或 ImageView 结合使用 [英] Using Android Google Maps v2 with custom View or ImageView
问题描述
基本上我希望能够使用 Google Maps v2在地图上绘制雷达图像,具有良好的位图图像无闪烁或延迟.
我目前正在使用 Maps v1 来执行此操作,并且效果很好,但是 Maps v2不太适合这样做.
你会认为 GroundOverlay 或 TileOverlay 可能有用,但从我从尝试使用它们的人那里读到的,在绘制下一张图像之前,您必须删除()上一张图像,或者尝试将位图图像绘制为标记或者其他的东西.它必须具有良好的性能.
所以我希望能够使用自定义视图或 ImageView并使用它的 onDraw() 绘制位图并使其在地图上可见并随之移动.
喜欢:
<外部容器><片段../><com.my.customView ../>或者<图像视图../></外部容器>
我在网上到处找可能的例子有关如何使用 Maps v2 执行此类操作的详细信息,但已发现什么都没有.
我在当前的应用程序中使用了几个自定义视图所以我对这些很熟悉,而且我有位图的边界框详细信息我很确定我可以使用投影信息帮助他们画画.
另一个问题是如何调用 invalidate() 以便onDraw() 将被调用.
我只需要一些示例代码来展示如何使用 onDraw()从某种基于视图的对象中,我可以尝试查看它是否有效,但一个不尝试使用GroundOverlay"、TileOverlay"或Marker"的,我真的很感激!
谢谢!
如果你熟悉
您也可以通过 canvas 在自定义视图画布上绘制位图雷达图像.drawBitmap()
方法.
您也可以将 ImageView
放在 MapView
或 MapFragment
上(例如在 RelativeLayout
内)
<片段android:id="@+id/地图"android:layout_width="match_parent"android:layout_height="match_parent"class="com.google.android.gms.maps.MapFragment"/><图像视图android:layout_width="wrap_content"android:layout_height="wrap_content"机器人:layout_centerInParent =真"android:src="@drawable/雷达"/></RelativeLayout>
并在 ImageView
上绘制(甚至只是设置)雷达图像.
Basically I want to be able to use Google Maps v2 to draw RADAR images over the Map, with good performance and no flickering or delay of the Bitmap images.
I'm currently using Maps v1 to do this, and it works great, but Maps v2 is not well suited to do that.
You would think that GroundOverlay or TileOverlay might work, but from what I've read from people who have tried using them, you have to remove() the previous image before you draw the next one, or do some kludge of trying to draw the Bitmap image as a Marker or something. It has to have good performance.
So I'd like to be able to use either a custom View, or an ImageView and use it's onDraw() to draw the Bitmap and have it be visible on the Map and move with it.
Like:
<Outer Container>
<fragment .. />
<com.my.customView .. />
or
<ImageView .. />
</Outer Container>
I've looked everywhere over the web for possible examples of the details of how to do something like that, with Maps v2, but have found nothing.
I use several custom Views in my current application so I'm familiar with those, and I have the Bounding Box details of the Bitmaps and I'm pretty sure that I can use the Projection information to help draw them.
Another issue is how to call invalidate() so that the onDraw() will be called.
I just need some example code that would show how to use the onDraw() from some kind of a View based object that I could try to see if it works, but one that doesn't try to use 'GroundOverlay', 'TileOverlay' or "Marker', I'd really appreciate it!
Thanks!
If you familiar with implementing custom view, you can create custom view which extends MapView
class for full control of drawing on view canvas. But because MapView
extends FrameLayout
which is ViewGroup
, you should override dispatchDraw()
method, not onDraw()
and implement within it radar drawing. Something like that:
@Override
public void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
canvas.save();
drawRadarOverTheMap(canvas);
canvas.restore();
}
and you need to call it via invalidate()
on every map move/zoom/rotate. For detect map move/zoom/rotate you need GoogleMap
(exactly GoogleMap.setOnCameraMoveListener()
method). You can declare GoogleMap
object inside your custom MapView class and set it via setter, but better if custom MapView class will implement OnMapReadyCallback
interface and get it in onMapReady()
callback.
Full source code of MapView
-based custom view (e.g. RadarMapView
) can be like that:
public class RadarMapView extends MapView implements OnMapReadyCallback {
private OnMapReadyCallback mMapReadyCallback;
private GoogleMap mGoogleMap;
private Marker mMarker;
private Paint mPaintRadar;
public RadarMapView(@NonNull Context context) {
super(context);
init();
}
public RadarMapView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public RadarMapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public RadarMapView(@NonNull Context context, @Nullable GoogleMapOptions options) {
super(context, options);
init();
}
@Override
public void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
canvas.save();
drawRadarOverTheMap(canvas);
canvas.restore();
}
private void drawRadarOverTheMap(Canvas canvas) {
if (mGoogleMap == null) {
return;
}
final float centerX = getX() + getWidth() / 2;
final float centerY = getY() + getHeight() / 2;
canvas.drawCircle(centerX, centerY, 150, mPaintRadar);
canvas.drawCircle(centerX, centerY, 300, mPaintRadar);
canvas.drawCircle(centerX, centerY, 450, mPaintRadar);
}
private void init() {
setWillNotDraw(false);
mPaintRadar = new Paint();
mPaintRadar.setColor(Color.GREEN);
mPaintRadar.setStyle(Paint.Style.STROKE);
mPaintRadar.setStrokeWidth(10);
}
@Override
public void getMapAsync(OnMapReadyCallback callback) {
mMapReadyCallback = callback;
super.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
mGoogleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
@Override
public void onCameraMove() {
invalidate();
}
});
if (mMapReadyCallback != null) {
mMapReadyCallback.onMapReady(googleMap);
}
}
}
And you can use it in .xml
file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="{your_package_name}.MainActivity">
<{your_package_name}.RadarMapView
android:id="@+id/mapview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</RelativeLayout>
for MainActivity
like:
public class MainActivity extends AppCompatActivity {
private static final String MAP_VIEW_BUNDLE_KEY = "MapViewBundleKey";
private GoogleMap mGoogleMap;
private RadarMapView mMapView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Bundle mapViewBundle = null;
if (savedInstanceState != null) {
mapViewBundle = savedInstanceState.getBundle(MAP_VIEW_BUNDLE_KEY);
}
mMapView = (RadarMapView) findViewById(R.id.mapview);
mMapView.onCreate(mapViewBundle);
mMapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
}
});
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Bundle mapViewBundle = outState.getBundle(MAP_VIEW_BUNDLE_KEY);
if (mapViewBundle == null) {
mapViewBundle = new Bundle();
outState.putBundle(MAP_VIEW_BUNDLE_KEY, mapViewBundle);
}
mMapView.onSaveInstanceState(mapViewBundle);
}
@Override
protected void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
protected void onStart() {
super.onStart();
mMapView.onStart();
}
@Override
protected void onStop() {
super.onStop();
mMapView.onStop();
}
@Override
protected void onPause() {
mMapView.onPause();
super.onPause();
}
@Override
protected void onDestroy() {
mMapView.onDestroy();
super.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mMapView.onLowMemory();
}
}
and you should get something like that:
Also you can draw bitmap Radar image on custom view canvas via canvas.drawBitmap()
method.
And also you can place ImageView
over MapView
or MapFragment
(e.g. within RelativeLayout
)
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
class="com.google.android.gms.maps.MapFragment"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/radar"
/>
</RelativeLayout>
and draw (or even just set) Radar images on ImageView
.
这篇关于将 Android Google Maps v2 与自定义 View 或 ImageView 结合使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!