diff --git a/app/src/androidTest/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/PlaceAutocompleteFragmentTest.java b/app/src/androidTest/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/PlaceAutocompleteFragmentTest.java
index 948e627d5..ae9990c52 100644
--- a/app/src/androidTest/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/PlaceAutocompleteFragmentTest.java
+++ b/app/src/androidTest/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/PlaceAutocompleteFragmentTest.java
@@ -4,6 +4,7 @@
import android.graphics.Color;
import android.net.wifi.WifiManager;
import android.support.test.espresso.action.ViewActions;
+import android.support.test.espresso.assertion.ViewAssertions;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
@@ -22,13 +23,14 @@
import static android.support.test.espresso.action.ViewActions.typeText;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.hasBackground;
+import static android.support.test.espresso.matcher.ViewMatchers.hasFocus;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withHint;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
-import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -100,6 +102,36 @@ public void onBackButtonPress_doesInvokeOnCancelCallback() throws Exception {
verify(listener, times(1)).onCancel();
}
+ @Test
+ public void onClearSearchQueryTextButtonPress_doesClearEditText() throws Exception {
+ ClearButtonListener clearButtonListener = mock(ClearButtonListener.class);
+ placeAutocompleteFragment.setOnClearButtonListener(clearButtonListener);
+ onView(withId(R.id.edittext_search)).check(ViewAssertions.matches((withText(""))));
+ }
+
+ @Test
+ public void onClearSearchQueryTextButtonPress_doesInvokeOnCancelCallback() throws Exception {
+ ClearButtonListener clearButtonListener = mock(ClearButtonListener.class);
+ placeAutocompleteFragment.setOnClearButtonListener(clearButtonListener);
+ verify(clearButtonListener, times(1)).onCancel();
+ }
+
+ @Test
+ public void onSearchQueryEditTextPress_doesAddFocusToEditText() throws Exception {
+ QueryFocusListener searchUiHasFocusListener = mock(QueryFocusListener.class);
+ placeAutocompleteFragment.setOnSearchUiHasFocusListener(searchUiHasFocusListener);
+ onView(withId(R.id.edittext_search)).perform(ViewActions.click());
+ onView(withId(R.id.edittext_search)).check(matches(hasFocus()));
+ }
+
+ @Test
+ public void onResultPress_doesRemoveFocus() throws Exception {
+ PlaceSelectionListener listener = mock(PlaceSelectionListener.class);
+ placeAutocompleteFragment.setOnPlaceSelectedListener(listener);
+ onView(withId(R.id.scroll_view_results)).perform(ViewActions.click());
+ onView(withId(R.id.edittext_search)).check(matches(not(hasFocus())));
+ }
+
//
// Offline state test
//
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4b893a088..3a72cd5a5 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -32,6 +32,18 @@
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.FeatureOverviewActivity"/>
+
+
+
+
+ reverseGeocodingSwitch.text = if (checked)
+ getString(R.string.reverse_geocoding_enabled)
+ else getString(R.string.reverse_geocoding_disabled)
+ }
+
+ includeSearchUiSwitch.text = getString(R.string.search_ui_enabled)
+ includeSearchUiSwitch.setOnCheckedChangeListener { compoundButton, checked ->
+ includeSearchUiSwitch.text = if (checked)
+ getString(R.string.search_ui_enabled)
+ else getString(R.string.search_ui_disabled)
+ }
+
+ userLocationSwitch.text = getString(R.string.user_location_button_enabled)
+ userLocationSwitch.setOnCheckedChangeListener { compoundButton, checked ->
+ userLocationSwitch.text = if (checked)
+ getString(R.string.user_location_button_enabled)
+ else getString(R.string.user_location_button_disabled)
+ }
+
+ fabLocationPicker.setOnClickListener { _ ->
+ Mapbox.getAccessToken()?.let {
+ startActivityForResult(
+ PlacePicker.IntentBuilder()
+ .accessToken(it)
+ .placeOptions(PlacePickerOptions.builder()
+ .includeReverseGeocode(reverseGeocodingSwitch.isChecked)
+ .includeSearch(includeSearchUiSwitch.isChecked)
+ .includeDeviceLocationButton(userLocationSwitch.isChecked)
+ .statingCameraPosition(CameraPosition.Builder()
+ .target(LatLng(40.7544, -73.9862))
+ .zoom(16.0)
+ .build())
+ .build())
+ .build(this), REQUEST_CODE)
+ }
+ }
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {
+ if (reverseGeocodingSwitch.isChecked) {
+ val carmenFeature = PlacePicker.getPlace(data)
+ Toast.makeText(this, carmenFeature?.placeName(), Toast.LENGTH_LONG).show()
+ } else {
+ val cameraPosition = PlacePicker.getLastCameraPosition(data)
+ Toast.makeText(this, cameraPosition.target.toString(), Toast.LENGTH_LONG).show()
+ }
+ }
+ }
+
+ companion object {
+ private val REQUEST_CODE = 5678
+ }
+}
diff --git a/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/places/PickerLauncherActivity.kt b/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/places/PickerLauncherActivity.kt
index 51ec2d51a..805521961 100644
--- a/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/places/PickerLauncherActivity.kt
+++ b/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/places/PickerLauncherActivity.kt
@@ -25,7 +25,7 @@ class PickerLauncherActivity : AppCompatActivity() {
else getString(R.string.reverse_geocoding_disabled)
}
- userLocationSwitch.text = getString(R.string.user_location_button_disabled)
+ userLocationSwitch.text = getString(R.string.user_location_button_enabled)
userLocationSwitch.setOnCheckedChangeListener { compoundButton, checked ->
userLocationSwitch.text = if (checked)
getString(R.string.user_location_button_enabled)
diff --git a/app/src/main/res/layout/activity_picker_autocomplete_combo_launcher.xml b/app/src/main/res/layout/activity_picker_autocomplete_combo_launcher.xml
new file mode 100644
index 000000000..42e801c87
--- /dev/null
+++ b/app/src/main/res/layout/activity_picker_autocomplete_combo_launcher.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_picker_launcher.xml b/app/src/main/res/layout/activity_picker_launcher.xml
index e53dde63d..f9be9333b 100644
--- a/app/src/main/res/layout/activity_picker_launcher.xml
+++ b/app/src/main/res/layout/activity_picker_launcher.xml
@@ -33,6 +33,7 @@
app:layout_constraintBottom_toTopOf="@+id/reverseGeocodingSwitch"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
+ android:checked="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 51893ab59..37b90241d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -19,6 +19,7 @@
Building Plugin
Places Autocomplete
Places Autocomplete Fragment
+ Autocomplete and Place Picker Combination
Create region
List regions
Place picker
@@ -42,6 +43,7 @@
Add 3D Building layer to a Mapbox map.
Launch the autocomplete activity.
Launch the autocomplete fragment inside an activity
+ Show the Place Picker and autocomplete UI together.
Use a form to create an offline region.
List all offline regions.
Launch the place picker activity and receive result
@@ -62,10 +64,13 @@
Example shows how to launch the Place Picker using the Floating action button and receiving a result in onActivityResult.
+ PickerAutocompleteCombinedActivity: Example shows how to launch the Place Picker combined with the autocomplete geocoding search UI.
Reverse geocoding enabled
Reverse geocoding disabled
User location button enabled
User location button disabled
+ Search autocomplete UI enabled
+ Search autocomplete UI disabled
Min zoom: %1$d
diff --git a/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/BackButtonListener.java b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/BackButtonListener.java
new file mode 100644
index 000000000..11403d633
--- /dev/null
+++ b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/BackButtonListener.java
@@ -0,0 +1,11 @@
+package com.mapbox.mapboxsdk.plugins.places.autocomplete.ui;
+
+/**
+ * This click interface notifies when the back arrow button is clicked
+ * in the {@link SearchView}.
+ */
+public interface BackButtonListener {
+
+ void onBackButtonPress();
+
+}
diff --git a/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/ClearButtonListener.java b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/ClearButtonListener.java
new file mode 100644
index 000000000..55bc97bfe
--- /dev/null
+++ b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/ClearButtonListener.java
@@ -0,0 +1,13 @@
+package com.mapbox.mapboxsdk.plugins.places.autocomplete.ui;
+
+/**
+ * This click interface notifies when the clear button
+ * is clickedin the {@link SearchView} to clear the query text in the EditText.
+ */
+public interface ClearButtonListener {
+
+ void onClearButtonPress();
+
+ void onCancel();
+
+}
\ No newline at end of file
diff --git a/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/PlaceAutocompleteFragment.java b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/PlaceAutocompleteFragment.java
index af3edaa2e..7870f157c 100644
--- a/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/PlaceAutocompleteFragment.java
+++ b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/PlaceAutocompleteFragment.java
@@ -3,15 +3,21 @@
import android.app.Activity;
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.graphics.drawable.VectorDrawableCompat;
import android.support.v4.app.Fragment;
+import android.support.v4.graphics.drawable.DrawableCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.widget.EditText;
+import android.widget.ImageView;
import android.widget.ScrollView;
import android.widget.Toast;
@@ -24,18 +30,23 @@
import com.mapbox.mapboxsdk.plugins.places.autocomplete.viewmodel.PlaceAutocompleteViewModel;
import com.mapbox.mapboxsdk.plugins.places.common.PlaceConstants;
import com.mapbox.mapboxsdk.plugins.places.common.utils.KeyboardUtils;
+import com.mapbox.mapboxsdk.plugins.places.picker.ui.PlacePickerActivity;
import java.util.List;
import timber.log.Timber;
public class PlaceAutocompleteFragment extends Fragment implements ResultClickCallback,
- SearchView.QueryListener, SearchView.BackButtonListener,
+ QueryListener, QueryFocusListener, BackButtonListener, ClearButtonListener,
ViewTreeObserver.OnScrollChangedListener {
public static final String TAG = "PlaceAutocompleteFragment";
private PlaceSelectionListener placeSelectionListener;
+ private QueryFocusListener queryFocusListener;
+ private QueryListener searchQueryListener;
+ private ClearButtonListener clearButtonListener;
+ private SearchHistoryCountListener searchHistoryCountListener;
private PlaceAutocompleteViewModel viewModel;
private ResultView searchHistoryView;
private ResultView searchResultView;
@@ -48,7 +59,9 @@ public class PlaceAutocompleteFragment extends Fragment implements ResultClickCa
private String accessToken;
private Integer historyCount;
private View rootView;
+ private Activity context;
private int mode;
+ private EditText searchEditText;
public static PlaceAutocompleteFragment newInstance(@NonNull String accessToken) {
PlaceAutocompleteFragment fragment = new PlaceAutocompleteFragment();
@@ -81,6 +94,7 @@ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
}
mode = placeOptions.viewMode();
+ placeOptions.toolbarColor();
rootView = inflater.inflate(
mode == PlaceOptions.MODE_CARDS ? R.layout.mapbox_fragment_autocomplete_card
: R.layout.mapbox_fragment_autocomplete_full,
@@ -96,6 +110,8 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
resultScrollView.getViewTreeObserver().addOnScrollChangedListener(this);
styleView();
+ KeyboardUtils.showKeyboard(context.getWindow().getDecorView());
+ searchEditText.requestFocus();
}
private void styleView() {
@@ -105,19 +121,30 @@ private void styleView() {
View toolbar = rootView.findViewById(R.id.toolbar);
if (toolbar != null) {
toolbar.setBackgroundColor(placeOptions.toolbarColor());
+ if (placeOptions.toolbarColor() != Color.WHITE) {
+ swapUiColor();
+ }
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- Activity context = (Activity) rootView.getContext();
+ context = (Activity) rootView.getContext();
context.getWindow().setStatusBarColor(placeOptions.statusbarColor());
}
searchView = rootView.findViewById(R.id.searchView);
searchView.setHint(placeOptions.hint() == null
? getString(R.string.mapbox_plugins_autocomplete_search_hint) : placeOptions.hint());
+
+ searchEditText = searchView.findViewById(R.id.edittext_search);
}
}
+ private void swapUiColor() {
+ changeBackButtonColorToWhite();
+ changeClearSearchTextButtonColorToWhite();
+ changeSearchTextColorToWhite();
+ }
+
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
@@ -153,6 +180,9 @@ public void onScrollChanged() {
@Override
public void onQueryChange(CharSequence charSequence) {
viewModel.onQueryChange(charSequence);
+ if (searchQueryListener != null) {
+ searchQueryListener.onQueryChange(charSequence);
+ }
if (charSequence.length() <= 0) {
searchResultView.getResultsList().clear();
searchResultView.setVisibility(
@@ -162,27 +192,132 @@ public void onQueryChange(CharSequence charSequence) {
}
}
+ @Override
+ public void onClearButtonPress() {
+ if (clearButtonListener != null) {
+ clearButtonListener.onClearButtonPress();
+ }
+ }
+
@Override
public void onClick(CarmenFeature carmenFeature) {
+ searchEditText.clearFocus();
viewModel.saveCarmenFeatureToDatabase(carmenFeature);
if (placeSelectionListener != null) {
placeSelectionListener.onPlaceSelected(carmenFeature);
}
}
+ private void changeBackButtonColorToWhite() {
+ ImageView clearButtonImageView = searchView.findViewById(R.id.button_search_clear);
+ Drawable clearButtonVectorDrawable = VectorDrawableCompat.create(
+ getResources(),
+ R.drawable.mapbox_ic_clear,
+ null);
+ Drawable clearButtonDrawable = DrawableCompat.wrap(clearButtonVectorDrawable);
+ DrawableCompat.setTint(clearButtonDrawable.mutate(), Color.WHITE);
+ clearButtonImageView.setImageDrawable(clearButtonDrawable);
+ }
+
+ private void changeClearSearchTextButtonColorToWhite() {
+ ImageView backButtonImageView = searchView.findViewById(R.id.button_search_back);
+ Drawable backButtonVectorDrawable = VectorDrawableCompat.create(
+ getResources(),
+ R.drawable.mapbox_ic_arrow_back,
+ null);
+ Drawable backButtonDrawable = DrawableCompat.wrap(backButtonVectorDrawable);
+ DrawableCompat.setTint(backButtonDrawable.mutate(), Color.WHITE);
+ backButtonImageView.setImageDrawable(backButtonDrawable);
+ }
+
+ private void changeSearchTextColorToWhite() {
+ EditText searchEditText = searchView.findViewById(R.id.edittext_search);
+ if (searchEditText != null) {
+ searchEditText.setTextColor(Color.WHITE);
+ searchEditText.setHintTextColor(Color.WHITE);
+ }
+ }
+
@Override
public void onDestroyView() {
if (resultScrollView != null) {
resultScrollView.getViewTreeObserver().removeOnScrollChangedListener(this);
}
- placeSelectionListener = null;
+ if (placeSelectionListener != null) {
+ placeSelectionListener = null;
+ }
+ if (placeSelectionListener != null) {
+ placeSelectionListener = null;
+ }
+ if (searchQueryListener != null) {
+ searchQueryListener = null;
+ }
+ if (clearButtonListener != null) {
+ clearButtonListener = null;
+ }
+ if (searchHistoryCountListener != null) {
+ searchHistoryCountListener = null;
+ }
super.onDestroyView();
}
@Override
public void onBackButtonPress() {
- if (placeSelectionListener != null) {
- placeSelectionListener.onCancel();
+ if (searchEditText.hasFocus()) {
+ // Remove focus from the search UI EditText
+ searchEditText.clearFocus();
+
+ // Hide the keyboard
+ KeyboardUtils.hideKeyboard(rootView);
+
+ // Shrink the results CardView if using PlacePickerActivity and search UI is enabled
+ if (context instanceof PlacePickerActivity) {
+ if (!((PlacePickerActivity) context).resultsCardViewListIsCollapsed) {
+ ((PlacePickerActivity) context).adjustResultsCardViewHeight(false);
+ }
+ }
+ } else {
+ if (placeSelectionListener != null) {
+ placeSelectionListener.onCancel();
+ }
+ if (queryFocusListener != null) {
+ queryFocusListener.onCancel();
+ }
+ if (searchQueryListener != null) {
+ searchQueryListener.onCancel();
+ }
+ if (clearButtonListener != null) {
+ clearButtonListener.onCancel();
+ }
+ if (searchHistoryCountListener != null) {
+ searchHistoryCountListener.onCancel();
+ }
+ }
+ }
+
+ @Override
+ public void onCancel() {
+ if (queryFocusListener != null) {
+ queryFocusListener.onCancel();
+ }
+ if (searchQueryListener != null) {
+ searchQueryListener.onCancel();
+ }
+ if (queryFocusListener != null) {
+ queryFocusListener.onCancel();
+ }
+ if (searchQueryListener != null) {
+ searchQueryListener.onCancel();
+ }
+ if (clearButtonListener != null) {
+ clearButtonListener.onCancel();
+ }
+ }
+
+ @Override
+ public void onSearchViewEditTextHasFocus() {
+ if (queryFocusListener != null) {
+ queryFocusListener.onSearchViewEditTextHasFocus();
}
}
@@ -190,12 +325,30 @@ public void setOnPlaceSelectedListener(PlaceSelectionListener listener) {
placeSelectionListener = listener;
}
+ public void setOnSearchUiHasFocusListener(QueryFocusListener listener) {
+ queryFocusListener = listener;
+ }
+
+ public void setOnSearchQueryListener(QueryListener listener) {
+ searchQueryListener = listener;
+ }
+
+ public void setOnClearButtonListener(ClearButtonListener listener) {
+ clearButtonListener = listener;
+ }
+
+ public void setOnHistoryCountListener(SearchHistoryCountListener listener) {
+ searchHistoryCountListener = listener;
+ }
+
private void bindClickListeners() {
searchHistoryView.setOnItemClickListener(this);
searchResultView.setOnItemClickListener(this);
starredView.setOnItemClickListener(this);
searchView.setBackButtonListener(this);
+ searchView.setClearButtonListener(this);
searchView.setQueryListener(this);
+ searchView.setQueryFocusListener(this);
}
private void bindViews() {
@@ -212,6 +365,9 @@ private void bindViews() {
void updateSearchHistoryView(@Nullable List searchHistoryEntities) {
searchHistoryView.getResultsList().clear();
if (searchHistoryEntities != null) {
+ if (searchHistoryCountListener != null) {
+ searchHistoryCountListener.onNewHistoryCount(searchHistoryEntities.size());
+ }
if (placeOptions.historyCount() != null) {
historyCount = placeOptions.historyCount();
for (int x = 0; x < historyCount; x++) {
@@ -288,4 +444,11 @@ public String getAccessToken() {
public Integer getHistoryCount() {
return historyCount;
}
+
+ public interface SearchHistoryCountListener {
+
+ void onNewHistoryCount(int count);
+
+ void onCancel();
+ }
}
diff --git a/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/QueryFocusListener.java b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/QueryFocusListener.java
new file mode 100644
index 000000000..69167ac2a
--- /dev/null
+++ b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/QueryFocusListener.java
@@ -0,0 +1,15 @@
+package com.mapbox.mapboxsdk.plugins.places.autocomplete.ui;
+
+/**
+ * This interface is used to notify when the search UI EditText is focused on
+ * in the {@link SearchView}. This is helpful for adjusting the cardview height in
+ * {@link com.mapbox.mapboxsdk.plugins.places.picker.ui.PlacePickerActivity}
+ * as a user interacts with the search UI in the toolbar.
+ */
+public interface QueryFocusListener {
+
+ void onSearchViewEditTextHasFocus();
+
+ void onCancel();
+
+}
\ No newline at end of file
diff --git a/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/QueryListener.java b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/QueryListener.java
new file mode 100644
index 000000000..0f1cca0de
--- /dev/null
+++ b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/QueryListener.java
@@ -0,0 +1,13 @@
+package com.mapbox.mapboxsdk.plugins.places.autocomplete.ui;
+
+/**
+ * This click interface notifies when the search query text in the
+ * {@link SearchView} EditText changes.
+ */
+public interface QueryListener {
+
+ void onQueryChange(CharSequence charSequence);
+
+ void onCancel();
+
+}
diff --git a/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/SearchView.java b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/SearchView.java
index 72f2772bb..5b9cc68d9 100644
--- a/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/SearchView.java
+++ b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/autocomplete/ui/SearchView.java
@@ -19,17 +19,21 @@
import com.mapbox.mapboxsdk.places.R;
public class SearchView extends LinearLayout implements ImageButton.OnClickListener, TextWatcher,
- LifecycleObserver {
+ LifecycleObserver, View.OnFocusChangeListener {
@Nullable
private BackButtonListener backButtonListener;
@Nullable
+ private ClearButtonListener clearButtonListener;
+ @Nullable
private QueryListener queryListener;
+ @Nullable
+ private QueryFocusListener focusListener;
private final ImageView backButton;
private final ImageView clearButton;
private final EditText searchEditText;
-
+
public SearchView(@NonNull Context context) {
this(context, null);
}
@@ -51,6 +55,7 @@ private void initialize() {
backButton.setOnClickListener(this);
clearButton.setOnClickListener(this);
searchEditText.addTextChangedListener(this);
+ searchEditText.setOnFocusChangeListener(this);
((LifecycleOwner) getContext()).getLifecycle().addObserver(this);
}
@@ -62,6 +67,18 @@ public void onClick(View view) {
}
} else {
searchEditText.getText().clear();
+ if (clearButtonListener != null) {
+ clearButtonListener.onClearButtonPress();
+ }
+ }
+ }
+
+ @Override
+ public void onFocusChange(View view, boolean hasFocus) {
+ if (view.getId() == searchEditText.getId()) {
+ if (focusListener != null) {
+ focusListener.onSearchViewEditTextHasFocus();
+ }
}
}
@@ -69,6 +86,8 @@ public void onClick(View view) {
public void onDestroy() {
backButtonListener = null;
queryListener = null;
+ focusListener = null;
+ clearButtonListener = null;
}
public void setHint(String hint) {
@@ -76,7 +95,7 @@ public void setHint(String hint) {
}
@Override
- public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+ public void onTextChanged(CharSequence charSequence, int start, int count, int after) {
if (queryListener != null) {
queryListener.onQueryChange(charSequence);
}
@@ -84,7 +103,7 @@ public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
- public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+ public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
// Not used
}
@@ -97,15 +116,15 @@ public void setBackButtonListener(@Nullable BackButtonListener backButtonListene
this.backButtonListener = backButtonListener;
}
- public void setQueryListener(@Nullable QueryListener queryListener) {
- this.queryListener = queryListener;
+ public void setClearButtonListener(@Nullable ClearButtonListener clearButtonListener) {
+ this.clearButtonListener = clearButtonListener;
}
- interface QueryListener {
- void onQueryChange(CharSequence charSequence);
+ public void setQueryListener(@Nullable QueryListener queryListener) {
+ this.queryListener = queryListener;
}
- interface BackButtonListener {
- void onBackButtonPress();
+ public void setQueryFocusListener(@Nullable QueryFocusListener focusListener) {
+ this.focusListener = focusListener;
}
}
\ No newline at end of file
diff --git a/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/common/model/BasePlaceOptions.java b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/common/model/BasePlaceOptions.java
index 56d6c7128..4f9f4f692 100644
--- a/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/common/model/BasePlaceOptions.java
+++ b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/common/model/BasePlaceOptions.java
@@ -16,4 +16,6 @@ public interface BasePlaceOptions {
Integer toolbarColor();
+ Integer statusBarColor();
+
}
\ No newline at end of file
diff --git a/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/picker/model/PlacePickerOptions.java b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/picker/model/PlacePickerOptions.java
index 0090ac2bc..a5a256212 100644
--- a/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/picker/model/PlacePickerOptions.java
+++ b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/picker/model/PlacePickerOptions.java
@@ -37,10 +37,20 @@ public abstract class PlacePickerOptions implements BasePlaceOptions, Parcelable
public abstract boolean includeDeviceLocationButton();
+ public abstract boolean includeSearch();
+
+ @Nullable
+ @Override
+ public abstract Integer statusBarColor();
+
+ @Nullable
+ public abstract String mapStyle();
+
public static Builder builder() {
return new AutoValue_PlacePickerOptions.Builder()
.includeReverseGeocode(true)
- .includeDeviceLocationButton(false);
+ .includeDeviceLocationButton(false)
+ .includeSearch(false);
}
@AutoValue.Builder
@@ -66,7 +76,7 @@ public Builder geocodingTypes(@NonNull @GeocodingTypeCriteria String... geocodin
* geocoding information associated with coordinates at the center of the map. A new
* geocoding call is made every time the map is moved when true is passed through
* includeReverseGeocode().
- *
+
* @param includeReverseGeocode whether or not to make a reverse geocoding call to
* retrieve and display information associated with
* the picked location's coordinates. Defaults to true.
@@ -87,6 +97,33 @@ public Builder geocodingTypes(@NonNull @GeocodingTypeCriteria String... geocodin
*/
public abstract Builder includeDeviceLocationButton(boolean includeDeviceLocationButton);
+ /**
+ * @param includeSearch whether or not to include autocomplete geocoding search
+ * field with the Place Picker UI. Defaults to false.
+ *
+ * @return this builder instance for chaining options together
+ */
+ public abstract Builder includeSearch(boolean includeSearch);
+
+ /**
+ * Set the {@link com.mapbox.mapboxsdk.plugins.places.picker.ui.PlacePickerActivity}'s layout
+ * status bar color. Defaults to the app theme's primary color.
+ *
+ * @param statusBarColor the views status bar color as a ColorInt
+ * @return this builder instance for chaining options together
+ */
+ public abstract Builder statusBarColor(@ColorInt Integer statusBarColor);
+
+ /**
+ * Set the {@link com.mapbox.mapboxsdk.plugins.places.picker.ui.PlacePickerActivity}'s
+ * map style. Defaults to {@link com.mapbox.mapboxsdk.maps.Style#MAPBOX_STREETS} if
+ * this option isn't used when building this {@link PlacePickerOptions} class.
+ *
+ * @param customMapStyleUrl a map style URL to use in the Place Picker.
+ * @return this builder instance for chaining options together
+ */
+ public abstract Builder mapStyle(String customMapStyleUrl);
+
public abstract PlacePickerOptions build();
}
}
diff --git a/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/picker/ui/PlacePickerActivity.java b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/picker/ui/PlacePickerActivity.java
index 5c5f2b03c..331fcfa2f 100644
--- a/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/picker/ui/PlacePickerActivity.java
+++ b/plugin-places/src/main/java/com/mapbox/mapboxsdk/plugins/places/picker/ui/PlacePickerActivity.java
@@ -2,20 +2,33 @@
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
+import android.content.Context;
import android.content.Intent;
+import android.content.res.TypedArray;
import android.location.Location;
+import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.constraint.ConstraintLayout;
+import android.support.design.widget.AppBarLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
+import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.CardView;
+import android.transition.ChangeBounds;
+import android.transition.TransitionManager;
+import android.transition.TransitionSet;
+import android.util.TypedValue;
import android.view.View;
+import android.view.ViewGroup;
import android.view.Window;
import android.view.animation.OvershootInterpolator;
+import android.widget.FrameLayout;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.Toast;
import com.google.gson.JsonObject;
@@ -23,6 +36,7 @@
import com.mapbox.android.core.permissions.PermissionsManager;
import com.mapbox.api.geocoding.v5.models.CarmenFeature;
import com.mapbox.geojson.Point;
+import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
@@ -35,8 +49,15 @@
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.places.R;
+import com.mapbox.mapboxsdk.plugins.places.autocomplete.model.PlaceOptions;
+import com.mapbox.mapboxsdk.plugins.places.autocomplete.ui.ClearButtonListener;
+import com.mapbox.mapboxsdk.plugins.places.autocomplete.ui.PlaceAutocompleteFragment;
+import com.mapbox.mapboxsdk.plugins.places.autocomplete.ui.PlaceSelectionListener;
+import com.mapbox.mapboxsdk.plugins.places.autocomplete.ui.QueryFocusListener;
+import com.mapbox.mapboxsdk.plugins.places.autocomplete.ui.QueryListener;
import com.mapbox.mapboxsdk.plugins.places.common.PlaceConstants;
import com.mapbox.mapboxsdk.plugins.places.common.utils.ColorUtils;
+import com.mapbox.mapboxsdk.plugins.places.common.utils.KeyboardUtils;
import com.mapbox.mapboxsdk.plugins.places.picker.PlacePicker;
import com.mapbox.mapboxsdk.plugins.places.picker.PlacePicker.IntentBuilder;
import com.mapbox.mapboxsdk.plugins.places.picker.model.PlacePickerOptions;
@@ -56,12 +77,19 @@
* @since 0.2.0
*/
public class PlacePickerActivity extends AppCompatActivity implements OnMapReadyCallback,
- MapboxMap.OnCameraMoveStartedListener, MapboxMap.OnCameraIdleListener, Observer,
+ MapboxMap.OnCameraMoveStartedListener, MapboxMap.OnMapClickListener,
+ MapboxMap.OnCameraIdleListener, Observer,
PermissionsListener {
+ public int COLLAPSED_SEARCH_CARDVIEW_HEIGHT;
+ public boolean includeReverseGeocode;
+ public boolean includeDeviceLocationButton;
+ public Boolean resultsCardViewListIsCollapsed = true;
+ private final int EXPANDED_SEARCH_CARDVIEW_HEIGHT = 555;
+ private final int SPACE_BETWEEN_RESULTS_LIST_AND_COMPASS = 3;
private PermissionsManager permissionsManager;
- CurrentPlaceSelectionBottomSheet bottomSheet;
- CarmenFeature carmenFeature;
+ private CurrentPlaceSelectionBottomSheet bottomSheet;
+ private CarmenFeature carmenFeature;
private PlacePickerViewModel viewModel;
private PlacePickerOptions options;
private ImageView markerImage;
@@ -69,7 +97,12 @@ public class PlacePickerActivity extends AppCompatActivity implements OnMapReady
private String accessToken;
private MapView mapView;
private FloatingActionButton userLocationButton;
- private boolean includeReverseGeocode;
+ private CardView searchCardView;
+ private CardView searchResultsCardView;
+ private int searchHistoryCount;
+ private boolean includeSearch;
+ private Integer customToolbarColor;
+ private String customMapStyle;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
@@ -83,12 +116,19 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
if (actionBar != null) {
actionBar.hide();
}
+
+ COLLAPSED_SEARCH_CARDVIEW_HEIGHT = getToolBarHeight();
+
setContentView(R.layout.mapbox_activity_place_picker);
if (savedInstanceState == null) {
accessToken = getIntent().getStringExtra(PlaceConstants.ACCESS_TOKEN);
options = getIntent().getParcelableExtra(PlaceConstants.PLACE_OPTIONS);
includeReverseGeocode = options.includeReverseGeocode();
+ includeDeviceLocationButton = options.includeDeviceLocationButton();
+ includeSearch = options.includeSearch();
+ customMapStyle = options.mapStyle();
+ customToolbarColor = options.toolbarColor();
}
// Initialize the view model.
@@ -96,10 +136,14 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
viewModel.getResults().observe(this, this);
bindViews();
- addBackButtonListener();
+ if (includeSearch) {
+ AppBarLayout appBarLayout = findViewById(R.id.place_picker_app_bar_layout);
+ appBarLayout.setVisibility(View.GONE);
+ } else {
+ addBackButtonListener();
+ setToolbarColor();
+ }
addPlaceSelectedButton();
- customizeViews();
-
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(this);
}
@@ -124,38 +168,187 @@ private void bindViews() {
private void bindListeners() {
PlacePickerActivity.this.mapboxMap.addOnCameraMoveStartedListener(PlacePickerActivity.this);
PlacePickerActivity.this.mapboxMap.addOnCameraIdleListener(PlacePickerActivity.this);
+ searchResultsCardView = findViewById(R.id.optional_search_autocomplete_cardview);
}
- private void customizeViews() {
+ private void setToolbarColor() {
ConstraintLayout toolbar = findViewById(R.id.place_picker_toolbar);
- if (options != null && options.toolbarColor() != null) {
- toolbar.setBackgroundColor(options.toolbarColor());
- } else {
- int color = ColorUtils.getMaterialColor(this, R.attr.colorPrimary);
- toolbar.setBackgroundColor(color);
- }
+ toolbar.setBackgroundColor(customToolbarColor != null
+ ? customToolbarColor : ColorUtils.getMaterialColor(
+ this, R.attr.colorPrimary));
}
@Override
public void onMapReady(final MapboxMap mapboxMap) {
this.mapboxMap = mapboxMap;
- mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {
- @Override
- public void onStyleLoaded(@NonNull Style style) {
- adjustCameraBasedOnOptions();
- if (includeReverseGeocode) {
- // Initialize with the marker's current coordinates.
- makeReverseGeocodingSearch();
- }
- bindListeners();
+ mapboxMap.setStyle(new Style.Builder().fromUri(customMapStyle != null
+ ? customMapStyle : Style.MAPBOX_STREETS), new Style.OnStyleLoaded() {
+ @Override
+ public void onStyleLoaded(@NonNull Style style) {
+ adjustCameraBasedOnOptions();
+ if (includeReverseGeocode) {
+ // Initialize with the marker's current coordinates.
+ makeReverseGeocodingSearch();
+ if (includeDeviceLocationButton) {
+ adjustBottomMarginOfFabLinearLayout(135);
+ } else {
+ adjustBottomMarginOfFabLinearLayout(7);
+ }
+ }
+
+ bindListeners();
+
+ if (options != null && includeDeviceLocationButton) {
+ enableLocationComponent(style);
+ addUserLocationButton();
+ } else {
+ userLocationButton.hide();
+ }
+
+ if (options != null) {
+ if (options.startingBounds() != null) {
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(options.startingBounds(), 0));
+ } else if (options.statingCameraPosition() != null) {
+ mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(options.statingCameraPosition()));
+ }
+
+ if (includeSearch) {
+ searchCardView = findViewById(R.id.optional_search_autocomplete_cardview);
+ searchCardView.setVisibility(View.VISIBLE);
+
+ adjustMapCompassTopPadding(false);
+
+ PlaceAutocompleteFragment autocompleteFragment = PlaceAutocompleteFragment.newInstance(
+ Mapbox.getAccessToken(), initPlaceOptions());
+
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ transaction
+ .add(R.id.optional_search_autocomplete_cardview_fragment_container,
+ autocompleteFragment, PlaceAutocompleteFragment.TAG)
+ .commit();
+
+ autocompleteFragment.setOnClearButtonListener(new ClearButtonListener() {
+ @Override
+ public void onClearButtonPress() {
+ adjustResultsCardViewHeight(false);
+ }
+
+ @Override
+ public void onCancel() {
+ finish();
+ }
+ });
+
+ // Update the search history count to determine whether the search UI should
+ // be expanded when the EditText is focused on.
+ autocompleteFragment.setOnHistoryCountListener(
+ new PlaceAutocompleteFragment.SearchHistoryCountListener() {
+ @Override
+ public void onNewHistoryCount(int count) {
+ searchHistoryCount = count;
+ }
+
+ @Override
+ public void onCancel() {
+ finish();
+ }
+ });
+
+ // Set up what should happen when the search UI EditText is focused on
+ autocompleteFragment.setOnSearchUiHasFocusListener(new QueryFocusListener() {
+ @Override
+ public void onSearchViewEditTextHasFocus() {
+ if (searchHistoryCount > 0) {
+ adjustResultsCardViewHeight(true);
+ }
+ }
+
+ @Override
+ public void onCancel() {
+ finish();
+ }
+ });
+
+ // Expand the search UI cardview height when typing happens in the EditText.
+ autocompleteFragment.setOnSearchQueryListener(new QueryListener() {
+ @Override
+ public void onQueryChange(CharSequence charSequence) {
+ // charSequence not needed here in this activity. The cardview height
+ // will adjust once text query change has changed.
+ adjustResultsCardViewHeight(true);
+ }
+
+ @Override
+ public void onCancel() {
+ finish();
+ }
+ });
+
+ // Expand the search UI cardview height and move the map when a place is selected.
+ autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
+ @Override
+ public void onPlaceSelected(CarmenFeature carmenFeature) {
+ PlacePickerActivity.this.carmenFeature = carmenFeature;
+
+ // Adjust the height of the cardview that has the list of search results
+ adjustResultsCardViewHeight(false);
+
+ // Hide the keyboard once a place has been selected
+ KeyboardUtils.hideKeyboard(getWindow().getDecorView());
+
+ // Move camera to selected location
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
+ new LatLng(carmenFeature.center().latitude(),
+ carmenFeature.center().longitude()), mapboxMap.getCameraPosition().zoom));
+ }
+
+ @Override
+ public void onCancel() {
+ finish();
+ }
+ });
+ }
+ }
+
+ PlacePickerActivity.this.mapboxMap.addOnMapClickListener(PlacePickerActivity.this);
+ PlacePickerActivity.this.mapboxMap.addOnCameraMoveStartedListener(PlacePickerActivity.this);
+ PlacePickerActivity.this.mapboxMap.addOnCameraIdleListener(PlacePickerActivity.this);
+ }
+ });
+ }
- if (options != null && options.includeDeviceLocationButton()) {
- enableLocationComponent(style);
- } else {
- userLocationButton.hide();
- }
- }
- });
+ private void adjustBottomMarginOfFabLinearLayout(int newBottom) {
+ View placeChosenButton = findViewById(R.id.place_chosen_button);
+ LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) placeChosenButton.getLayoutParams();
+ params.bottomMargin = newBottom;
+ placeChosenButton.setLayoutParams(params);
+ }
+
+ /**
+ * Initialize {@link PlaceOptions} to use when creating an instance of {@link PlaceAutocompleteFragment}
+ * if search was enabled in the {@link PlacePickerOptions}.
+ *
+ * @return a fully built {@link PlaceOptions} object.
+ */
+ private PlaceOptions initPlaceOptions() {
+ int toolbarColor = customToolbarColor != null ? customToolbarColor
+ : getThemePrimaryColor(PlacePickerActivity.this);
+ int statusBarColor = options.statusBarColor() != null ? options.statusBarColor()
+ : getThemePrimaryDarkColor(PlacePickerActivity.this);
+ return PlaceOptions.builder()
+ .toolbarColor(toolbarColor)
+ .statusbarColor(statusBarColor)
+ .hint(getString(R.string.mapbox_plugins_autocomplete_search_hint))
+ .build();
+ }
+
+ @Override
+ public boolean onMapClick(@NonNull LatLng point) {
+ if (!resultsCardViewListIsCollapsed) {
+ adjustResultsCardViewHeight(false);
+ KeyboardUtils.hideKeyboard(getWindow().getDecorView());
+ }
+ return true;
}
private void adjustCameraBasedOnOptions() {
@@ -189,7 +382,6 @@ private void enableLocationComponent(@NonNull Style loadedMapStyle) {
// Set the component's render mode
locationComponent.setRenderMode(RenderMode.NORMAL);
- addUserLocationButton();
} else {
permissionsManager = new PermissionsManager(this);
permissionsManager.requestLocationPermissions(this);
@@ -213,7 +405,7 @@ public void onPermissionResult(boolean granted) {
mapboxMap.getStyle(new Style.OnStyleLoaded() {
@Override
public void onStyleLoaded(@NonNull Style style) {
- if (options != null && options.includeDeviceLocationButton()) {
+ if (options != null && includeDeviceLocationButton) {
enableLocationComponent(style);
}
}
@@ -221,6 +413,85 @@ public void onStyleLoaded(@NonNull Style style) {
}
}
+ /**
+ * Adjusts the height of the {@link PlaceAutocompleteFragment} CardView.
+ *
+ * @param expandCard whether or not the height should be lengthened.
+ */
+ public void adjustResultsCardViewHeight(boolean expandCard) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ TransitionManager.beginDelayedTransition(searchResultsCardView, new TransitionSet()
+ .addTransition(new ChangeBounds()));
+ ViewGroup.LayoutParams params = searchResultsCardView.getLayoutParams();
+ params.height = expandCard ? EXPANDED_SEARCH_CARDVIEW_HEIGHT : COLLAPSED_SEARCH_CARDVIEW_HEIGHT;
+ searchResultsCardView.setLayoutParams(params);
+ } else {
+ searchResultsCardView.setLayoutParams(new FrameLayout.LayoutParams(
+ searchResultsCardView.getMeasuredWidth(), expandCard ? EXPANDED_SEARCH_CARDVIEW_HEIGHT
+ : COLLAPSED_SEARCH_CARDVIEW_HEIGHT));
+ }
+ adjustMapTopPadding(expandCard);
+ adjustMapCompassTopPadding(expandCard);
+ resultsCardViewListIsCollapsed = !expandCard;
+ }
+
+ private void adjustMapTopPadding(boolean cardExpanded) {
+ int[] mapPadding = mapboxMap.getPadding();
+ mapboxMap.setPadding(mapPadding[0], cardExpanded ? EXPANDED_SEARCH_CARDVIEW_HEIGHT
+ : COLLAPSED_SEARCH_CARDVIEW_HEIGHT,
+ mapPadding[2], mapPadding[3]);
+ }
+
+ private void adjustMapCompassTopPadding(boolean cardExpanded) {
+ int[] mapPadding = mapboxMap.getPadding();
+ int newTopPadding;
+ newTopPadding = cardExpanded
+ ? EXPANDED_SEARCH_CARDVIEW_HEIGHT + SPACE_BETWEEN_RESULTS_LIST_AND_COMPASS
+ : COLLAPSED_SEARCH_CARDVIEW_HEIGHT + SPACE_BETWEEN_RESULTS_LIST_AND_COMPASS;
+ mapboxMap.getUiSettings().setCompassMargins(mapPadding[0],
+ newTopPadding, mapPadding[2], mapPadding[3]);
+ }
+
+ /**
+ * Get the primary color from the app's theming.
+ *
+ * @param context this activity's context.
+ * @return an int value representing the theme's primary color
+ */
+ private static int getThemePrimaryColor(Context context) {
+ int colorAttr;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ colorAttr = android.R.attr.colorPrimary;
+ } else {
+ //Get colorAccent defined for AppCompat
+ colorAttr = context.getResources().getIdentifier("colorPrimary", "attr",
+ context.getPackageName());
+ }
+ TypedValue outValue = new TypedValue();
+ context.getTheme().resolveAttribute(colorAttr, outValue, true);
+ return outValue.data;
+ }
+
+ /**
+ * Get the primary dark color from the app's theming.
+ *
+ * @param context this activity's context.
+ * @return an int value representing the theme's primary dark color
+ */
+ private static int getThemePrimaryDarkColor(Context context) {
+ int colorAttr;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ colorAttr = android.R.attr.colorPrimaryDark;
+ } else {
+ //Get colorAccent defined for AppCompat
+ colorAttr = context.getResources().getIdentifier("colorPrimaryDark",
+ "attr", context.getPackageName());
+ }
+ TypedValue outValue = new TypedValue();
+ context.getTheme().resolveAttribute(colorAttr, outValue, true);
+ return outValue.data;
+ }
+
@Override
public void onCameraMoveStarted(int reason) {
Timber.v("Map camera has begun moving.");
@@ -241,7 +512,13 @@ public void onCameraIdle() {
markerImage.animate().translationY(0)
.setInterpolator(new OvershootInterpolator()).setDuration(250).start();
if (includeReverseGeocode) {
- bottomSheet.setPlaceDetails(null);
+ if (includeSearch) {
+ if (carmenFeature != null) {
+ bottomSheet.setPlaceDetails(carmenFeature);
+ }
+ } else {
+ bottomSheet.setPlaceDetails(null);
+ }
// Initialize with the markers current location information.
makeReverseGeocodingSearch();
}
@@ -287,8 +564,8 @@ public void onClick(View view) {
}
/**
- * Bind the device location Floating Action Button to this activity's UI and move the
- * map camera if the button's clicked.
+ * Bind the device location Floating Action Button to this activity's UI and animate the
+ * map camera to the device's location if the button's clicked.
*/
private void addUserLocationButton() {
userLocationButton.show();
@@ -300,10 +577,10 @@ public void onClick(View view) {
mapboxMap.animateCamera(CameraUpdateFactory.newCameraPosition(
new CameraPosition.Builder()
.target(new LatLng(lastKnownLocation.getLatitude(),
- lastKnownLocation.getLongitude()))
+ lastKnownLocation.getLongitude()))
.zoom(17.5)
.build()
- ),1400);
+ ), 1400);
} else {
Toast.makeText(PlacePickerActivity.this,
getString(R.string.mapbox_plugins_place_picker_user_location_not_found), Toast.LENGTH_SHORT).show();
@@ -323,6 +600,14 @@ void placeSelected() {
finish();
}
+ public int getToolBarHeight() {
+ int[] attrs = new int[] {R.attr.actionBarSize};
+ TypedArray ta = this.obtainStyledAttributes(attrs);
+ int toolBarHeight = ta.getDimensionPixelSize(0, -1);
+ ta.recycle();
+ return toolBarHeight;
+ }
+
@Override
protected void onStart() {
super.onStart();
diff --git a/plugin-places/src/main/res/drawable/mapbox_ic_arrow_back.xml b/plugin-places/src/main/res/drawable/mapbox_ic_arrow_back.xml
index beafea395..4933d7f7b 100644
--- a/plugin-places/src/main/res/drawable/mapbox_ic_arrow_back.xml
+++ b/plugin-places/src/main/res/drawable/mapbox_ic_arrow_back.xml
@@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
diff --git a/plugin-places/src/main/res/drawable/mapbox_ic_clear.xml b/plugin-places/src/main/res/drawable/mapbox_ic_clear.xml
index ede4b7108..3edee749b 100644
--- a/plugin-places/src/main/res/drawable/mapbox_ic_clear.xml
+++ b/plugin-places/src/main/res/drawable/mapbox_ic_clear.xml
@@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
diff --git a/plugin-places/src/main/res/layout/mapbox_activity_place_picker.xml b/plugin-places/src/main/res/layout/mapbox_activity_place_picker.xml
index ed0987f6c..cf242b5e3 100644
--- a/plugin-places/src/main/res/layout/mapbox_activity_place_picker.xml
+++ b/plugin-places/src/main/res/layout/mapbox_activity_place_picker.xml
@@ -1,20 +1,35 @@
-
-
-
+ android:layout_height="match_parent"
+ tools:context="com.mapbox.mapboxsdk.plugins.places.picker.ui.PlacePickerActivity">
-
+
-
+
-
+
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugin-places/src/main/res/layout/mapbox_content_place_picker.xml b/plugin-places/src/main/res/layout/mapbox_content_place_picker.xml
index 802c0ea44..98f46fb69 100644
--- a/plugin-places/src/main/res/layout/mapbox_content_place_picker.xml
+++ b/plugin-places/src/main/res/layout/mapbox_content_place_picker.xml
@@ -34,7 +34,7 @@
android:id="@+id/map_view"
android:layout_width="0dp"
android:layout_height="0dp"
- app:mapbox_uiLogo="false"
+ app:mapbox_uiLogo="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
diff --git a/plugin-places/src/main/res/layout/mapbox_view_bottom_sheet_container.xml b/plugin-places/src/main/res/layout/mapbox_view_bottom_sheet_container.xml
index 345604a26..10b26004b 100644
--- a/plugin-places/src/main/res/layout/mapbox_view_bottom_sheet_container.xml
+++ b/plugin-places/src/main/res/layout/mapbox_view_bottom_sheet_container.xml
@@ -1,47 +1,20 @@
-
-
-
-
-
+ app:srcCompat="@drawable/mapbox_logo_icon" />
+
+ app:layout_anchorGravity="top" />
-
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugin-places/src/main/res/layout/mapbox_view_search.xml b/plugin-places/src/main/res/layout/mapbox_view_search.xml
index f6aea32f4..f194980ee 100644
--- a/plugin-places/src/main/res/layout/mapbox_view_search.xml
+++ b/plugin-places/src/main/res/layout/mapbox_view_search.xml
@@ -20,10 +20,10 @@
android:imeOptions="actionSearch|flagNoExtractUi"
android:inputType="textNoSuggestions"
android:singleLine="true"
+ android:textCursorDrawable="@null"
android:textColor="@color/mapbox_plugins_navy"
android:textColorHint="@color/mapbox_plugins_light_navy"
android:textColorLink="@color/mapbox_plugins_navy"
- android:textCursorDrawable="@drawable/mapbox_color_text_cursor"
android:textSize="16sp"
android:typeface="sans"
app:layout_constraintBottom_toBottomOf="parent"
@@ -41,7 +41,6 @@
android:contentDescription="@string/mapbox_plugins_cd_search_clear_button"
android:focusable="true"
android:scaleType="center"
- android:tint="@color/mapbox_plugins_navy"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
@@ -63,7 +62,6 @@
android:paddingRight="20dp"
android:paddingStart="0dp"
android:scaleType="center"
- android:tint="@color/mapbox_plugins_navy"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
diff --git a/plugin-places/src/test/java/com/mapbox/mapboxsdk/plugins/places/picker/PlacePickerTest.java b/plugin-places/src/test/java/com/mapbox/mapboxsdk/plugins/places/picker/PlacePickerTest.java
index 08511c9dd..89fec1713 100644
--- a/plugin-places/src/test/java/com/mapbox/mapboxsdk/plugins/places/picker/PlacePickerTest.java
+++ b/plugin-places/src/test/java/com/mapbox/mapboxsdk/plugins/places/picker/PlacePickerTest.java
@@ -7,7 +7,9 @@
import com.mapbox.api.geocoding.v5.models.CarmenFeature;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.geometry.LatLng;
+import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.plugins.places.common.PlaceConstants;
+import com.mapbox.mapboxsdk.plugins.places.picker.model.PlacePickerOptions;
import org.junit.Ignore;
import org.junit.Test;
@@ -72,6 +74,25 @@ public void intentBuilder_initializesCorrectly() throws Exception {
assertNotNull(builder);
}
+ @Test
+ public void intentBuilder_initializesCorrectlyWithSearchIncluded() throws Exception {
+ PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder();
+ builder.placeOptions(PlacePickerOptions.builder()
+ .includeReverseGeocode(true)
+ .includeSearch(true)
+ .build());
+ assertNotNull(builder);
+ }
+
+ @Test
+ public void intentBuilder_initializesCorrectlyWithCustomMapStyleIncluded() throws Exception {
+ PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder();
+ builder.placeOptions(PlacePickerOptions.builder()
+ .mapStyle(Style.SATELLITE)
+ .build());
+ assertNotNull(builder);
+ }
+
// TODO finish mocking this class
@Test
@Ignore
diff --git a/scripts/exclude-activity-gen.json b/scripts/exclude-activity-gen.json
index 1e2bc88eb..e3837c9d0 100644
--- a/scripts/exclude-activity-gen.json
+++ b/scripts/exclude-activity-gen.json
@@ -9,5 +9,6 @@
"LocationLayerFragmentActivity",
"LocationLayerMapChangeActivity",
"LocationLayerModesActivity",
- "ManualLocationUpdatesActivity"
+ "ManualLocationUpdatesActivity",
+ "PickerAutocompleteCombinedActivity"
]