create custom marker icons on runtime using android xml - android

I am developing an android app in which I need to download an image from its URL, create a bitmap out of it and than display it on map as an icon. so far I have successfully completed to show bitmaps dynamically on map but I need to place my images on some background. something like this shown here How to create a custom-shaped bitmap marker with Android map API v2?
any example or suggestion would be helpful.
thanks...:)

I got the answer for my above problem
I created a bitmap from view and then placed it on marker. my xml is below
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/img_id"
android:layout_width="#dimen/custom_profile_image"
android:layout_height="#dimen/custom_profile_image"
android:contentDescription="#string/content"
android:scaleType="centerCrop" />
</RelativeLayout>
inflating above xml
View viewMarker = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(R.layout.custom_marker_layout, null);
ImageView myImage = (ImageView) viewMarker.findViewById(R.id.img_id);
set Imagebitmap on imageview which you download from url on runtime
myImage.setImageBitmap(Imagebitmap);
now pass view object to the method and return the bitmap out of it. like this
Bitmap bmp=createDrawableFromView(context,viewMarker);
googleMap.addMarker(new MarkerOptions()
.position(new LatLng(latitude, longitude)).title(title)
.snippet(snippet)
.icon(BitmapDescriptorFactory.fromBitmap(bmp)));
now you can use returned bitmap anywhere, thats you'll be able to make custom marker icons using xmls.
public static Bitmap createDrawableFromView(Context context, View view) {
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay()
.getMetrics(displayMetrics);
view.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
view.measure(displayMetrics.widthPixels, displayMetrics.heightPixels);
view.layout(0, 0, displayMetrics.widthPixels,
displayMetrics.heightPixels);
view.buildDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(),
view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
Its working for me. Thanks!!!

There's probably a better solution, but maybe try this:
Put the background you need into your drawable folder and load the bitmap:
Bitmap marker = getResources().getDrawable(R.drawable.marker_background);
Edit a copy of it with the Image you downloaded (only pseudo, don't know if this works like this):
int xOffset = 20;
int yOffset = 50;
int xPosition = xOffset;
int yPosition = yOffset;
int numberOfPixels = image.getHeight()*image.getWidth();
int[] pixels = new int[numberOfPixels];
image.getPixels(pixels,0,0,0,0,image.getWidth(), image.getHeight());
for (int x = 0; x<numberOfPixels;x++){
marker.setPixel(xPosition,yPosition,pixels[x]);
if((xPosition-xOffset)%image.getWidth()==0){
yPosition+=1;
xPosition=xOffset;
}else{
xPosition++;
}
}
MarkerOptions markerOptions = new MarkerOptions().icon(BitmapDescriptorFactory.fromBitmap(marker));

Related

Save mapView as image without rendering it on screen

I'm creating free activity monitoring app similar to Strava. Using vtm-android as map library.
I would like save org.oscim.android.MapView as image, without rendering it to screen.
I found several solutions, how to save view as image, but unfortunately none of them is working when when view is not "attached" to existing component tree.
My expectation was to initialize MapView like this:
final String MAP_FILE = "somemap.map";
MapView mapView = new MapView(mContext);
final org.oscim.map.Map map = mapView.map();
MapFileTileSource tileSource = new MapFileTileSource();
String mapPath = new File(Environment.getExternalStorageDirectory(), MAP_FILE).getAbsolutePath();
if (tileSource.setMapFile(mapPath)) {
// Vector layer
VectorTileLayer tileLayer = map.setBaseMap(tileSource);
// Render theme
map.setTheme(VtmThemes.DEFAULT);
double latitude = 49.1625214;
double longitude = 20.2644075;
// Note: this map position is specific to Berlin area
map.setMapPosition(latitude, longitude, 1 << 12);
}
mapView.layout(0, 0, 200, 200);
//Get the dimensions of the view so we can re-layout the view at its current size
//and create a bitmap of the same size
int width = view.getWidth();
int height = view.getHeight();
int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
int measuredHeight = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
//Cause the view to re-layout
view.measure(measuredWidth, measuredHeight);
view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
//Create a bitmap backed Canvas to draw the view into
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
//Now that the view is laid out and we have a canvas, ask the view to draw itself into the canvas
view.draw(canvas);
ByteBuffer byteBuffer = ByteBuffer.allocate(bitmap.getByteCount());
bitmap.copyPixelsToBuffer(byteBuffer);
//save bytes from bytebuffer to file or db
But instead of map image, I get full transparent image.
To take screen shot you need render it on screen. Without rendering screenshot is not possible
mapView.getDrawingCache()
It will return you bitmap of current displaying.
Bitmap capturedScreen = Bitmap.createBitmap(mapView.getDrawingCache()); imageView.setImageBitmap(capturedScreen);
Here 'capturedScreen' will give you image of mapview.

Create custom bitmap marker with android map API V2

I'm trying to Create custom bitmap marker and place it at particular Lat-Lng on google Map, for that I have written the following code--
My custom marker view is (user_prof_pic_marker.xml)--
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageView
android:layout_width="#dimen/sz_sixty_five"
android:layout_height="#dimen/sz_sixty_five"
android:layout_centerInParent="true"
android:src="#drawable/map_marker" />
<com.wikiNews.custom.CircleImageView
android:id="#+id/myImage"
android:layout_width="#dimen/sz_fifty"
android:layout_height="#dimen/sz_fifty"
android:layout_centerInParent="true"
android:src="#drawable/profiledefaultimg" />
</RelativeLayout>
This is how I am setting image to the custom view--
View myUserMarkerLayout = getLayoutInflater().inflate(R.layout.user_prof_pic_marker, null);
myUserImageView = (CircleImageView) myUserMarkerLayout.findViewById(R.id.myImage);
myUserImageView.setBorderColor(Color.WHITE);
myUserImageView.setBorderWidth(2);
//String strPic = UserDetails.getInstance().getCurrentProfilePic();
if(UserDetails.getInstance().getCurrentProfilePic()!=null && !UserDetails.getInstance().getCurrentProfilePic().isEmpty())
{
Picasso.with(this).load(UserDetails.getInstance().getCurrentProfilePic()).into(myUserImageView);
}
My method to create BitMap from custom view is--
public static Bitmap createDrawableFromView(Context context, View view) {
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
view.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
view.measure(displayMetrics.widthPixels, displayMetrics.heightPixels);
view.layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels);
view.buildDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
My code to add Marker is--
if (googleMap != null)
{
final LatLng currentAddressLatLong = new LatLng(gps.getLatitude(), gps.getLongitude());
//LatLng currentAddressLatLong = new LatLng(latitude, longitude);
Bitmap markerUserBitmap = CommonFunctions.createDrawableFromView(NearByActivity.this, myUserMarkerLayout);
googleMap.addMarker(new MarkerOptions().position(currentAddressLatLong).icon(BitmapDescriptorFactory.fromBitmap(markerUserBitmap)).anchor(0.5f, 1));
}
I checked, my code is creating expected bitmap successfully also code to add marker on google map is executing successfully, but marker is not visible on Map. Please guide me and let me know if I can provide more information for the same. Thank you.

how to use xml layout as cluster marker Android

I have a question, Is it possible to set a layout with multi imageviews and textviews as a cluster marker on the google map by android map utils? and how? if somebody provide an good example it would be great this an example of what i want to do:
thanks
I don't know if there is an easier way than what I used that was a year a go this method takes a lot of time if the data set is big so use it on small data set or talk to the designer for other options.
you can create a layout with what you want the get the bitmap of this layout this add the bitmap as a marker to the map since add marker only takes images.
*you need to set the data before creating the bitmap
first step inflate and set data to your layout
View marker = ((LayoutInflater) getActivity()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE))
.inflate(R.layout.marker_layout, null);
second get the bitmap from this view
Bitmap bitmap = createDrawableFromView(
getActivity(), marker);
third add the bitmap as a marker
MarkerOptions mo = new MarkerOptions().position(
new LatLng(lat, lng))
// .title(address)
.snippet(i + "")
.icon(BitmapDescriptorFactory
.fromBitmap(bitmap));
Marker customMarker = googleMap.addMarker(mo);
this is how to get the bitmap
public static Bitmap createDrawableFromView(Context context, View view) {
DisplayMetrics displayMetrics = new DisplayMetrics();
if (context != null) {
((Activity) context).getWindowManager().getDefaultDisplay()
.getMetrics(displayMetrics);
view.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
view.measure(displayMetrics.widthPixels, displayMetrics.heightPixels);
view.layout(0, 0, displayMetrics.widthPixels,
displayMetrics.heightPixels);
view.buildDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(),
view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
return null;
}
goodluck with that it was a lot of pain.

Google Map Marker with custom background and text

I'm trying to customize an map marker so that it can be displayed with 3 main features:
9patch drawable as background
Custom text
Optional drawable to the left of the text (some markers have it, some don't)
I have used IconGenerator from android google map utils library, but somehow the entire clickable area of the marker is affected. An very big area around the marker is clickable and activates the marker. It also has issues with the content padding and gravity attributes.
I have added the custom hack on the map in order to bring to front the markers without opening the info window (I've setup an info window with no content to display and I've called showInfoWindow in Marker click event listener).
How can I manually created the icon for the marker and avoid the issue with the big clickable area around it?
I have also tried the implementation described here, basically the drawTextToBitmap() method:
private Bitmap drawTextToBitmap(#DrawableRes int backgroundRes, String text) {
Resources resources = getResources();
float scale = resources.getDisplayMetrics().density;
Bitmap bitmap = BitmapFactory.decodeResource(resources, backgroundRes);
android.graphics.Bitmap.Config bitmapConfig = bitmap.getConfig();
if (bitmapConfig == null) {
bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
}
bitmap = bitmap.copy(bitmapConfig, true);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
// SET FONT COLOR (e.g. WHITE -> rgb(255,255,255))
paint.setColor(Color.rgb(255, 255, 255));
// SET FONT SIZE (e.g. 15)
paint.setTextSize((int) (15 * scale));
// SET SHADOW WIDTH, POSITION AND COLOR (e.g. BLACK)
paint.setShadowLayer(1f, 0f, 1f, Color.BLACK);
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
int x = (bitmap.getWidth() - bounds.width()) / 2;
int y = (bitmap.getHeight() + bounds.height()) / 2;
canvas.drawText(text, x, y, paint);
return bitmap;
}
But it doesn't work as expected, because my text is bigger than the background, and I also don't know how to add an resource to the left of the text.
This is the implementation for IconGenerator I'm using:
private BitmapDescriptor getBitmapDescriptorForProduct(#NonNull final MyCustomObject product, boolean isActive) {
if (product.shouldDisplayWithLabel) {
// We use an custom layout for displaying markers on the map
#SuppressLint("InflateParams") View view =
LayoutInflater.from(getActivity()).inflate(R.layout.my_custom_label, null);
// Get the text view which will display the text
TextView label = (TextView) view.findViewById(R.id.text);
// Set the left drawable if needed
label.setCompoundDrawablesWithIntrinsicBounds(product.shouldDisplayWithDrawable ? R.drawable.my_custom_drawable : 0, 0,
0, 0);
// Set the text for the label
label.setText(product.label);
label.setBackgroundResource(R.drawable.my_custom_background);
// Set the layout for the icon
mIconGenerator.setContentView(view); // set the custom layout
// We don't want the default background
mIconGenerator.setBackground(null);
// Disable the content padding as we handle it in the view and in the 9patch resources
mIconGenerator.setContentPadding(0, 0, 0, 0);
// Make the icon and create the BitmapDescriptor necessary for the marker creation
Bitmap icon = mIconGenerator.makeIcon();
return BitmapDescriptorFactory.fromBitmap(icon);
} else {
// Lazy initialization for the normal markers
if (null == simpleMarkerIcon) {
simpleMarkerIcon = BitmapDescriptorFactory.fromResource(R.drawable.my_simple_marker);
}
// Reuse the bitmap for the simple markers that will be displayed on the map.
return simpleMarkerIcon;
}
}
LE:
#Harpreet, this how the marker icon will look like using your solution:
As you can see, the properties of the view are not displayed correctly in the bitmap.
public static Bitmap createDrawableFromView(Context context, View view) {
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay()
.getMetrics(displayMetrics);
view.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
view.measure(displayMetrics.widthPixels, displayMetrics.heightPixels);
view.layout(0, 0, displayMetrics.widthPixels,
displayMetrics.heightPixels);
view.buildDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(),
view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
}
Note:- Just fill Context and add your complete custom created view/layout as an object of View
It'll help you.

Customising marker in android map, placing text inside image

I have an image to show as marker, inside that image i have to update time when the map is moving
The problem facing now is
I dont know how to show time inside my custom image.
BitmapDescriptor descriptor = BitmapDescriptorFactory.fromResource(R.drawable.ic_remaining_time);
googleMap.addMarker(new MarkerOptions()
.position(cameraPosition.target)
.title(cameraPosition.toString())
.icon(descriptor)
);
Please anyone help me
Make drawable on every time when map get changed or move and set icon like below
marker.setIcon(BitmapDescriptorFactory.fromBitmap(CommonUtils.writeOnDrawable(mContext,R.drawable.ic_location,"your text here").getBitmap()));
// Bitmap Drawable method
public static BitmapDrawable writeOnDrawable(Context context, int drawableId, String text){
Bitmap bm = BitmapFactory.decodeResource(context.getResources(), drawableId).copy(Bitmap.Config.ARGB_8888, true);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
paint.setTextSize(30);
paint.setTextAlign(Paint.Align.CENTER);
Canvas canvas = new Canvas(bm);
// Change the position of text here
canvas.drawText(text,bm.getWidth()/2 //x position
, bm.getHeight()/2 // y position
, paint);
return new BitmapDrawable(context.getResources(),bm);
}
you can get the marker when u first time add marker in google map object
Marker marker = googleMap.addMarker(new MarkerOptions().position(new LatLng(mLocation.getLatitude(), mLocation.getLongitude())).title(allJob.getBusiness().getName()).icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_location_icon)));
I don't reccomend to update repeatedly a text inside an image in marker because to achieve that you must creat a bitmap with the image and text and put that bitmap as icon marker and that's not free (in terms of memory usage).
But you can try, anyway... Create the bitmap descriptor that way and put inside the icon:
public static Bitmap createDrawableFromView(Context context, View view) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
view.setLayoutParams( new RelativeLayout.LayoutParams( RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT ) );
view.measure(displayMetrics.widthPixels, displayMetrics.heightPixels);
view.layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels);
view.buildDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap); view.draw(canvas);
return bitmap;
}
Pass to that function the view you can set as icon, inflating an xml maybe.
Try something like this -
BitmapDescriptor descriptor = BitmapDescriptorFactory.fromBitmap(BitmapFactory.decodeResource(getActivity().getResources(),R.drawable.ic_remaining_time));
googleMap.addMarker(new MarkerOptions()
.position(cameraPosition.target)
.title(cameraPosition.toString())
.icon(descriptor)
);
To get customized marker inflate your custom layout at the place of marker like below -
private Bitmap fillCustomizedMarker(int markerResource) {
//Log.d(TAG, "fillMarkerWithText ++");
View markerLayout;
markerLayout = getActivity().getLayoutInflater().inflate(R.layout.custom_marker, null);
markerLayout.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
markerLayout.layout(0, 0, markerLayout.getMeasuredWidth(), markerLayout.getMeasuredHeight());
ImageView markerImage = (ImageView) markerLayout.findViewById(R.id.marker_image);
TextView timeText = (TextView) markerLayout.findViewById(R.id.timeText);
markerImage.setImageResource(markerResource);
markerCost.setText(time);
final Bitmap bitmap = Bitmap.createBitmap(markerLayout.getMeasuredWidth(), markerLayout.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
markerLayout.draw(canvas);
return bitmap;
}
And to update this layout i would suggest you to use handler in android. It will update your UI efficiently.

Categories

Resources