[android] Revise handling of tracking modes and interactions

with touch gestures.

This fixes issues #6549 and #6567. Also pertinent to #6557.
Additional code has been added to the test app (Activity "User Tracking
Mode") to test.
A potential race condition in the MapboxMap#easeCamera() methods where
a camera change generated by tracking which could have reset the tracking
modes has been eliminated by factoring out a new method
MapboxMap#easeCameraInternal().
This commit is contained in:
clydebarrow
2016-10-04 18:13:02 +11:00
committed by Tobrun
parent 214ec4e96a
commit a4b0e2f30c
9 changed files with 236 additions and 161 deletions

View File

@@ -50,7 +50,6 @@ public class MyLocationDrawableActivity extends AppCompatActivity implements Loc
findViewById(R.id.progress).setVisibility(View.GONE);
MapboxMapOptions mapboxMapOptions = new MapboxMapOptions();
mapboxMapOptions.accessToken(getString(R.string.mapbox_access_token));
mapboxMapOptions.styleUrl(Style.MAPBOX_STREETS);
// configure MyLocationView drawables

View File

@@ -30,17 +30,27 @@ import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.TrackingSettings;
import com.mapbox.mapboxsdk.maps.UiSettings;
import com.mapbox.mapboxsdk.testapp.R;
public class MyLocationTrackingModeActivity extends AppCompatActivity
implements MapboxMap.OnMyLocationChangeListener, AdapterView.OnItemSelectedListener {
implements MapboxMap.OnMyLocationChangeListener, AdapterView.OnItemSelectedListener {
public static final int TRACKING_NONE_INDEX = 0;
public static final int TRACKING_FOLLOW_INDEX = 1;
public static final int BEARING_NONE_INDEX = 0;
public static final int BEARING_GPS_INDEX = 1;
public static final int BEARING_COMPASS_INDEX = 2;
private MapView mapView;
private MapboxMap mapboxMap;
private Spinner locationSpinner;
private Spinner bearingSpinner;
private Location location;
private static final int PERMISSIONS_LOCATION = 0;
private MenuItem dismissLocationTrackingOnGestureItem;
private MenuItem dismissBearingTrackingOnGestureItem;
private MenuItem enableRotateGesturesItem;
private MenuItem enableScrollGesturesItem;
@Override
protected void onCreate(final Bundle savedInstanceState) {
@@ -57,53 +67,66 @@ public class MyLocationTrackingModeActivity extends AppCompatActivity
actionBar.setDisplayShowHomeEnabled(true);
}
locationSpinner = (Spinner) findViewById(R.id.spinner_location);
ArrayAdapter<CharSequence> locationTrackingAdapter = ArrayAdapter.createFromResource(
actionBar.getThemedContext(), R.array.user_tracking_mode, android.R.layout.simple_spinner_item);
locationTrackingAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
locationSpinner.setAdapter(locationTrackingAdapter);
bearingSpinner = (Spinner) findViewById(R.id.spinner_bearing);
ArrayAdapter<CharSequence> bearingTrackingAdapter = ArrayAdapter.createFromResource(
actionBar.getThemedContext(), R.array.user_bearing_mode, android.R.layout.simple_spinner_item);
bearingTrackingAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
bearingSpinner.setAdapter(bearingTrackingAdapter);
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull MapboxMap mapboxMap) {
MyLocationTrackingModeActivity.this.mapboxMap = mapboxMap;
// disable dismissal when a gesture occurs
TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
trackingSettings.setDismissLocationTrackingOnGesture(false);
trackingSettings.setDismissBearingTrackingOnGesture(false);
locationSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
bearingSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
setCheckBoxes();
mapboxMap.setOnMyLocationChangeListener(MyLocationTrackingModeActivity.this);
ArrayAdapter<CharSequence> locationTrackingAdapter = ArrayAdapter.createFromResource(
actionBar.getThemedContext(), R.array.user_tracking_mode, android.R.layout.simple_spinner_item);
locationTrackingAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
locationSpinner = (Spinner) findViewById(R.id.spinner_location);
locationSpinner.setAdapter(locationTrackingAdapter);
locationSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
ArrayAdapter<CharSequence> bearingTrackingAdapter = ArrayAdapter.createFromResource(
actionBar.getThemedContext(), R.array.user_bearing_mode, android.R.layout.simple_spinner_item);
bearingTrackingAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
bearingSpinner = (Spinner) findViewById(R.id.spinner_bearing);
bearingSpinner.setAdapter(bearingTrackingAdapter);
bearingSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
mapboxMap.setOnMyLocationTrackingModeChangeListener(new MapboxMap.OnMyLocationTrackingModeChangeListener() {
@Override
public void onMyLocationTrackingModeChange(@MyLocationTracking.Mode int myLocationTrackingMode) {
if (MyLocationTracking.TRACKING_NONE == myLocationTrackingMode) {
locationSpinner.setOnItemSelectedListener(null);
locationSpinner.setSelection(0);
locationSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
locationSpinner.setOnItemSelectedListener(null);
switch (myLocationTrackingMode) {
case MyLocationTracking.TRACKING_NONE:
locationSpinner.setSelection(TRACKING_NONE_INDEX);
break;
case MyLocationTracking.TRACKING_FOLLOW:
locationSpinner.setSelection(TRACKING_FOLLOW_INDEX);
break;
}
locationSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
}
});
mapboxMap.setOnMyBearingTrackingModeChangeListener(new MapboxMap.OnMyBearingTrackingModeChangeListener() {
@Override
public void onMyBearingTrackingModeChange(@MyBearingTracking.Mode int myBearingTrackingMode) {
if (MyBearingTracking.NONE == myBearingTrackingMode) {
bearingSpinner.setOnItemSelectedListener(null);
bearingSpinner.setSelection(0);
bearingSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
bearingSpinner.setOnItemSelectedListener(null);
switch (myBearingTrackingMode) {
case MyBearingTracking.NONE:
bearingSpinner.setSelection(BEARING_NONE_INDEX);
break;
case MyBearingTracking.GPS:
bearingSpinner.setSelection(BEARING_GPS_INDEX);
break;
case MyBearingTracking.COMPASS:
bearingSpinner.setSelection(BEARING_COMPASS_INDEX);
break;
}
bearingSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
}
});
@@ -118,12 +141,12 @@ public class MyLocationTrackingModeActivity extends AppCompatActivity
public void toggleGps(boolean enableGps) {
if (enableGps) {
if ((ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
|| (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED)) {
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
|| (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED)) {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_LOCATION);
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_LOCATION);
} else {
enableLocation(true);
}
@@ -198,25 +221,25 @@ public class MyLocationTrackingModeActivity extends AppCompatActivity
TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
if (parent.getId() == R.id.spinner_location) {
switch (position) {
case 0:
case TRACKING_NONE_INDEX:
trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_NONE);
break;
case 1:
case TRACKING_FOLLOW_INDEX:
trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
break;
}
} else if (parent.getId() == R.id.spinner_bearing) {
switch (position) {
case 0:
case BEARING_NONE_INDEX:
trackingSettings.setMyBearingTrackingMode(MyBearingTracking.NONE);
break;
case 1:
case BEARING_GPS_INDEX:
trackingSettings.setMyBearingTrackingMode(MyBearingTracking.GPS);
break;
case 2:
case BEARING_COMPASS_INDEX:
trackingSettings.setMyBearingTrackingMode(MyBearingTracking.COMPASS);
break;
}
@@ -261,9 +284,25 @@ public class MyLocationTrackingModeActivity extends AppCompatActivity
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_tracking, menu);
dismissLocationTrackingOnGestureItem = menu.findItem(R.id.action_toggle_dismissible_location);
dismissBearingTrackingOnGestureItem = menu.findItem(R.id.action_toggle_dismissible_bearing);
enableRotateGesturesItem = menu.findItem(R.id.action_toggle_rotate_gesture_enabled);
enableScrollGesturesItem = menu.findItem(R.id.action_toggle_scroll_gesture_enabled);
setCheckBoxes();
return true;
}
private void setCheckBoxes() {
if(mapboxMap != null && dismissBearingTrackingOnGestureItem != null) {
TrackingSettings trackingSettings = mapboxMap.getTrackingSettings();
UiSettings uiSettings = mapboxMap.getUiSettings();
dismissBearingTrackingOnGestureItem.setChecked(trackingSettings.isDismissBearingTrackingOnGesture());
dismissLocationTrackingOnGestureItem.setChecked(trackingSettings.isDismissLocationTrackingOnGesture());
enableRotateGesturesItem.setChecked(uiSettings.isRotateGesturesEnabled());
enableScrollGesturesItem.setChecked(uiSettings.isScrollGesturesEnabled());
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
boolean state;
@@ -271,7 +310,7 @@ public class MyLocationTrackingModeActivity extends AppCompatActivity
case android.R.id.home:
onBackPressed();
return true;
case R.id.action_toggle_dismissible_tracking:
case R.id.action_toggle_dismissible_location:
state = !item.isChecked();
mapboxMap.getTrackingSettings().setDismissLocationTrackingOnGesture(state);
Toast.makeText(this, "Dismiss tracking mode on gesture = " + state, Toast.LENGTH_SHORT).show();
@@ -283,9 +322,20 @@ public class MyLocationTrackingModeActivity extends AppCompatActivity
Toast.makeText(this, "Dismiss bearing mode on gesture = " + state, Toast.LENGTH_SHORT).show();
item.setChecked(state);
return true;
case R.id.action_toggle_rotate_gesture_enabled:
state = !item.isChecked();
mapboxMap.getUiSettings().setRotateGesturesEnabled(state);
Toast.makeText(this, "Rotate gesture enabled = " + state, Toast.LENGTH_SHORT).show();
item.setChecked(state);
return true;
case R.id.action_toggle_scroll_gesture_enabled:
state = !item.isChecked();
mapboxMap.getUiSettings().setScrollGesturesEnabled(state);
Toast.makeText(this, "Scroll gesture enabled = " + state, Toast.LENGTH_SHORT).show();
item.setChecked(state);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}

View File

@@ -4,7 +4,7 @@
<group android:checkableBehavior="all">
<item
android:id="@+id/action_toggle_dismissible_tracking"
android:id="@+id/action_toggle_dismissible_location"
android:checkable="true"
android:checked="false"
android:title="@string/menuitem_title_tracking_mode_dismiss_on_gesture"
@@ -15,6 +15,18 @@
android:checked="false"
android:title="@string/menuitem_title_bearing_mode_dismiss_on_gesture"
app:showAsAction="never" />
<item
android:id="@+id/action_toggle_rotate_gesture_enabled"
android:checkable="true"
android:checked="false"
android:title="@string/menuitem_title_rotate_gesture_enabled"
app:showAsAction="never" />
<item
android:id="@+id/action_toggle_scroll_gesture_enabled"
android:checkable="true"
android:checked="false"
android:title="@string/menuitem_title_scroll_gesture_enabled"
app:showAsAction="never" />
</group>
</menu>

View File

@@ -221,5 +221,7 @@
<string name="action_example">Example action</string>
<string name="action_settings">Settings</string>
<string name="menuitem_title_rotate_gesture_enabled">Enable rotate gestures</string>
<string name="menuitem_title_scroll_gesture_enabled">Enable scroll gestures</string>
</resources>