问题
I've tried both methods to save a MapView as a bitmap which I've found here and none seem to work for me. The first option,
Bitmap bitMap = mMapView.getDrawingCache();
mMapView.setDrawingCacheEnabled(true);
bitMap = mMapView.getDrawingCache(true);
and the second,
Canvas offscreencanvas = new Canvas();
Bitmap bmap = Bitmap.createBitmap(mMapView.getWidth(), mMapView.getHeight(),
Bitmap.Config.ARGB_8888);
bmap.copy(Config.ARGB_4444, true);
offscreencanvas.setBitmap(bmap);
offscreencanvas.drawBitmap(bmap, 0, 0, null);
both result in a bitmap object with width and height of -1 so when I then try and use the bitmap as a texture, it doesn't show. I call the bitmap saving code in a button click, after the mapview has rendered but it still gives the same result.
Has anyone managed to do this?
回答1:
I encountered similar problems attempting to make use of the drawing cache. Some items I found that helped me:
- Ensure you copy the drawing cache immediately. Android can and will recycle the bitmap that the cache is drawn too. I have had Android destroy the bitmap cache while I was drawing to a view with it.
- For some reason, destroying the cache before retrieving it gave me more consistent results.
Here is the working code I am using:
// Disable caching, destroy the cache, and force a rebuild
imageView.setWillNotCacheDrawing(false);
imageView.destroyDrawingCache();
imageView.buildDrawingCache();
// Copy the drawing cache before the system recycles it
Bitmap cachedImage = Bitmap.createBitmap(imageView.getDrawingCache());
Also note that I am using an ImageView
, but I would expect the code path to be the same for MapView
.
Finally in the code sample that you posted, you are creating a bitmap the size of the map view. You copy this bitmap and then throw the result away. Then you set your canvas to be backed by this bitmap, and then you try to draw the bitmap to the bitmap. (Yes I typed that correctly.) Try something like this, in place of your canvas code
Bitmap mapCache = /* Get this using the previous code */
Bitmap bmap = Bitmap.createBitmap(mMapView.getWidth(), mMapView.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas offscreencanvas = new Canvas(bmap);
offscreencanvas.drawBitmap(mapCache, 0, 0, null);
回答2:
i didn't work much with MapView, i'll assume that it exteneding the View class, thus, make sure to specify the layout before you build the cach, and you should do it as follow :
This is how i do it, you can change it or try something different if you preffer :
View v = new View(context)
{ public void onMeasure(int w, int h)
{ setMeasuredDimension(width, height);//the desired width and height
}}; //important
v.setDrawingCacheEnabled(true); //important
v.measure(width,height); //important the desired width and height
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight()); //important
v.setDrawingCacheQuality(DRAWING_CACHE_QUALITY_HIGH);
v.setLayoutParams(new LayoutParams(width,height)); //important
v.buildDrawingCache(true); //important
Bitmap b = v.getDrawingCache(true);
v.buildDrawingCache(false);
Hope this helps, Best regards.
回答3:
No need to save mapview drawing cache as bitmap.This will be cleared by Android very soon so you have to put a layout over mapView and get drawingcache bitmap from it. This class is what i used to locate a point on overlay and get the image of map on imageview.
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import android.R.layout;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Point;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
public class GoogleMap extends MapActivity {
MapView mapView;
MapController mc;
GeoPoint p;
LinearLayout layout;
ImageView imageview;
/** Called when the activity is first created. */
@SuppressWarnings("deprecation")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.testmap);
layout = (LinearLayout)findViewById(R.id.maplayout);
layout.setDrawingCacheEnabled(true);
layout.setDrawingCacheQuality(LinearLayout.DRAWING_CACHE_QUALITY_HIGH);
imageview=(ImageView)findViewById(R.id.imageView);
ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
getDrawingBitmap();
}
});
mapView = (MapView) findViewById(R.id.mapview);
mapView.setStreetView(true);
mapView.setBuiltInZoomControls(true);
/*LinearLayout zoomLayout = (LinearLayout)findViewById(R.id.zoom);
View zoomView = mapView.getZoomControls();
zoomLayout.addView(zoomView,
new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));*/
mapView.displayZoomControls(true);
mc = mapView.getController();
String coordinates[] = {"23.0504926", "72.528938925"};
double lat = Double.parseDouble(coordinates[0]);
double lng = Double.parseDouble(coordinates[1]);
p = new GeoPoint(
(int) (lat * 1E6),
(int) (lng * 1E6));
mc.animateTo(p);
mc.setZoom(17);
//---Add a location marker---
MapOverlay mapOverlay = new MapOverlay();
List<Overlay> listOfOverlays = mapView.getOverlays();
listOfOverlays.clear();
listOfOverlays.add(mapOverlay);
mapView.invalidate();
}
public void getDrawingBitmap(){
Bitmap b = layout.getDrawingCache();
imageview.setImageBitmap(b);
}
public void fitAgain(GeoPoint point){
p = point;
mc.animateTo(p,new Runnable() {
public void run() {
getDrawingBitmap();
}
});
// mc.setZoom(17);
MapOverlay mapOverlay = new MapOverlay();
List<Overlay> listOfOverlays = mapView.getOverlays();
listOfOverlays.clear();
listOfOverlays.add(mapOverlay);
mapView.invalidate();
System.out.println("");
}
@Override
protected boolean isRouteDisplayed() {
return false;
}
class MapOverlay extends com.google.android.maps.Overlay
{
@Override
public boolean draw(Canvas canvas, MapView mapView,
boolean shadow, long when)
{
super.draw(canvas, mapView, shadow);
//---translate the GeoPoint to screen pixels---
Point screenPts = new Point();
mapView.getProjection().toPixels(p, screenPts);
//---add the marker---
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_maps_indicator_current_position);
canvas.drawBitmap(bmp, screenPts.x-20, screenPts.y-20, null);
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event, MapView mapView)
{
//---when user lifts his finger---
if (event.getAction() == 1) {
GeoPoint p = mapView.getProjection().fromPixels(
(int) event.getX(),
(int) event.getY());
Geocoder geoCoder = new Geocoder(
getBaseContext(), Locale.getDefault());
try {
List<Address> addresses = geoCoder.getFromLocation(
p.getLatitudeE6() / 1E6,
p.getLongitudeE6() / 1E6, 1);
String add = "";
if (addresses.size() > 0)
{
for (int i=0; i<addresses.get(0).getMaxAddressLineIndex();
i++)
add += addresses.get(0).getAddressLine(i) + "\n";
}
Toast.makeText(getBaseContext(), add, Toast.LENGTH_SHORT).show();
}
catch (IOException e) {
e.printStackTrace();
}
fitAgain(p);
return true;
}
else
return false;
}
}
}
来源:https://stackoverflow.com/questions/6221098/save-mapview-as-a-bitmap