Google map v2 Custom Infowindow with two clickable buttons or ImageView

44,422

Solution 1

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.

Solution 2

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

  1. mapwrapperlauot (include your package name in tag)
  2. MapWrapperLayout.java
  3. OnInfoWindowElemTouchListener.java

It will work.

Solution 3

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.

Solution 4

I have build a sample android studio project for this question.

output screen shots :-

enter image description here

enter image description here

enter image description here

Download full project source code Click here

Please note: you have to add your API key in Androidmanifest.xml

Solution 5

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

Share:
44,422

Related videos on Youtube

Shivang Trivedi
Author by

Shivang Trivedi

Updated on July 25, 2022

Comments

  • Shivang Trivedi
    Shivang Trivedi almost 2 years

    enter image description here

    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?

    • Sreedhu Madhu
      Sreedhu Madhu over 10 years
      Use custom popup window using adapter,map.setInfoWindowAdapter(new PopupAdapterTodays(getLayoutInflater(bundle), context));
    • Shivang Trivedi
      Shivang Trivedi over 10 years
      yes this is right but how can i get two different actions for example show firstactivity on first button and secondactivity on second button in infowindow.
    • Sreedhu Madhu
      Sreedhu Madhu over 10 years
      you can create custom layout in the adapter there you can have two buttons with listeners
    • Shivang Trivedi
      Shivang Trivedi over 10 years
      can u suggest what should be in public View getInfoWindow(){}
    • Girish Bhutiya
      Girish Bhutiya over 10 years
      check this I have open a dialog on marker click.
    • Trung Nguyen
      Trung Nguyen almost 8 years
  • Shivang Trivedi
    Shivang Trivedi over 10 years
    in google map api v1 i already use custom overlay but in v2 this is not possible
  • Emil Adz
    Emil Adz over 10 years
    you can reed the edit from the documentation, what you are trying to do is not possible for V2
  • korujzade
    korujzade over 7 years
    I believe you need to make OnInfoWindowElemTouchListener for each button. Your code might work without an exception as you only show a toast popup which there is nothing to do with a specific marker. If you try to show a marker's title when infoButton1 is clicked, you will get nullpointerexception.