Close PopupWindow upon tapping outside or back button - android

I want to close a PopupWindow by either tapping outside the window or pressing a back button. Right now you can tap anywhere on the screen and the window closes, and I can't figure out why. I'd also like to add a shadow to the PopupWindow. Thanks!
MainActivity.Java:
public class MainActivity extends FragmentActivity implements OnMapReadyCallback, GoogleMap.OnMarkerClickListener{
LinearLayout mainLayout;
private GoogleMap mMap;
PlaceAutocompleteFragment placeAutoComplete;
private static final String TAG = "Main Activity";
List<Marker> list = new ArrayList<>();
Marker NY_MANHATTAN;
Marker NY_BROOKLYN;
Marker NY_BRONX;
Marker NY_QUEENS;
Marker NY_STATENISLAND;
private PopupWindow popupWindow;
private LayoutInflater layoutInflater;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//TODO:initialize startup stuff here:
/*
* layoutTest is the testing inflater for all popup windows.
* here is where new popup windows will be added to the list.
* */
mainLayout = (LinearLayout) findViewById(R.id.mainLayout);
placeAutoComplete = (PlaceAutocompleteFragment) getFragmentManager().findFragmentById(R.id.place_autocomplete);
placeAutoComplete.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected(Place place) {
Log.i(TAG, "Place Selected: " + place.getName());
LatLng latLng = place.getLatLng();
//move map camera
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 11));
}
#Override
public void onError(Status status) {
Log.d("Maps", "An error occurred: " + status);
}
});
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
try {
// Customise the styling of the base map using a JSON object defined
// in a raw resource file.
boolean success = googleMap.setMapStyle(
MapStyleOptions.loadRawResourceStyle(
this, R.raw.style_json));
if (!success) {
Log.e(TAG, "Style parsing failed.");
}
} catch (Resources.NotFoundException e) {
Log.e(TAG, "Can't find style. Error: ", e);
}
//TODO: DEFINE MARKER LOCATIONS HERE:
LatLng manhattanLoc = new LatLng(40.754932, -73.984016);
LatLng brooklynLoc = new LatLng(40.650002, -73.949997);
LatLng bronxLoc = new LatLng(40.837048, -73.865433);
LatLng queensLoc = new LatLng(40.742054, -73.769417);
LatLng statenIslandLoc = new LatLng(40.579021, -74.151535);
//TODO: INIT MARKERS HERE:
NY_MANHATTAN = googleMap.addMarker(new MarkerOptions().position(manhattanLoc).title("Manhattan").snippet("test"));
list.add(NY_MANHATTAN);
NY_BROOKLYN = googleMap.addMarker(new MarkerOptions().position(brooklynLoc).title("Brooklyn").snippet("test"));
list.add(NY_BROOKLYN);
NY_BRONX = googleMap.addMarker(new MarkerOptions().position(bronxLoc).title("Bronx").snippet("test"));
list.add(NY_BRONX);
NY_QUEENS = googleMap.addMarker(new MarkerOptions().position(queensLoc).title("Queens").snippet("test"));
list.add(NY_QUEENS);
NY_STATENISLAND = googleMap.addMarker(new MarkerOptions().position(statenIslandLoc).title("Staten Island").snippet("test"));
list.add(NY_STATENISLAND);
googleMap.setOnCameraChangeListener(new
GoogleMap.OnCameraChangeListener() {
#Override
public void onCameraChange(CameraPosition cameraPosition) {
for (Marker m : list) {
m.setVisible(cameraPosition.zoom > 10); // <-- define zoom level for markers here
/**
* Zoom level guidelines:
* 12 = zoomed in about 90%
* 1 = zommed in less than 5%
* Higher = higher zoom, Lower = lower zoom.
* Confusing. I know.
*/
}
}
});
mMap.setOnMarkerClickListener(this);
}
//TODO: handle marker clicks below:
/*
* current placeholder code states that all markers
* will open the popup_test layout.
* */
public boolean onMarkerClick(Marker arg0) {
PopupInit();
return false;
}
public void PopupInit()
{
layoutInflater = (LayoutInflater) getApplicationContext().getSystemService(LAYOUT_INFLATER_SERVICE);
ViewGroup container = (ViewGroup) layoutInflater.inflate(R.layout.popup_test,null);
/*
*
* set x/y locations here:
*
* */
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int popWidth = dm.widthPixels;
int popHeight = dm.heightPixels;
popupWindow = new PopupWindow(container,(int) (popWidth*.8),(int) (popHeight*.6),true);
popupWindow.showAtLocation(mainLayout, Gravity.CENTER,0,0);
container.setOnTouchListener(new View.OnTouchListener()
{
#Override
public boolean onTouch(View view, MotionEvent motionEvent)
{
popupWindow.dismiss();
return true;
}
});
}
}
Popup_Test.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#fff55250"
android:layout_width="match_parent"
android:layout_height="match_parent">
</RelativeLayout>
Sorry about the noob question. I've been at this for a while and I just can't seem to figure out no matter how much I try... my biggest two concerns are getting the shadow behind the popupwindow and also closing it upon the press of the back button or tapping outside the popup window. thanks very much in advance. thanks.

You will need to set Background Drawable using and on Outside touch true
popWindow.setFocusable(true);
popupWindow.setBackgroundDrawable(new ColorDrawable())
popupWindow.setOutsideTouchable(true);
method by passing any drawable. Otherwise the whole screen is your background and tapping outside will not work backPressed will work automatically using this way!
To add a shadow to you PopupWindow the easier way is to put CardView as the root of your View in xml and change elevation attribute. To use CardView you may have to add a dependency it in your gradle file as well
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view"
android:layout_gravity="center"
android:layout_width="200dp"
android:layout_height="200dp"
card_view:cardElevation="4dp"
card_view:cardCornerRadius="4dp">
<!--YOUR RELATIVE LAYOUT SHOULD BE HERE!-->
</android.support.v7.widget.CardView>
You also have to add dependency in your app gradle files like:
dependencies {
...
compile 'com.android.support:cardview-v7:21.0.+'
}
More details in CardView and elevation here.
THIS IS HOW IT LOOKS IN MY CODE
LayoutInflater layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// inflate the custom popup layout
final View inflatedView = layoutInflater.inflate(R.layout.pop_up_test, null,false);
// get device size
Display display = getWindowManager().getDefaultDisplay();
final Point size = new Point();
display.getSize(size);
//mDeviceHeight = size.y; //Not in use just comment it off for now
// set height depends on the device size
popupWindow = new PopupWindow(inflatedView, size.x - 50,(WindowManager.LayoutParams.WRAP_CONTENT), true );
// set a background drawable with rounders corners
// make it focusable to show the keyboard to enter in `EditText`
popupWindow.setFocusable(true);
popupWindow.setBackgroundDrawable(new ColorDrawable());//This has no meaning than dismissal of the Pop Up Noni!!
// make it outside touchable to dismiss the popup window
popupWindow.setOutsideTouchable(true);
// show the popup at bottom of the screen and set some margin at bottom ie,
popupWindow.showAtLocation(v, Gravity.BOTTOM, 0,100);

I could override your onBackPressed() method in your Activity. That being said, if you press your back button this method is fired. In that method you can check wether the popup is showing, and dissmiss it if needed, like this:
#Override
public void onBackPressed() {
if (popupWindow != null && popupWindow.isShowing()) {
popupWindow.dismiss();
}
super.onBackPressed();
}
You can implement the dismiss() logic also with some onClickListeners from the area's you want the user to click to cancel the popup.

If you don't want to use Xenolion asnwer for whatever reason, You can just create backdrop manually which goes over your whole screen.
Add whatever on top of it.
Add onclick listener on backdrop which closes backdrop and window.
Add onclick listener on popupwindow as null that will prevent from closing pop up when clicked on top of it.
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</LinearLayout>
<LinearLayout
android:id="#+id/popUp"
android:layout_width="500dp"
android:layout_height="500dp"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="#+id/backdrop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"></LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
backdrop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// code to close backdrop and pop up
}
};)
// this prevents closing of the window by clicking on pop up window
popup.setOnClickListener(null);

I had popups that would not be dismissed by either back button or tap outside on Android 5. I worked great on newer Android versions, just not on Android 5, Lollipop, API level 21.
All that was needed in my case was:
popupWindow.setBackgroundDrawable(new ColorDrawable())
Go figure!

Related

Clickable links or buttons inside Google Maps - Info Windows

I am using Xamarin to render map with pins in Android. I am able Load the map and show custom Info window for my app, but I want a button or a link inside my Info window which when clicked do some computation and start a new activity.
This is what I am looking for:
On click of links (link1 and link2) I would like to redirect user to new screen based on some value. My concern here is how can I get a click function for the links.
Also I want the Info Window to have rounded corners and have a pointer pointing to the pin.
Here is my code for above example:
Activity
public class MainActivity : Activity, IOnMapReadyCallback
{
private GoogleMap GMap;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
SetUpMap();
}
private void SetUpMap()
{
if (GMap == null)
{
FragmentManager.FindFragmentById<MapFragment>(Resource.Id.googlemap).GetMapAsync(this);
}
}
public void OnMapReady(GoogleMap googleMap)
{
this.GMap = googleMap;
GMap.UiSettings.ZoomControlsEnabled = true;
LatLng latlng = new LatLng(Convert.ToDouble(15.354942), Convert.ToDouble(73.929845));
MarkerOptions markerOpt = new MarkerOptions();
markerOpt.SetPosition(latlng).SetTitle("test")
.SetSnippet("test")
.SetIcon(BitmapDescriptorFactory.DefaultMarker(BitmapDescriptorFactory.HueOrange));
MapAdapter adapter = new MapAdapter(this);
GMap.SetInfoWindowAdapter(adapter);
GMap.AddMarker(markerOpt).ShowInfoWindow();
GMap.MoveCamera(CameraUpdateFactory.NewLatLngZoom(
new LatLng(15.354942, 73.929845), 20));
}
}
Adapter
public class MapAdapter : Java.Lang.Object, GoogleMap.IInfoWindowAdapter
{
private IOnTouchListener infoButtonListener;
LayoutInflater inflater;
private Activity context;
public MapAdapter(Activity context)
{
this.context = context;
}
public View GetInfoContents(Marker marker)
{
return null;
}
public View GetInfoWindow(Marker marker)
{
View view = context.LayoutInflater.Inflate(Resource.Layout.CustomWindow, null);
TextView Link1 = (TextView)view.FindViewById(Resource.Id.Link1);
TextView Link2 = (TextView)view.FindViewById(Resource.Id.Link2);
String udata = "Link1";
SpannableString content = new SpannableString(udata);
content.SetSpan(new UnderlineSpan(), 0, udata.Length, 0);
gotoLink.SetText(content,TextView.BufferType.Normal);
String udataPickup = "Link2";
SpannableString contentPickup = new SpannableString(udataPickup);
contentPickup.SetSpan(new UnderlineSpan(), 0, udataPickup.Length, 0);
pickupLink.SetText(contentPickup, TextView.BufferType.Normal);
return view;
}
}
Actually, it is not possible, Google Map renders the content of your custom InfoWindow into an image and displays it to you as an Image. Therefore you set a click Listener only to the whole window and not to the Views inside it.
Your only choice is to set the ClickListener to the whole InfoWindow and popup a Dialog with clickable content you want, and not do it directly inside the InfoWindow.
From Google Docs: https://developers.google.com/maps/documentation/android/marker#info_windows
Note: The info window that is drawn is not a live view. The view is rendered as an image (using View.draw(Canvas)) at the time it is returned. This means that any subsequent changes to the view will not be reflected by the info window on the map. To update the info window later (e.g., after an image has loaded), call showInfoWindow(). Furthermore, the info window will not respect any of the interactivity typical for a normal view such as touch or gesture events. However, you can listen to a generic click event on the whole info window as described in the section below.`

Why can't I access a button added to a custom info window added to a marker in Google Maps?

I'm creating a small app that will help a user find a sports club. Based on the type of sport picked from a spinner in the previous activity a number of markers representing different clubs will be shown on a map.(See screenshot below)
Results after a type of sport is clicked in a spinner
I've attempted to add a button to an information window (contains a title, and a snippet) of a marker in Google Maps that will start another activity. It will produce a toast pop up for now. At the moment I'm producing the following result:
App Screenshot (unable to embed image as reputation too low)
The issue I'm having is that I cannot interact with the button in the info window when I try to click the button the whole information window gets clicked instead (leads to the window changing from a white to a grey background to show it was clicked). This happens whether I try to click the button or any other section of the information window.
Grey background to signify info window was clicked
To do this I created an XML layout file (custom_window_info.xml) that would be displayed in the map activity in the event of a marker being clicked. It displays the title, snippet and the button method declared in the MapActivity.java class.
I then created a java class (CustomInfoWindowAdapter.java) that provided the java functionality for the layout file mentioned above, e.g. assigning the values to the title and snippet text fields, the getInfoWindow() and getInfoContents() methods, etc.
I'm not sure If I've approached this the wrong way entirely or I'm making a little mistake. Any tips/suggestions?
custom_window_info.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:padding="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/title"
android:layout_gravity="center_horizontal"
android:ellipsize="end"
android:maxLines="1"
android:textColor="#000"
android:textSize="14sp"
android:textStyle="bold"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:id="#+id/snippet"
android:maxLines="5" />
<Button
android:id="#+id/joinCLub"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:onClick="ClubButtonClick"
android:text="Join Club"
android:visibility="visible" />
</LinearLayout>
</LinearLayout>
CustomInfoWindowAdapter.java
public class CustomInfoWindowAdapter implements GoogleMap.InfoWindowAdapter {
private final View mWindow;
private Context mContext;
public CustomInfoWindowAdapter(Context context) {
this.mContext = mContext;
this.mWindow = LayoutInflater.from(context).inflate(R.layout.custom_info_window, null);
}
private void rendowWindowText(Marker marker, View v){
String title = marker.getTitle();
TextView clubtitle = (TextView) v.findViewById(R.id.title);
if(!title.equals(" ")){
clubtitle.setText(title);
}
String snippet = marker.getSnippet();
TextView clubsnippet = (TextView) v.findViewById(R.id.snippet);
if(!title.equals(" ")){
clubsnippet.setText(snippet);
}
}
#Override
public View getInfoWindow(Marker marker) {
rendowWindowText(marker, mWindow);
return mWindow;
}
#Override
public View getInfoContents(Marker marker) {
rendowWindowText(marker, mWindow);
return mWindow;
}
}
MapActivity.java
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Assigning coordinates to a club (I've left out the 4 other markers to reduce the code)
LatLng vincentsGAA = new LatLng(53.374042,-6.2300634);
// Adding marker to map with the coordinates declared above, a title for the name of the club and a snippet for the address
mMap.addMarker(new MarkerOptions().position(vincentsGAA).title("St Vincents GFC").snippet("Malahide Road, Dublin"));
//Assigning the default coordinates to Dublin, Ireland when the map opens
LatLng dublin = new LatLng(53.3242381,-6.385785);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(dublin, 10));
// Sets the custom info window to this map activity's markers
mMap.setInfoWindowAdapter(new CustomInfoWindowAdapter(MapsActivity.this));
}
// This is the back button in the top right of the map activity that will
// bring the user back to the previous activity that had the spinner that
// allows the user to pick the type of sport they want to see clubs for
public void ButtonClick(View v) {
Intent intent1 = new Intent(this, Welcome_Activity.class);
startActivity(intent1);
}
}
Actually, it not possible, Google Map renders the content of your custom InfoWindow into an image and displays it to you as an Image. Therefore you set a click Listener only to the whole window and not to the Views inside it.
Your only choice is to set the ClickListener to the whole InfoWindow and popup a Dialog with clickable content you want, and not do it directly inside the InfoWindow.
From Google Docs: https://developers.google.com/maps/documentation/android/marker#info_windows
Note: The info window that is drawn is not a live view. The view is rendered as an image (using View.draw(Canvas)) at the time it is returned. This means that any subsequent changes to the view will not be reflected by the info window on the map. To update the info window later (e.g., after an image has loaded), call showInfoWindow(). Furthermore, the info window will not respect any of the interactivity typical for a normal view such as touch or gesture events. However, you can listen to a generic click event on the whole info window as described in the section below.`

Google map v2 Custom Infowindow with two clickable buttons or ImageView

I need custom info window with two clickable button as above.In it when more then marker and click any one of them then window should be open and when click on another marker another window should open and close previous window as well in single click.
is there any specific reason why google map v2 not support live component like button ,check box?
What you are trying to achieve is possible.
You can see the recipe in this answer: https://stackoverflow.com/a/15040761/2183804
And a working implementation on Google Play.
MainActivity.java
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class MainActivity extends Activity {
private ViewGroup infoWindow;
private TextView infoTitle;
private TextView infoSnippet;
private Button infoButton1, infoButton2;
private OnInfoWindowElemTouchListener infoButtonListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mapwrapperlauot);
final MapFragment mapFragment =
(MapFragment) getFragmentManager().findFragmentById(R.id.map);
final MapWrapperLayout mapWrapperLayout =
(MapWrapperLayout) findViewById(R.id.map_relative_layout);
final GoogleMap map = mapFragment.getMap();
mapWrapperLayout.init(map, getPixelsFromDp(this, 39 + 20));
final Marker ki = map.addMarker(new MarkerOptions()
.position(new LatLng(50.08, 14.43))
.icon(BitmapDescriptorFactory
.fromResource(R.drawable.circles)));
infoWindow = (ViewGroup) getLayoutInflater()
.inflate(R.layout.activity_main, null);
infoButton1 = (Button) infoWindow.findViewById(R.id.b1);
infoButton2 = (Button) infoWindow.findViewById(R.id.b2);
infoButtonListener = new OnInfoWindowElemTouchListener(infoButton1,
getResources().getDrawable(R.drawable.ic_launcher),
getResources().getDrawable(R.drawable.ic_launcher)) {
#Override
protected void onClickConfirmed(View v, Marker marker) {
Toast.makeText(getApplicationContext(),
"click on button 1", Toast.LENGTH_LONG).show();
}
};
infoButton1.setOnTouchListener(infoButtonListener);
infoButtonListener = new OnInfoWindowElemTouchListener(infoButton2,
getResources().getDrawable(R.drawable.ic_launcher),
getResources().getDrawable(R.drawable.ic_launcher)) {
#Override
protected void onClickConfirmed(View v, Marker marker) {
Toast.makeText(getApplicationContext(),
"click on button 2", Toast.LENGTH_LONG).show();
}
};
infoButton2.setOnTouchListener(infoButtonListener);
infoWindow.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
map.setInfoWindowAdapter(new InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker marker) {
infoButtonListener.setMarker(marker);
mapWrapperLayout.setMarkerWithInfoWindow(marker, infoWindow);
return infoWindow;
}
#Override
public View getInfoContents(Marker marker) {
// Setting up the infoWindow with current's marker info
return null;
}
});
ki.showInfoWindow();
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(50.08, 14.43), 15));
map.animateCamera(CameraUpdateFactory.zoomTo(10), 2000, null);
}
public static int getPixelsFromDp(Context context, float dp) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
}
activity_main
<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"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:background="#drawable/marker" >
<Button
android:id="#+id/b1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Button1"
android:layout_marginBottom="10dp" />
<Button
android:id="#+id/b2"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Button2"
android:layout_marginBottom="10dp" />
</LinearLayout>
</RelativeLayout>
now copy the following files from the link https://stackoverflow.com/a/15040761/2183804
mapwrapperlauot (include your package name in tag)
MapWrapperLayout.java
OnInfoWindowElemTouchListener.java
It will work.
I have build a sample android studio project for this question.
output screen shots :-
Download full project source code Click here
Please note: you have to add your API key in Androidmanifest.xml
What you are trying to achieve is not possible. Even if you create an XML layout for your info-window, info window contents are rendered and presented as an image on the maps. So it can accept only one click listener for the whole window. You can't specify multiple click listeners for a window.
UPDATE:
From the Docs:
Note: The info window that is drawn is not a live view. The view is rendered as an image (using View.draw(Canvas)) at the time it is returned. This means that any subsequent changes to the view will not be reflected by the info window on the map. To update the info window later (e.g., after an image has loaded), call showInfoWindow(). Furthermore, the info window will not respect any of the interactivity typical for a normal view such as touch or gesture events. However you can listen to a generic click event on the whole info window as described in the section below.
There is actually a library that can resolve your problem and add an info window that is a live view and you can interact with it.
https://github.com/Appolica/InteractiveInfoWindowAndroid

Android Google Map API V2 : Open Custom Info Window on Right Side of Marker

I have Integrated Google MAP API V2 for Android. I want to have a Custom Info Window at Onclick of My Marker. Up to that it is fine. i have integrate it.
What I want : I want to Show my Custom Info Window on Right Side of Marker Instead of Top of the Marker.
Below is the Code I am Using :
public class MainActivity extends FragmentActivity {
private MainMapFragement mapFragment;
private HashMap<Marker, EventInfo> eventMarkerMap;
Marker ThirdMarker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mapFragment = new MainMapFragement();
// FragmentTransaction ft = getFragmentManager().beginTransaction();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.map, mapFragment);
ft.commit();
}
#Override
protected void onStart() {
super.onStart();
setUpEventSpots();
}
private void setUpEventSpots() {
// I'm going to make 2 EventInfo objects and place them on the map
EventInfo firstEventInfo = new EventInfo(new LatLng(50.154, 4.35),
"Right now - event", new Date(), "Party");
EventInfo secondEventInfo = new EventInfo(new LatLng(51.25, 4.15),
"Future Event", new Date(1032, 5, 25), "Convention");
EventInfo thirdEventInfo = new EventInfo(new LatLng(23.25, 72.15),
"Our Next Event", new Date(), "Ahmedabad-India");
// this date constructor is deprecated but it's just to make a simple
// example
Marker firstMarker = mapFragment.placeMarker(firstEventInfo);
Marker secondMarker = mapFragment.placeMarker(secondEventInfo);
ThirdMarker = mapFragment.placeMarker(thirdEventInfo);
eventMarkerMap = new HashMap<Marker, EventInfo>();
eventMarkerMap.put(firstMarker, firstEventInfo);
eventMarkerMap.put(secondMarker, secondEventInfo);
eventMarkerMap.put(ThirdMarker, thirdEventInfo);
// add the onClickInfoWindowListener
mapFragment.getMap().setOnInfoWindowClickListener(
new OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
EventInfo eventInfo = eventMarkerMap.get(marker);
Toast.makeText(
getBaseContext(),
"The date of "
+ eventInfo.getName()
+ " is "
+ eventInfo.getSomeDate()
.toLocaleString(),
Toast.LENGTH_LONG).show();
}
});
// Custom Bhavesh
mapFragment.getMap().setInfoWindowAdapter(new InfoWindowAdapter() {
private final View window = getLayoutInflater().inflate(
R.layout.ballonoverlly, null);
#Override
public View getInfoWindow(Marker marker) {
EventInfo eventInfo = eventMarkerMap.get(marker);
String title = marker.getTitle();
TextView txtTitle = ((TextView) window
.findViewById(R.id.textview_name));
if (title != null) {
// Spannable string allows us to edit the formatting of the
// text.
SpannableString titleText = new SpannableString(title);
titleText.setSpan(new ForegroundColorSpan(Color.RED), 0,
titleText.length(), 0);
txtTitle.setText(titleText);
} else {
txtTitle.setText("");
}
// TextView txtType = ((TextView) window
// .findViewById(R.id.textview_aboutme));
// if (eventInfo.getType() != null)
// txtType.setText(eventInfo.getType());
return window;
}
#Override
public View getInfoContents(Marker marker) {
// this method is not called if getInfoWindow(Marker) does not
// return null
return null;
}
});
}
}
xml file :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/RlMain"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<LinearLayout
android:id="#+id/imageview_comment"
android:layout_width="150dp"
android:layout_height="62dp"
android:background="#drawable/map_comment_back"
android:gravity="center_vertical"
android:orientation="vertical"
android:scaleType="fitXY"
android:visibility="visible" >
<TextView
android:id="#+id/textview_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:text="Bhavesh Patadiya"
android:textColor="#FFFFFF"
android:textStyle="bold" />
<TextView
android:id="#+id/textview_aboutme"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"
android:maxLines="2"
android:text="How&apos;s Going?"
android:textColor="#FFFFFF"
android:textStyle="normal" />
</LinearLayout>
</LinearLayout>
Below is the Screen Shot of What I am getting :
Now , I want to have my custom InfoWindow to the Right Side of the Marker instead of Top.
All Helps are Appreciated.
Thanks in Advance.
Edit 2:
Starting from September update (v12 or 3.2.65) of the Google Maps Android API v2 MarkerOptions.infoWindowAnchor was added. There are quite a few new functions, so check release notes too.
Edit 3:
Unfortunatelly this addition doesn't solve your problem yet. Added new issue for that.
This is not currently possible.
Trying to work around it by putting a View over MapFragment can be a good solution if users are not allowed to move the map. If they can, you will see some bad lags on repositioning when using either "push techonology" onCameraChange or polling with Handler and map.getCameraPosition().
Same problems if you try to use additional marker with transparent icon to show info window on when the visible is clicked, but it would be more fun to see it actually implemented.
If you can live without info window on the right for now, I would suggest starring this feature already requested and waiting.
Edit:
As of 3.1.36 (rev. 7) of the API v2 you can change the icon of marker. This means you can make two icons: one normal, and another that looks like you have an info window open on the right. Disabling opening default info window and using this instead might work for you.
You can do by simple convert marker.getPosition() to screenPosition like below code
Projection projection = map.getProjection();
LatLng markerLocation = marker.getPosition();
Point screenPosition = projection.toScreenLocation(markerLocation);
int x = screenPosition.x +marker. markerImage.getWidth();
You can ref below link for more infomation (which convert getPosition to projection):
How to get screen coordinates from marker in google maps v2 android

Android - setInfoWindowAdapter with WebView in google Marker (api v2)

I have a problem with marker on google maps api v2.
I would like to customize infoWindows with a WebView:
Here my code of InfoWindowAdapter
mMap.setInfoWindowAdapter(new InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
#Override
public View getInfoContents(Marker arg0) {
View v = getLayoutInflater().inflate(R.layout.info_window_layout, null);
TextView title = (TextView) v.findViewById(R.id.title_marker);
WebView snippet = (WebView) v.findViewById(R.id.item_snippet);
title.setText(arg0.getTitle());
snippet.setVisibility(WebView.VISIBLE);
snippet.loadData(arg0.getSnippet(),"text/html", "UTF-8");
return v;
}
});
And this is the layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/title_marker"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<WebView
android:id="#+id/item_snippet"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
My problem is that I see the content into the TextView, but not the content into the WebView.
What i'm doing wrong?
Thanks a lot
You can't use a WebView directly. The reason is (source: official docs):
Note: The info window that is drawn is not a live view. The view is rendered as an image (using View.draw(Canvas)) at the time it is returned. This means that any subsequent changes to the view will not be reflected by the info window on the map. To update the info window later (e.g., after an image has loaded), call showInfoWindow(). Furthermore, the info window will not respect any of the interactivity typical for a normal view such as touch or gesture events. However you can listen to a generic click event on the whole info window as described in the section below.
You can try drawing the webview on a bitmap (after the content has been loaded) and supplying an ImageView with that bitmap in the InfoWindow adapter, but you will lose interactivity with the webview anyway.
after a lot of tests, googling and some reversing I can say that view you return in getInfoContents is used to render into a Bitmap and then hidden. The bitmap is then displayed via GL
I've found a workaround that can be fine for you.
private View mGhost;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mGhost = new View(this);
mGhost.setLayoutParams(new LayoutParams(0, 0));
mGhost.setVisibility(View.GONE);
....
}
public void onMapReady(GoogleMap map) // or whatever
{
map.setInfoWindowAdapter(new InfoWindowAdapter()
{
#Override
public View getInfoWindow(Marker marker)
{
return null;
}
#Override
public View getInfoContents(final Marker marker)
{
WebView webview = new WebView(MainActivity.this);
webview.loadUrl(marker.getSnippet());
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
AlertDialog alert = builder.setView(webview).create();
alert.show();
alert.getWindow().setLayout(200, 200);
mGhost.post(new Runnable()
{
#Override
public void run()
{
marker.hideInfoWindow();
}
});
return mGhost;
}
});
}
in this example I've used the snippet to store the url, It's not exactly what did you asked, but it may look similar.
Edit: the first version was recycling the WebView but it's not possible without some trick to remove it from the Alert, this revised version doesn't shows the InfoContents box below but has still an issue, when pressed it keeps a sort of state, and it believes the marker is clicked after closing the dialog.
You may use a layout that contains a WebView to decor a bit the window
Edit2: Reverted to something like the first version, a blank InfoContents box shows for bit I'm not sure it's avoidable.

Categories

Resources