title: android: how to set button on click listener on custom infoWindow using google map V2
body: <p>I want to set <code>button</code> <code>onClick</code> on custom <code>infoWindow</code> using <code>Google Map</code> V2 and below is my complete code but not working properly.</p>
  
  <p>here is my MainActivity.</p>
  
  <pre><code>public class MainActivity extends Activity {
  private ViewGroup infoWindow;
  private TextView infoTitle;
  private TextView infoSnippet;
  private Button infoButton;
  private OnInfoWindowElemTouchListener infoButtonListener;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
  
  
      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));
  
      this.infoWindow = (ViewGroup)getLayoutInflater().inflate(R.layout.info_window, null);
      this.infoTitle = (TextView)infoWindow.findViewById(R.id.title);
      this.infoSnippet = (TextView)infoWindow.findViewById(R.id.snippet);
      this.infoButton = (Button)infoWindow.findViewById(R.id.button);
  
      this.infoButtonListener = new OnInfoWindowElemTouchListener(infoButton,
              getResources().getDrawable(R.drawable.ic_launcher),
              getResources().getDrawable(R.drawable.ic_launcher))
      {
          @Override
          protected void onClickConfirmed(View v, Marker marker) {
              // Here we can perform some action triggered after clicking the button
              Toast.makeText(MainActivity.this, marker.getTitle() + "'s button clicked!", Toast.LENGTH_SHORT).show();
          }
      };
      this.infoButton.setOnTouchListener(infoButtonListener);
  
      map.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
          @Override
          public View getInfoWindow(Marker marker) {
              return null;
          }
  
          @Override
          public View getInfoContents(Marker marker) {
              // Setting up the infoWindow with current's marker info
              infoTitle.setText(marker.getTitle());
              infoSnippet.setText(marker.getSnippet());
              infoButtonListener.setMarker(marker);
              mapWrapperLayout.setMarkerWithInfoWindow(marker, infoWindow);
              return infoWindow;
          }
      });
  
      // Let's add a couple of markers
      map.addMarker(new MarkerOptions()
              .title("Prague")
              .snippet("Czech Republic")
              .position(new LatLng(50.08, 14.43)));
  
      map.addMarker(new MarkerOptions()
              .title("Paris")
              .snippet("France")
              .position(new LatLng(48.86,2.33)));
  
      map.addMarker(new MarkerOptions()
              .title("London")
              .snippet("United Kingdom")
              .position(new LatLng(51.51,-0.1)));
  }
  
  public static int getPixelsFromDp(Context context, float dp) {
      final float scale = context.getResources().getDisplayMetrics().density;
      return (int)(dp * scale + 0.5f);
  
  }
  </code></pre>
  
  <p>and below is my activity_main</p>
  
  <pre><code>&lt;com.circlegate.tt.cg.an.lib.map.MapWrapperLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/map_relative_layout"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".MainActivity" &gt;
  &lt;fragment
      android:id="@+id/map"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      class="com.google.android.gms.maps.MapFragment" /&gt;
  </code></pre>
  
  <p></p>
  
  <p>// here is MapWrapperLayout.</p>
  
  <pre><code>public class MapWrapperLayout extends RelativeLayout {
  private GoogleMap map;
  private int bottomOffsetPixels;
  private Marker marker;
  private View infoWindow;
  
  public MapWrapperLayout(Context context) {
      super(context);
  }
  public MapWrapperLayout(Context context, AttributeSet attrs) {
      super(context, attrs);
  }
  public MapWrapperLayout(Context context, AttributeSet attrs, int defStyle) {
      super(context, attrs, defStyle);
  }
  public void init(GoogleMap map, int bottomOffsetPixels) {
      this.map = map;
      this.bottomOffsetPixels = bottomOffsetPixels;
  }
  public void setMarkerWithInfoWindow(Marker marker, View infoWindow) {
      this.marker = marker;
      this.infoWindow = infoWindow;
  }
  
  @Override
  public boolean dispatchTouchEvent(MotionEvent ev) {
      boolean ret = false;
      // Make sure that the infoWindow is shown and we have all the needed references
      if (marker != null &amp;&amp; marker.isInfoWindowShown() &amp;&amp; map != null &amp;&amp; infoWindow != null) {
  
          Point point = map.getProjection().toScreenLocation(marker.getPosition());
          MotionEvent copyEv = MotionEvent.obtain(ev);
          copyEv.offsetLocation(
                  -point.x + (infoWindow.getWidth() / 2),
                  -point.y + infoWindow.getHeight() + bottomOffsetPixels);
  
          ret = infoWindow.dispatchTouchEvent(copyEv);
      }
      return ret || super.dispatchTouchEvent(ev);
  }
  </code></pre>
  
  <p>// and here is OnInfoWindowElemTouchListener</p>
  
  <pre><code>        public abstract class OnInfoWindowElemTouchListener implements View.OnTouchListener 
      {
          private final View view;
          private final Drawable bgDrawableNormal;
          private final Drawable bgDrawablePressed;
          private final Handler handler = new Handler();
          private Marker marker;
          private boolean pressed = false;
  
          public OnInfoWindowElemTouchListener(View view, Drawable bgDrawableNormal, Drawable bgDrawablePressed) {
              this.view = view;
              this.bgDrawableNormal = bgDrawableNormal;
              this.bgDrawablePressed = bgDrawablePressed;
          }
          public void setMarker(Marker marker) {
              this.marker = marker;
          }
          @Override
          public boolean onTouch(View vv, MotionEvent event) {
              if (0 &lt;= event.getX() &amp;&amp; event.getX() &lt;= view.getWidth() &amp;&amp;
                      0 &lt;= event.getY() &amp;&amp; event.getY() &lt;= view.getHeight())
              {
                  switch (event.getActionMasked()) {
                      case MotionEvent.ACTION_DOWN: startPress(); break;
                      case MotionEvent.ACTION_UP: handler.postDelayed(confirmClickRunnable, 150); break;
                      case MotionEvent.ACTION_CANCEL: endPress(); break;
                      default: break;
                  }
              }
              else {
                  endPress();
              }
              return false;
          }
          private void startPress() {
              if (!pressed) {
                  pressed = true;
                  handler.removeCallbacks(confirmClickRunnable);
                  view.setBackground(bgDrawablePressed);
                  if (marker != null)
                      marker.showInfoWindow();
              }
          }
          private boolean endPress() {
              if (pressed) {
                  this.pressed = false;
                  handler.removeCallbacks(confirmClickRunnable);
                  view.setBackground(bgDrawableNormal);
                  if (marker != null)
                      marker.showInfoWindow();
                  return true;
              }
              else
                  return false;
          }
          private final Runnable confirmClickRunnable = new Runnable() {
              public void run() {
                  if (endPress()) {
                      onClickConfirmed(view, marker);
                  }
              }
          };
          protected abstract void onClickConfirmed(View v, Marker marker);
      }
  </code></pre>