Map Rotation

The Map Rotation sample app shows how to allow a user to rotate a map, and also shows a compass that displays the current map rotation angle. The setAllowRotationByPinch method allows rotation of the map using a pinch gesture; the current angle of rotation is then retrieved from the MapView using getRotationAngle. A custom View showing a compass image is added to the map, which rotates itself in response to the OnPinchListener set on the MapView. An OnSingleTapListener allows the map rotation angle to be reset to 0 by tapping on the map.

Features

  • MapView
  • OnPinchListener
  • Compass

Sample Code

/* Copyright 2010 ESRI
 *
 * All rights reserved under the copyright laws of the United States
 * and applicable international laws, treaties, and conventions.
 *
 * You may freely redistribute and use this sample code, with or
 * without modification, provided you include the original copyright
 * notice and use restrictions.
 *
 * See the Sample code usage restrictions document for further information.
 *
 */

package com.esri.arcgis.android.samples.maprotation;

import android.app.Activity;
import android.os.Bundle;

import com.esri.android.map.MapView;
import com.esri.android.map.event.OnSingleTapListener;

/**
 * The Map Rotation sample app shows how to allow a user to rotate a map, and also shows a compass that displays the
 * current map rotation angle. The setAllowRotationByPinch method allows rotation of the map using a pinch gesture; the
 * current angle of rotation is then retrieved from the MapView using getRotationAngle. A custom View showing a compass
 * image is added to the map, which rotates itself in response to the OnPinchListener set on the MapView. An
 * OnSingleTapListener allows the map rotation angle to be reset to 0 by tapping on the map.
 */
public class MapRotation extends Activity {

  MapView mMapView = null;

  Compass mCompass;

  int mProgress;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // Get a reference to the MapView.
    mMapView = (MapView) findViewById(R.id.map);

    // Set the MapView to allow the user to rotate the map when as part of a pinch gesture.
    mMapView.setAllowRotationByPinch(true);
    
    // Enabled wrap around map.
    mMapView.enableWrapAround(true);

    // Create the Compass custom view, and add it onto the MapView.
    mCompass = new Compass(this, null, mMapView);
    mMapView.addView(mCompass);

    // Set a single tap listener on the MapView.
    mMapView.setOnSingleTapListener(new OnSingleTapListener() {

      private static final long serialVersionUID = 1L;

      @Override
      public void onSingleTap(float x, float y) {

        // When a single tap gesture is received, reset the map to its default rotation angle,
        // where North is shown at the top of the device.
        mMapView.setRotationAngle(0);

        // Also reset the compass angle.
        mCompass.setRotationAngle(0);
      }
    });

  }

  @Override
  protected void onPause() {
    super.onPause();

    // Call MapView.pause to suspend map rendering while the activity is paused, which can save battery usage.
    mMapView.pause();
  }

  @Override
  protected void onResume() {
    super.onResume();

    // Call MapView.unpause to resume map rendering when the activity returns to the foreground.
    mMapView.unpause();
  }

}
/* Copyright 2012 ESRI
 *
 * All rights reserved under the copyright laws of the United States
 * and applicable international laws, treaties, and conventions.
 *
 * You may freely redistribute and use this sample code, with or
 * without modification, provided you include the original copyright
 * notice and use restrictions.
 *
 * See the sample code usage restrictions document for further information.
 *
 */

package com.esri.arcgis.android.samples.maprotation;

import com.esri.android.map.MapView;
import com.esri.android.map.event.OnPinchListener;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

/**
 * This class defines a custom view that draws an image of a compass. The angle of the compass changes when the
 * setRotationAngle method is called. If a MapView is passed to the constructor, an OnPinchListener is set in order to
 * update the compass rotation angle when the pinch gesture is used on the MapView.
 */
public class Compass extends View {

  float mAngle = 0;

  Paint mPaint;

  Bitmap mBitmap;

  Matrix mMatrix;

  MapView mMapView;

  // Called when the Compass view is inflated from XML. In this case, no attributes are initialized from XML. 
  public Compass(Context context, AttributeSet attrs) {
    super(context, attrs);

    // Create a Paint, Matrix and Bitmap that will be re-used together to draw the
    // compass image each time the onDraw method is called.
    mPaint = new Paint();
    mMatrix = new Matrix();

    // Create the bitmap of the compass from a resource.
    mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.compass);
  }

  /** Overloaded constructor that takes a MapView, from which the compass rotation angle will be set. */
  public Compass(Context context, AttributeSet attrs, MapView mapView) {
    this(context, attrs);

    // Save reference to the MapView passed in to this compass.
    mMapView = mapView;
    if (mMapView != null) {

      // Set an OnPinchListener on the map to listen for the pinch gesture which may change the map rotation.
      mMapView.setOnPinchListener(new OnPinchListener() {

        private static final long serialVersionUID = 1L;

        @Override
        public void prePointersUp(float arg0, float arg1, float arg2, float arg3, double arg4) {
        }

        @Override
        public void prePointersMove(float arg0, float arg1, float arg2, float arg3, double arg4) {
        }

        @Override
        public void prePointersDown(float arg0, float arg1, float arg2, float arg3, double arg4) {
        }

        @Override
        public void postPointersUp(float arg0, float arg1, float arg2, float arg3, double arg4) {
        }

        @Override
        public void postPointersMove(float arg0, float arg1, float arg2, float arg3, double arg4) {
          // Update the compass angle from the map rotation angle (the arguments passed in to the method are not
          // relevant in this case).
          setRotationAngle(mMapView.getRotationAngle());
        }

        @Override
        public void postPointersDown(float arg0, float arg1, float arg2, float arg3, double arg4) {
        }
      });
    }
  }

  /** Updates the angle, in degrees, at which the compass is draw within this view. */
  public void setRotationAngle(double angle) {
    // Save the new rotation angle.
    mAngle = (float) angle;

    // Force the compass to re-paint itself.
    postInvalidate();
  }

  /** Draws the compass image at the current angle of rotation on the canvas. */
  @Override
  protected void onDraw(Canvas canvas) {

    // Reset the matrix to default values.
    mMatrix.reset();

    // Pass the current rotation angle to the matrix. The center of rotation is set to be the center of the bitmap.
    mMatrix.postRotate(-this.mAngle, mBitmap.getHeight() / 2, mBitmap.getWidth() / 2);

    // Use the matrix to draw the bitmap image of the compass.
    canvas.drawBitmap(mBitmap, mMatrix, mPaint);
    super.onDraw(canvas);

  }

}
Feedback on this topic?