Я ищу что-то похожее на то, как Uber обрабатывает масштабные события масштабирования. Независимо от того, где вы щелкаете на экране, он удерживает карту в центре и масштабируется в центре. Есть ли способ сделать это без какого-либо наложения на фрагмент карты? Или я должен просто отключать события карт, создавать наложения над фрагментом карты и обрабатывать все трансляции/другие события из оверлея?Держите карту в центре независимо от того, где вы зажимаете масштаб на андроиде.
ответ
Я основал полное решение, потратив около 3 дней на поиск в google.Мой ответ редактируется от https://stackoverflow.com/a/32734436/3693334.
public class CustomMapView extends MapView {
private int fingers = 0;
private GoogleMap googleMap;
private long lastZoomTime = 0;
private float lastSpan = -1;
private Handler handler = new Handler();
private ScaleGestureDetector scaleGestureDetector;
private GestureDetector gestureDetector;
public CustomMapView(Context context) {
super(context);
}
public CustomMapView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomMapView(Context context, AttributeSet attrs, int style) {
super(context, attrs, style);
}
public CustomMapView(Context context, GoogleMapOptions options) {
super(context, options);
}
public void init(GoogleMap map) {
scaleGestureDetector = new ScaleGestureDetector(getContext(), new ScaleGestureDetector.OnScaleGestureListener() {
@Override
public boolean onScale(ScaleGestureDetector detector) {
if (lastSpan == -1) {
lastSpan = detector.getCurrentSpan();
} else if (detector.getEventTime() - lastZoomTime >= 50) {
lastZoomTime = detector.getEventTime();
googleMap.animateCamera(CameraUpdateFactory.zoomBy(getZoomValue(detector.getCurrentSpan(), lastSpan)), 50, null);
lastSpan = detector.getCurrentSpan();
}
return false;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
lastSpan = -1;
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
lastSpan = -1;
}
});
gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
disableScrolling();
googleMap.animateCamera(CameraUpdateFactory.zoomIn(), 400, null);
return true;
}
});
googleMap = map;
}
private float getZoomValue(float currentSpan, float lastSpan) {
double value = (Math.log(currentSpan/lastSpan)/Math.log(1.55d));
return (float) value;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
gestureDetector.onTouchEvent(ev);
switch (ev.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN:
fingers = fingers + 1;
break;
case MotionEvent.ACTION_POINTER_UP:
fingers = fingers - 1;
break;
case MotionEvent.ACTION_UP:
fingers = 0;
break;
case MotionEvent.ACTION_DOWN:
fingers = 1;
break;
}
if (fingers > 1) {
disableScrolling();
} else if (fingers < 1) {
enableScrolling();
}
if (fingers > 1) {
return scaleGestureDetector.onTouchEvent(ev);
} else {
return super.dispatchTouchEvent(ev);
}
}
private void enableScrolling() {
if (googleMap != null && !googleMap.getUiSettings().isScrollGesturesEnabled()) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
googleMap.getUiSettings().setAllGesturesEnabled(true);
}
}, 50);
}
}
private void disableScrolling() {
handler.removeCallbacksAndMessages(null);
if (googleMap != null && googleMap.getUiSettings().isScrollGesturesEnabled()) {
googleMap.getUiSettings().setAllGesturesEnabled(false);
}
}
}
и настроить MapFragment
public class CustomMapFragment extends Fragment {
CustomMapView view;
Bundle bundle;
GoogleMap map;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bundle = savedInstanceState;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_map, container, false);
view = (CustomMapView) v.findViewById(R.id.mapView);
view.onCreate(bundle);
view.onResume();
map = view.getMap();
view.init(map);
MapsInitializer.initialize(getActivity());
return v;
}
public GoogleMap getMap() {
return map;
}
@Override
public void onResume() {
super.onResume();
view.onResume();
}
@Override
public void onPause() {
super.onPause();
view.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
view.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
view.onLowMemory();
}
}
Наконец, в своей деятельности:
....
<fragment
android:id="@+id/map"
class="yourpackage.CustomMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
...
Я уже протестирована на Android 4.1 (API 16) и последняя, она работает нормально и гладко , (Об API < 16, у меня нет устройства для тестирования).
Что такое чувство математики .log (1.55d) '? И всего расчета масштабирования '(Math.log (currentSpan/lastSpan)/Math.log (1.55d))'? – NOSTRA
Я использовал это .., но у него есть проблема с «двойным нажатием удерживать слайд вверх или вниз». –
эта работа не работает на android 6.0 и выше –
Лично я отключил бы только жесты увеличения на карте, обнаружил щепотку на оверлее, а затем передал все остальное на карту.
API-интерфейс google-maps v2 API не имеет ничего конкретного для пользовательской обработки масштабирования. Хотя я уверен, что вы могли бы что-то добавить, использование метода наложения изолирует вас от изменений в картах Google и позволяет вам легче поддерживать других поставщиков карт, если это необходимо.
(Только для полноты:. Вы можете также обрабатывать событие изменения после камеры и повторно центра, но это было бы Janky, плохой пользовательский опыт)
Спасибо за ответ. Да, это то, что я думал, что мне нужно будет сделать. Я попробовал несколько хакерских способов сделать повторное центрирование, как вы сказали. И ты совершенно прав, сумасшедший. haha – SoCmodder
Вот код для того, что MechEthan думает.
Сначала вы должны обнаружить двойное касание в режиме наложения.
public class TouchableWrapper extends FrameLayout { private final GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDoubleTap(MotionEvent e) { //Notify the event bus (I am using Otto eventbus of course) that you have just received a double-tap event on the map, inside the event bus event listener EventBus_Singleton.getInstance().post(new EventBus_Poster("double_tapped_map")); return true; } }; public TouchableWrapper(Context context) { super(context); mGestureDetector = new GestureDetectorCompat(context, mGestureListener); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { mGestureDetector.onTouchEvent(ev); return super.onInterceptTouchEvent(ev); } }
Везде, где это, что вы захватывая MAPview, завернуть, что MAPview внутри TouchableWrapper созданного выше. Вот как я это делаю, потому что у меня есть вопрос о необходимости добавления MapFragment в другой фрагмент, поэтому мне нужно пользовательский SupportMapFragment сделать это
public class CustomMap_Fragment extends SupportMapFragment { TouchableWrapper mTouchView; public CustomMap_Fragment() { super(); } public static CustomMap_Fragment newInstance() { return new CustomMap_Fragment(); } @Override public View onCreateView(LayoutInflater arg0, ViewGroup arg1, Bundle arg2) { View mapView = super.onCreateView(arg0, arg1, arg2); Fragment fragment = getParentFragment(); if (fragment != null && fragment instanceof OnMapReadyListener) { ((OnMapReadyListener) fragment).onMapReady(); } mTouchView = new TouchableWrapper(getActivity()); mTouchView.addView(mapView); return mTouchView; } public static interface OnMapReadyListener { void onMapReady(); } }
Внутри моей Map_Fragment (который в конце концов будет сидеть внутри FrameLayout в деятельности, которая поддерживает панель навигации и фрагмент операции переключения мнений)
mMapFragment = CustomMap_Fragment.newInstance(); getChildFragmentManager().beginTransaction().replace(R.id.map_container, mMapFragment).commit();
Теперь, наконец, в этом же фрагменте, где я только что получил свою карту, приемник EventBus будет делать следующее действие, когда он получает «double_tapped_map» :
@Subscribe public void eventBus_ListenerMethod(AnswerAvailableEvent event) { //Construct a CameraUpdate object that will zoom into the exact middle of the map, with a zoom of currentCameraZoom + 1 unit zoomInUpdate = CameraUpdateFactory.zoomIn(); //Run that with a speed of 400 ms. map.animateCamera(zoomInUpdate, 400, null); }
Примечание: Для достижения этой цели прекрасно отключить zoomGestures на вашей карте (то есть вы myMap.getUiSettings().setZoomGesturesEnabled(false);
. Если вы этого не сделаете, вы сможете быстро нажать на карте, и вы увидите, что он будет уменьшаться от центра, потому что реализация двойного крана точно так же, как и в первом ответе Я опубликовал, что они вычитают текущее время из предыдущего времени переключения, поэтому в этом окне вы можете проскользнуть в третьем касании, и он не будет инициировать событие шины событий, а карта google поймает его; Поэтому отключите жестов увеличения.
Но тогда вы увидите, что pinch-in/out больше не будет работать, и вам также придется обрабатывать пинч, который я также сделал, но мне нужно еще 1 час, и я не получил время сделать это еще но 100% я буду обновлять ответ, когда я это сделаю.
СОВЕТ: Убер также отключил поворот жесты на карте. map.getUiSettings().setRotateGesturesEnabled(false);
Можете добавить несколько подробностей. Я добавил карту в свою деятельность. Используя [this] (http://stackoverflow.com/questions/27504606/how-to-implement-draggable-map-like-uber-android/30346234#30346234), и я хочу добавить в нее вышеприведенную функцию. – Shvet
В последнее время я решил эту проблему лучше, я отредактирую свой ответ, чтобы отразить все эти изменения, но, к сожалению, сегодня я не могу – Odaym
Хорошо. Если вы можете помочь, это будет хорошо. Я застрял в этой точке прямо сейчас :) – Shvet
Вы можете использовать LatLngBounds, чтобы ограничить перемещение карты из положения, которое вы хотите. (Вы можете установить как северо-восточный, так и юго-западный угол границы одной и той же точки).
Пожалуйста, проверьте приведенную ниже ссылку.
https://developers.google.com/maps/documentation/android-api/views
- 1. Держите touchZoom в центре?
- 2. Держите div всегда в центре по горизонтали независимо от количества
- 3. Держите изображение в центре независимо от размера экрана?
- 4. перебазирования d3 карту в центре экрана независимо от устройства
- 5. С огромным трудом выставляя всплывающее окно точно в центре, независимо от того, где оно всплывает
- 6. Держите микроконтроллеры периферийными драйверами независимо
- 7. Как сделать div, который остается в фиксированной позиции независимо от того, где вы находитесь на странице?
- 8. Где вы обычно держите типы в рельсах?
- 9. JOIN - независимо от того,
- 10. Держите место в центре в любое время
- 11. Как увеличить масштаб экрана в центре экрана?
- 12. Воспроизведение непрерывного звука независимо от того, где вы находитесь на временной шкале
- 13. Держите логотип в центре экрана
- 14. Держите логотип в центре и поддерживайте коэффициент
- 15. Гиперссылка открывается примерно: пусто, независимо от того, где она просматривается
- 16. Масштаб Анимация негладкая в андроиде на изображении
- 17. Можете ли вы отправить смс в приложение, независимо от того, в какой стране вы проживаете?
- 18. SceneKit: unprojectPoint возвращает ту же самую/аналогичную точку независимо от того, где вы касаетесь экрана
- 19. Python: CARD GAME BOT - Remastering (Как вы продолжаете линию, независимо от того, где она находится?)
- 20. Scala - Держите карту в Еогеасп
- 21. Создать DIV в центре экрана, независимо от того, что положение полосы прокрутки является
- 22. virtualenv зависит от того, где вы запускаете python от
- 23. Текстовая кнопка CSS не будет располагаться в центре независимо от того, что
- 24. NInject: Где вы держите свою ссылку на ядро?
- 25. R, находить дублирующиеся строки, независимо от того,
- 26. Неправильный BOOL независимо от того, что
- 27. Сделайте нижний колонтитул, независимо от того, что
- 28. Как вы держите GPG от запроса PinEntry?
- 29. .framework продукт красный независимо от того, что
- 30. держите два div бок о бок независимо от размера экрана
Пожалуйста звезда Эта функция запроса, чтобы позволить Google знать, что нам нужно: https://issuetracker.google.com/issues/69795937 – dan