-
-
Save vaibhav-jani/13f431256fdaef37ce42 to your computer and use it in GitHub Desktop.
Android Google Maps V2 - MapView in XML
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.vaibhavjani.geojsonexample; | |
import android.content.Context; | |
import android.graphics.Point; | |
import android.os.Handler; | |
import android.util.AttributeSet; | |
import android.view.GestureDetector; | |
import android.view.MotionEvent; | |
import android.view.ScaleGestureDetector; | |
import com.google.android.gms.maps.CameraUpdate; | |
import com.google.android.gms.maps.CameraUpdateFactory; | |
import com.google.android.gms.maps.GoogleMap; | |
import com.google.android.gms.maps.GoogleMapOptions; | |
import com.google.android.gms.maps.MapView; | |
import com.google.android.gms.maps.MapsInitializer; | |
import com.google.android.gms.maps.model.LatLng; | |
import com.google.android.gms.maps.model.VisibleRegion; | |
public class RestrictedMapView extends MapView { | |
public static float MAX_ZOOM = 20; | |
public static float MIN_ZOOM = 5; | |
public static float MIN_ZOOM_FOR_FLING = 7; | |
public static double MAX_LONGITUDE = 183.61; | |
public static double MIN_LONGITUDE = 159.31; | |
public static double MAX_LATITUDE = -32.98; | |
public static double MIN_LATITUDE = -53.82; | |
public static double DEF_LATITUDE = -41.78; | |
public static double DEF_LONGITUDE = 173.02; | |
public static float DEF_ZOOM = 7; | |
private Handler mHandler = new Handler(); | |
private Context mContext; | |
private VisibleRegion mLastCorrectRegion = null; | |
private boolean mIsInAnimation = false; | |
public RestrictedMapView(Context c, AttributeSet a, int o) { | |
super(c, a, o); | |
init(c); | |
} | |
public RestrictedMapView(Context c, AttributeSet a) { | |
super(c, a); | |
init(c); | |
} | |
public RestrictedMapView(Context c) { | |
super(c); | |
init(c); | |
} | |
public RestrictedMapView(Context c, GoogleMapOptions o) { | |
super(c, o); | |
init(c); | |
} | |
private GestureDetector mGestureDetector = null; | |
private GestureDetector.SimpleOnGestureListener mGestudeListener = | |
new GestureDetector.SimpleOnGestureListener() { | |
@Override | |
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { | |
if (mIsInAnimation) return false; | |
GoogleMap map = getMap(); | |
LatLng target = map.getCameraPosition().target; | |
Point screenPoint = map.getProjection().toScreenLocation(target); | |
Point newPoint = new Point(screenPoint.x + (int)distanceX, screenPoint.y + (int)distanceY); | |
LatLng mapNewTarget = map.getProjection().fromScreenLocation(newPoint); | |
CameraUpdate update = CameraUpdateFactory.newLatLngZoom( | |
mapNewTarget,map.getCameraPosition().zoom); | |
tryUpdateCamera(update, 0); | |
return true; | |
} | |
@Override | |
public boolean onFling (MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { | |
if (mIsInAnimation) return false; | |
GoogleMap map = getMap(); | |
double zoom = map.getCameraPosition().zoom; | |
if (zoom < MIN_ZOOM_FOR_FLING) | |
return false; | |
int velocity = (int) Math.sqrt(velocityX * velocityX + velocityY * velocityY); | |
if (velocity < 500) return false; | |
double k1 = 0.002d; /*exipemental*/ | |
double k2 = 0.002d;/*exipemental*/ | |
LatLng target = map.getCameraPosition().target; | |
Point screenPoint = map.getProjection().toScreenLocation(target); | |
Point newPoint = new Point(screenPoint.x - (int)(velocityX * k1 * zoom * zoom/*exipemental*/), | |
screenPoint.y - (int)(velocityY * k1 * zoom * zoom/*exipemental*/)); | |
LatLng mapNewTarget = map.getProjection().fromScreenLocation(newPoint); | |
CameraUpdate update = CameraUpdateFactory.newLatLngZoom( | |
mapNewTarget,map.getCameraPosition().zoom); | |
tryUpdateCamera(update, (int)(velocity * k2 * zoom * zoom) /*exipemental*/); | |
return true; | |
} | |
}; | |
private ScaleGestureDetector mScaleGestureDetector = null; | |
private ScaleGestureDetector.SimpleOnScaleGestureListener mScaleGestudeListener = | |
new ScaleGestureDetector.SimpleOnScaleGestureListener() { | |
@Override | |
public boolean onScale (ScaleGestureDetector detector) { | |
if (mIsInAnimation) return false; | |
GoogleMap map = getMap(); | |
double zoom = map.getCameraPosition().zoom; | |
double k = 1d / detector.getScaleFactor(); | |
int x = (int) detector.getFocusX(); | |
int y = (int) detector.getFocusY(); | |
LatLng mapFocus = map.getProjection(). | |
fromScreenLocation(new Point(x, y)); | |
LatLng target = map.getCameraPosition().target; | |
zoom = zoom + Math.log(detector.getScaleFactor()) / Math.log(2d); | |
if (zoom < MIN_ZOOM) | |
if (zoom == MIN_ZOOM) return false; | |
else zoom = MIN_ZOOM; | |
if (zoom > MAX_ZOOM) | |
if (zoom == MAX_ZOOM) return false; | |
else zoom = MAX_ZOOM; | |
double dx = norm(mapFocus.longitude) - norm(target.longitude); | |
double dy = mapFocus.latitude - target.latitude; | |
double dk = 1d - 1d / k; | |
LatLng newTarget = new LatLng(target.latitude - dy * dk, | |
norm(target.longitude) - dx * dk); | |
CameraUpdate update = CameraUpdateFactory.newLatLngZoom(newTarget, (float) zoom); | |
tryUpdateCamera(update, 0); | |
return true; | |
} | |
}; | |
private void tryUpdateCamera(CameraUpdate update, int animateTime) { | |
GoogleMap map = getMap(); | |
final VisibleRegion reg = map.getProjection().getVisibleRegion(); | |
if (animateTime <= 0) { | |
map.moveCamera(update); | |
checkCurrentRegion(reg); | |
} else { | |
mIsInAnimation = true; | |
map.animateCamera(update, animateTime, new GoogleMap.CancelableCallback() { | |
@Override | |
public void onFinish() { | |
mIsInAnimation = false; | |
checkCurrentRegion(reg); | |
} | |
@Override | |
public void onCancel() { | |
mIsInAnimation = false; | |
checkCurrentRegion(reg); | |
} | |
}); | |
} | |
} | |
private void checkCurrentRegion(VisibleRegion oldReg) { | |
GoogleMap map = getMap(); | |
VisibleRegion regNew = map.getProjection().getVisibleRegion(); | |
if (checkBounds(regNew)) { | |
mLastCorrectRegion = regNew; | |
} else { | |
if (mLastCorrectRegion != null) | |
oldReg = mLastCorrectRegion; | |
mIsInAnimation = true; | |
map.animateCamera(CameraUpdateFactory.newLatLngBounds( | |
oldReg.latLngBounds, 0), | |
200, new GoogleMap.CancelableCallback() { | |
@Override | |
public void onFinish() { | |
mIsInAnimation = false; | |
} | |
@Override | |
public void onCancel() { | |
mIsInAnimation = false; | |
} | |
}); | |
} | |
} | |
/** | |
* | |
* | |
* @param lonVal | |
* @return | |
*/ | |
private double norm(double lonVal) { | |
while (lonVal > 360d) lonVal -= 360d; | |
while (lonVal < -360d) lonVal += 360d; | |
if (lonVal < 0) lonVal = 360d + lonVal; | |
return lonVal; | |
} | |
private double denorm(double lonVal) { | |
if (lonVal > 180d) lonVal = -360d + lonVal; | |
return lonVal; | |
} | |
private boolean checkBounds(VisibleRegion reg) { | |
double left = Math.min( | |
Math.min(norm(reg.farLeft.longitude), norm(reg.nearLeft.longitude)), | |
Math.min(norm(reg.farRight.longitude), norm(reg.nearRight.longitude))); | |
double right = Math.max( | |
Math.max(norm(reg.farLeft.longitude), norm(reg.nearLeft.longitude)), | |
Math.max(norm(reg.farRight.longitude), norm(reg.nearRight.longitude))); | |
double top = Math.max( | |
Math.max(reg.farLeft.latitude, reg.nearLeft.latitude), | |
Math.max(reg.farRight.latitude, reg.nearRight.latitude)); | |
double bottom = Math.min( | |
Math.min(reg.farLeft.latitude, reg.nearLeft.latitude), | |
Math.min(reg.farRight.latitude, reg.nearRight.latitude)); | |
boolean limitBounds = left < MIN_LONGITUDE || right > MAX_LONGITUDE || | |
bottom < MIN_LATITUDE || top > MAX_LATITUDE; | |
return !limitBounds; | |
} | |
private void init(Context c) { | |
try { | |
MapsInitializer.initialize(c); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
mContext = c; | |
mHandler.post(new Runnable() { | |
@Override | |
public void run() { | |
GoogleMap map = getMap(); | |
if (map != null) { | |
getMap().getUiSettings().setZoomControlsEnabled(false); | |
map.getUiSettings().setAllGesturesEnabled(false); | |
map.moveCamera(CameraUpdateFactory.newLatLngZoom( | |
new LatLng(DEF_LATITUDE, DEF_LONGITUDE), DEF_ZOOM)); | |
mLastCorrectRegion = map.getProjection().getVisibleRegion(); | |
mGestureDetector = new GestureDetector(mContext, mGestudeListener); | |
mScaleGestureDetector = new ScaleGestureDetector(mContext, mScaleGestudeListener); | |
} else mHandler.post(this); | |
} | |
}); | |
} | |
@Override | |
public boolean onInterceptTouchEvent(MotionEvent event) { | |
if (mGestureDetector != null) mGestureDetector.onTouchEvent(event); | |
if (mScaleGestureDetector != null) mScaleGestureDetector.onTouchEvent(event); | |
return super.onInterceptTouchEvent(event); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:tools="http://schemas.android.com/tools" | |
android:layout_width="fill_parent" | |
android:layout_height="fill_parent" > | |
<com.google.android.gms.maps.MapView android:id="@+id/mapview" | |
android:layout_width="fill_parent" | |
android:layout_height="fill_parent" /> | |
</LinearLayout> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class SomeFragment extends Fragment { | |
MapView mapView; | |
GoogleMap map; | |
@Override | |
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { | |
View v = inflater.inflate(R.layout.some_layout, container, false); | |
// Gets the MapView from the XML layout and creates it | |
mapView = (MapView) v.findViewById(R.id.mapview); | |
mapView.onCreate(savedInstanceState); | |
// Gets to GoogleMap from the MapView and does initialization stuff | |
map = mapView.getMap(); | |
map.getUiSettings().setMyLocationButtonEnabled(false); | |
map.setMyLocationEnabled(true); | |
// Needs to call MapsInitializer before doing any CameraUpdateFactory calls | |
try { | |
MapsInitializer.initialize(this.getActivity()); | |
} catch (GooglePlayServicesNotAvailableException e) { | |
e.printStackTrace(); | |
} | |
// Updates the location and zoom of the MapView | |
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(43.1, -87.9), 10); | |
map.animateCamera(cameraUpdate); | |
return v; | |
} | |
@Override | |
public void onResume() { | |
mapView.onResume(); | |
super.onResume(); | |
} | |
@Override | |
public void onDestroy() { | |
super.onDestroy(); | |
mapView.onDestroy(); | |
} | |
@Override | |
public void onLowMemory() { | |
super.onLowMemory(); | |
mapView.onLowMemory(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |
package="com.example" | |
android:versionCode="1" | |
android:versionName="1.0" > | |
<uses-sdk | |
android:minSdkVersion="8" | |
android:targetSdkVersion="15" /> | |
<uses-permission android:name="android.permission.INTERNET"/> | |
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/> | |
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> | |
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> | |
<uses-feature | |
android:glEsVersion="0x00020000" | |
android:required="true"/> | |
<permission | |
android:name="com.example.permission.MAPS_RECEIVE" | |
android:protectionLevel="signature"/> | |
<uses-permission android:name="com.example.permission.MAPS_RECEIVE"/> | |
<application | |
android:icon="@drawable/ic_launcher" | |
android:label="@string/app_name" | |
android:theme="@style/AppTheme" > | |
<meta-data | |
android:name="com.google.android.maps.v2.API_KEY" | |
android:value="your_key"/> | |
<activity | |
android:name=".HomeActivity" | |
android:label="@string/app_name" > | |
<intent-filter> | |
<action android:name="android.intent.action.MAIN" /> | |
<category android:name="android.intent.category.LAUNCHER" /> | |
</intent-filter> | |
</activity> | |
</application> | |
</manifest> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment