Write text in Google Map v2 custom marker - Android - android

In my map , I have some list of Markers, now I need to achieve the output as like below
i.e. marker with index number.
I have searched over google but didn't get any solution, Please help me to get an idea to implement this.

Do whatever you want with Google Map Markers
I have made a very flexible and interesting hack to achieve whatever kind of marker you want.
What I do is,
Create an XML Layout file and design it the way you want your marker to appear. For example in your case it is going to be a Green Marker image with a TextView on it.
Set the values of TextViews as per requirement.
Convert the Layout file to an image and get BitmapDescriptor Object.
Create a custom marker by using the image you just created.
The benefit of such view over Info Window is that you can open window for multiple markers at same time. As in InfoWindow you can open it only for one marker at one time.
Code Sample
Check out my this answer for Code Help.

For custom marker:
You can create a custom image and draw an index number in top of
that image
Check this example for custom marker
For Marker Window:
You can create a custom xml file that contains ImageView and TextViews:
Something like customMapView.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#color/white_full"
android:layout_width="match_parent"
android:padding="#dimen/padding_micro"
android:layout_height="match_parent">
<ImageView
android:id="#+id/img"
android:layout_gravity="left"
android:src="#drawable/ic_launcher"
android:textColor="#color/black_full"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:gravity="right"
android:id="#+id/name"
android:text="test"
android:textColor="#color/black_full"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!-- Other TextViews or Whatever you want-->
</RelativeLayout>
After you initialize Markers you call setInfoWindowAdapter and inflate your custom view. Something like:
private void customizeMarkerInfoWindow(){
//Setting custom info window
mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
//Use default infoWindow frame
#Override
public View getInfoWindow(Marker marker) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
// Getting view from the layout file
View view = mActivity.getLayoutInflater().inflate(R.layout.customMapView, null);
// Getting the position from the marker
LatLng latLng = marker.getPosition();
//UI elements
ImageView img = (TextView) view.findViewById(R.id.img);
TextView coord = (TextView) view.findViewById(R.id.name);
mukAdTv.setText(mukAd);
//You set the image here depending on how you want to set it, if you are downloading from internet you can use PICASSO for it and set it to img
//With picasso
Picasso.with(mActivity).load(YOUR_IMAGE_URL).into(img);
//From drawables
//img.setBackground(yourDrawable);
name.setText(latLng.latitude + ", " + latLng.longitude);
return view;
}
});
}

Related

Android Google Maps API - align custom button with existing buttons

I'm trying to display a custom button on a googlemap.
<Button
android:id="#+id/button_backHome"
android:layout_alignParentRight="true"
android:layout_marginTop="50dp"
android:layout_marginRight="11.5dp"
android:layout_height="39dp"
android:layout_width="39dp"
android:background="#drawable/custom_button"
/>
This displays the button directly below googlemap's Set Camera to Current location button in the top right of the screen, but obviously only on my test device. On other devices these settings don't align the button correctly.
XXHDPI (galaxy S4)
XHDPI (Nexus 10)
What would be a good solution, other then making all the buttons myself? Could I inherit the margins from the google button without knowing the style's name?
I'm pretty much at a loss here, and any help would be Much apreciated.
Thanks in advance!
Parent Layout for Google Maps map is RelativeLayout so best approach for custom button alignment with default Google Maps control button (for all screens) is to put that custom button into same layout as default Google Maps control button. Assume our activity with Google Maps map has layout like:
<?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>.MainActivity">
<fragment
android:id="#+id/map_fragment"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<ImageView
android:id="#+id/custom_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:visibility="gone"
android:src="#drawable/ic_home_target"/>
</RelativeLayout>
As custom button View is better to use ImageView, because the default buttons layouts has 9 patches padding in them (details here), or it's necessary to set additional padding to default Google Maps control button. Now it belongs to activity layout. So in onMapReady(GoogleMap googleMap) we should:
1) get parent View for default Google Maps control button;
2) remove custom button view from root activity layout;
3) add custom button view to parent View for default Google Maps control button (defined in p.1);
4) set alignment for custom button view relative to default Google Maps control button.
With Source code like this:
...
private GoogleMap mGoogleMap;
private MapFragment mMapFragment;
private ImageView mCustomButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCustomButton = (ImageView) findViewById(R.id.custom_button);
mMapFragment = (MapFragment) getFragmentManager()
.findFragmentById(R.id.map_fragment);
mMapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
// don't forget to allow LOCATION permission
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int locationPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
if (locationPermission == PackageManager.PERMISSION_GRANTED) {
setConrolsPositions();
}
} else {
setConrolsPositions();
}
}
void setConrolsPositions() {
try {
mGoogleMap.setMyLocationEnabled(true);
mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);
// get parent view for default Google Maps control button
final ViewGroup parent = (ViewGroup) mMapFragment.getView().findViewWithTag("GoogleMapMyLocationButton").getParent();
parent.post(new Runnable() {
#Override
public void run() {
try {
// get view for default Google Maps control button
View defaultButton = mMapFragment.getView().findViewWithTag("GoogleMapMyLocationButton");
// remove custom button view from activity root layout
ViewGroup customButtonParent = (ViewGroup) mCustomButton.getParent();
customButtonParent.removeView(mCustomButton);
// add custom button view to Google Maps control button parent
ViewGroup defaultButtonParent = (ViewGroup) defaultButton.getParent();
defaultButtonParent.addView(mCustomButton);
// create layout with same size as default Google Maps control button
RelativeLayout.LayoutParams customButtonLayoutParams = new RelativeLayout.LayoutParams(defaultButton.getHeight(), defaultButton.getHeight());
// align custom button view layout relative to defaultButton
customButtonLayoutParams.addRule(RelativeLayout.ALIGN_LEFT, defaultButton.getId());
customButtonLayoutParams.addRule(RelativeLayout.BELOW, defaultButton.getId());
// add other settings (optional)
mCustomButton.setAlpha(defaultButton.getAlpha());
mCustomButton.setPadding(defaultButton.getPaddingLeft(), defaultButton.defaultButton(),
defaultButton.getPaddingRight(), defaultButton.getPaddingBottom());
// apply layout settings to custom button view
mCustomButton.setLayoutParams(customButtonLayoutParams);
mCustomButton.setVisibility(View.VISIBLE);
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
}
and enabled Show layout boundaries option in Developer Options you should get something like that:
As you can see custom button has exactly same size as default button layout and placed exactly below it.
For better result it's necessary to adjust custom button glyph (padding, transparency, colors, etc.)
Or may be easiest way: don't use default Google Maps "GoogleMapMyLocationButton" button at all - set it's Enabled property to false (mGoogleMap.getUiSettings().setMyLocationButtonEnabled(false);) but use custom layout with button with same icon and functionality emulated by GoogleMap.animateCamera() on same layout with "target home" custom button.
You have a dpi problems in your posted image, Also in your posted xml you are only using 1 attribute values for all devices android:layout_marginRight="11.5dp" which will fail in other device with higher dpi, except the one you first tried it on.
solution:
Use the values folder with dpi click here to know about it.
What you need is to create a dimens attribute on each of the dpi folder ldpi, hdpi, etc. for the margin
sample:
<resources>
<dimen name="margin_right">11.5dp</dimen> //this is located in hdpi values dimension
</resources>
and another in xhdpi
<resources>
<dimen name="margin_right">greater than hdpi</dimen> //this is located in xhdpi values dimension
</resources>
to use it is to just call #dimension
android:layout_marginRight="#dimension/margin_right"
now using this solution will enable your device to pick the right value of the margin on different devices.

Set image to list view item onclick

I am a beginner in android application development. I was going through listview today . Got a small doubt , say, I have a listview populated with string data . Now when I click on a list view item , it should set an image to the side of the text view in that particular row. Is it possible ? Please help me out. A code snippet or a tutorial link is much appreciated ! Thanks in advance to all those genius developers out here in this forum.
Of course this is possible.You should do the following:
1. you need to define a layout file for your row of listView, it should include an Imageview and a TextView.
2. In getView method of your Adapter class, you need to inflate the layoutfile in step1, and set ImageView invisible.
3. In your onItemClicked function, you should set ImageView visible.
Wish this helps.
It's possible. First you'll need to use and adapter that inflates custom ListView item layout.
The layout would look something like this:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent">
<ImageView
android:id="#+id/itemImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/itemText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/itemImage"/>
</RelativeLayout>
Then for your list you would register a OnItemClickListener like this:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ImageView image = (ImageView) view.findViewById(R.id.itemImage);
try {
// Open the image as an InputStream
InputStream input = getAssets().open("image.jpg");
// Transform the stream to a Bitmap and set it to the ImageView
image.setImageBitmap(BitmapFactory.decodeStream(input));
} catch (IOException e) {
e.printStackTrace();
}
}
});
Note that for the listener receives the position which can be used to open and set specific images (this example uses 1 image for all items of the list).

Google Maps v2 Marker zOrdering - Set to top

I know there are a few threads around on this topic but i havent yet found a good enough solution.
I NEED to place a marker over the top of all other markers. How do i do this?
I have tried adding this marker before and after all other markers, however the ordering seems to be from bottom (front) to top (back) on the map view. This is not acceptable as I want to center on a marker which is in front of all markers.
I know that Polygons can be zOrdered but I would MUCH prefer a nicely styled graphic!
In-fact you can't order a Polygon over a marker!
"The order in which this polygon is drawn with respect to other overlays, including Polylines, GroundOverlays and TileOverlays, but not Markers. An overlay with a larger z-index is drawn over overlays with smaller z-indices. The order of overlays with the same z-index value is arbitrary. The default is 0." - https://developers.google.com/maps/documentation/android/reference/com/google/android/gms/maps/model/Polygon
Does anyone have any ideas on this?
Aiden Fry's answer works if you do actually display an InfoWindow. If you don't, the marker won't come to the front. Here is a hack to make it come to the front anyway:
Create a custom InfoWindowAdapter that displays a 0dp info window:
public class MapWindowAdapter implements GoogleMap.InfoWindowAdapter {
private Context context = null;
public MapWindowAdapter(Context context) {
this.context = context;
}
// Hack to prevent info window from displaying: use a 0dp/0dp frame
#Override
public View getInfoWindow(Marker marker) {
View v = ((Activity) context).getLayoutInflater().inflate(R.layout.no_info_window, null);
return v;
}
#Override
public View getInfoContents(Marker marker) {
return null;
}
}
Here is the code for the layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="0dp"
android:layout_height="0dp">
</LinearLayout>
When you set up your map, set the adapter and custom InfoWindowAdapter and OnMarkerClickListener (using showInfoWindow and returning true as AIden Fry advised):
mMap.setInfoWindowAdapter(new MapWindowAdapter(this));
//Call showInfoWindow to put marker on top of others.
myMarker.showInfoWindow();
This is not beautiful, but I didn't find any other way to deal with z-indexing without using info windows.
This was added in Google Play Services 9.2 (June 27, 2016)
The new MarkerOptions.zIndex() sets the stack order of a marker in relation to other markers on the map. Read more about marker z-indexes and the effect of z-index on click events. (Issue 4688)
Whilst not the perfect solution! I have figured out how to show a selected (tapped) marker over all other markers by consuming the onMarkerClick event. Returning TRUE will consume this event, so we have to do the showInfoWindow and zoom to center
#Override
public boolean onMarkerClick(Marker marker) {
//Manually open the window
marker.showInfoWindow();
//Animate to center
sMapFrag_v2.getMap().animateCamera(CameraUpdateFactory.newLatLng(marker.getPosition());
//Consume the method
return true;
}

how to create custom UI like pulse in android

I am trying to crate a Custom UI similar to pulse android app. As I understand, to start with I have to first create a custom button as shown on the below image marked.
My button has an image and text overlay on it. I know it is a basic question, but I am facing this issue, as I am a beginner to android development. Please do help me to understand how to go with this.
You could compose a simple layout from an ImageView and a TextView aligned to the bottom with black text and some transparency. Both views should be placed inside a RelativeLayout. Then you set a click listener for the RelativeLayout and take appropriate action on click.
Ex:
<RelativeLayout
android:id="#+id/item"
android:layout_width="150dp"
android:layout_height="150dp" >
<ImageView
android:layout_width="150dp"
android:layout_height="150dp"
android:src="#drawable/my_test_image" />
<TextView
android:layout_width="fill_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:background="#4000"
android:text="Giorgio Armany Galaxy S"
android:textColor="#FFF" />
</RelativeLayout>
Then in your program:
RelativeLayout item=(RelativeLayout)findViewById(R.id.item);
item.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// take action
}
});
This is one scenario. Another scenario is to extend the Button and compose your custom UI component if you would like, which will involve some more coding but instead you'll have a unique component.
Please accept the answer if it answered your question.
Now about the part with grid integration: save the XML content of the example above (RelativeLayout + ImageView + TextView), into a new XML file, let it be layout/grid_item.xml.
Add a unique id for the ImageView and TextView
Then in the getView() method of your adapter inflate that layout and find the ImageView and TextView by id, and set appropriate content.
Note, this is not full source code, but a basic scheleton should look like this:
public View getView(int position, View convertView, ViewGroup parent) {
....
convertView = mInflater.inflate(R.layout.grid_item, null);
....
ImageView myImage=(ImageView)convertView.findViewById(R.id.my_image);
TextView myTextView=(TextView)convertView.findViewById(R.id.my_textview);
myImage.setImageResource(...);
myTextView.setText(...);
...
return convertView
}

Android - Google Maps add overlays

I am facing a problem of adding overlays. I want to add button which will toggle between normal and satelitte view, and some textView, which will display my actual coordinates and those will be updated on my location change. I tried to put there classic TextView, added into my map.java import for using GPS, and onLocationChanged I am trying to update TextView's, but no success. It must be done via Overlays, but I can't see, how to set on the screen my desired items - button with specific function and regularly updated textView. Any ideas?
THanks
edit:
int g=0;
mapView = (MapView) findViewById(R.id.mapview);
mapView.setBuiltInZoomControls(true);
mapView.setEnabled(true);
mapView.setClickable(true);
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.toggle:
if (g!=1){
mapView.invalidate();
mapView.setSatellite(true);
mapView.invalidate();
g=1;
}else{
mapView.invalidate();
mapView.setSatellite(false);
mapView.invalidate();
}
break;
}
}
You don't need a overlay for this. Just define you layout using a layout xml file with an RelativeLayout as root element.
With a relative layout you can place elements like TextViews or a Buttons on top of each other. So in your case you would first define the MapView in your layout file and then the elements you want to display on the MapView. Now all elements should be rendered in the upper left corner on top of each other. Using the attributes defined by the RelativeLayout you can now align your elements in the way you want. Have a look at the RealtiveLayout tutorial for a better understanding.
Here a some nice resources:
http://developer.android.com/resources/tutorials/views/hello-mapview.html
http://mobiforge.com/developing/story/using-google-maps-android
Efficient Map Overlays in Android Google Map
Hope you get an answer :-)

Categories

Resources