title: Google Maps API V2, I want to restrict the map to a bounding box
body: <p>I want to limit the visible map to a pre-defined rectangle on screen. For example, I am making a mapping application of a famous location with polylines and polygons on top of the map, and I do not want my users to scroll outside of the map. Is there a simple way to achieve this?</p>
  
  <p>I have looked through documentation and want to be able to set the <a href="http://developer.android.com/reference/com/google/android/gms/maps/model/VisibleRegion.html" rel="nofollow">VisibleRegion</a> on the map, but there appears no clean-cut solution.</p>
  
  <p>So here is my first attempt. It is ok in that if the user goes outside the map, it brings them back. However, I want it to stop immediately and prevent further interaction.</p>
  
  <pre><code>public class RestrictedMapView extends MapView implements GoogleMap.OnCameraChangeListener {
  
  private CameraPosition mCameraPosition;
  
  private LatLngBounds mRegion;
  
  private int mMaxZoom, mMinZoom;
  
  private boolean mTouchEnabled = true;
  
  private GoogleMap.OnCameraChangeListener mCameraChangeListener;
  
  private GoogleMap.CancelableCallback mCancelCallback = new GoogleMap.CancelableCallback() {
      @Override
      public void onFinish() {
          mTouchEnabled = true;
      }
  
      @Override
      public void onCancel() {
  
      }
  };
  
  public RestrictedMapView(Context context) {
      super(context);
  }
  
  public RestrictedMapView(Context context, AttributeSet attrs) {
      super(context, attrs);
  }
  
  public RestrictedMapView(Context context, AttributeSet attrs, int defStyle) {
      super(context, attrs, defStyle);
  }
  
  public RestrictedMapView(Context context, GoogleMapOptions options) {
      super(context, options);
  }
  
  /**
   * Call this after map has been created
   */
  public void initialize(){
      getMap().setOnCameraChangeListener(this);
  }
  
  public void setOnCameraChangeListener(GoogleMap.OnCameraChangeListener onCameraChangeListener){
      this.mCameraChangeListener = onCameraChangeListener;
  }
  
  /**
   * Sets the visible region we restrict the map to being in
   * @param visibleRegion
   */
  public void setVisibleRegion(int minZoom, int maxZoom, LatLngBounds visibleRegion){
      mRegion = visibleRegion;
      mMinZoom = minZoom;
      mMaxZoom = maxZoom;
  }
  
  @Override
  public void onCameraChange(CameraPosition cameraPosition) {
      if(mCameraChangeListener!=null){
          mCameraChangeListener.onCameraChange(cameraPosition);
      }
  
      if(!mRegion.contains(cameraPosition.target)){
          mTouchEnabled = false;
          getMap().animateCamera(CameraUpdateFactory.newLatLngBounds(mRegion, 0), mCancelCallback);
      } else {
          mCameraPosition = cameraPosition;
          if(mCameraPosition.zoom&gt;mMaxZoom){
              mTouchEnabled = false;
              CameraPosition cameraPosition1 = new CameraPosition(cameraPosition.target, mMaxZoom, cameraPosition.tilt, cameraPosition.bearing);
              getMap().animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition1), mCancelCallback);
  
          } else if(mCameraPosition.zoom&lt;mMinZoom){
              mTouchEnabled = false;
              CameraPosition cameraPosition1 = new CameraPosition(cameraPosition.target, mMinZoom, cameraPosition.tilt, cameraPosition.bearing);
              getMap().animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition1), mCancelCallback);
          }
      }
  }
  
  @Override
  public boolean dispatchTouchEvent(MotionEvent ev) {
      if(mTouchEnabled) {
          return super.dispatchTouchEvent(ev);
      } else{
          return true;
      }
  }
  </code></pre>
  
  <p>I hope this helps.</p>