无论在android上的何处收缩缩放,都要保持地图居中
我希望做一些类似Uber处理收缩缩放事件的方式。无论您在屏幕上挤压到哪里,它都会保持地图居中,并放大中心位置。有没有一种方法可以在不覆盖地图片段的情况下实现这一点?或者我应该禁用贴图的事件,在贴图片段上创建一个覆盖,并处理覆盖中的所有缩放/其他事件吗 就我个人而言,我只会禁用地图上的缩放手势,检测叠加上的挤压,然后将其他所有内容传递到地图 google maps v2 API没有任何明确的自定义缩放处理功能。虽然我相信你可以注入一些东西,但使用覆盖方法可以使你免受谷歌地图的变化,并让你在需要时更容易地支持其他地图提供商无论在android上的何处收缩缩放,都要保持地图居中,android,google-maps,location,zooming,Android,Google Maps,Location,Zooming,我希望做一些类似Uber处理收缩缩放事件的方式。无论您在屏幕上挤压到哪里,它都会保持地图居中,并放大中心位置。有没有一种方法可以在不覆盖地图片段的情况下实现这一点?或者我应该禁用贴图的事件,在贴图片段上创建一个覆盖,并处理覆盖中的所有缩放/其他事件吗 就我个人而言,我只会禁用地图上的缩放手势,检测叠加上的挤压,然后将其他所有内容传递到地图 google maps v2 API没有任何明确的自定义缩放处理功能。虽然我相信你可以注入一些东西,但使用覆盖方法可以使你免受谷歌地图的变化,并让你在需要时更
(为了完整起见:您也可以处理相机后的更改事件并重新调整中心,但这将是一种令人讨厌的用户体验。)以下是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);
}
}
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();
}
}
myMap.getUiSettings().setZoomGesturesEnabled(false)如果你不这样做,你将能够在地图上快速双击,你会看到地图将从中心变远,因为双击的实现与我发布的第一个答案完全相同,即他们从上一次点击时间中减去当前时间,因此在该窗口中,你可以滑入第三次点击并它不会触发事件总线事件,google map将捕获它;因此禁用缩放手势
但是,你会发现夹入/夹出不再有效,你也必须处理夹入/夹出,我也做了,但还需要1个小时,我还没有时间这样做,但100%我会在我做时更新答案
提示:优步也禁用了地图上的旋转手势。map.getUiSettings().setrotategesturenabled(false);
我花了大约3天的时间在谷歌上搜索后,找到了完整的解决方案。我的答案由编辑而成
最后,在您的活动中:
....
<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,我没有任何设备要测试)。您可以使用LatLngBounds限制地图从您想要的位置移动。(您可以将边界的东北角和西南角设置为同一点)
请查看下面的链接
我也有同样的要求。我必须了解android如何处理事件来解决这个问题,因为我们必须拦截用于缩放的触摸事件,并将滚动事件传递给地图。
为了实现这一点,我们需要一个自定义视图而不是谷歌地图视图。我们的自定义视图截取触摸事件,并决定是不给底层地图一个机会来处理后续事件,还是让底层地图自己来处理所有事件
现在是编码时间-
这里我们需要两样东西——一个自定义片段,一个自定义视图
自定义片段
public class CustomMapFragment extends SupportMapFragment implements OnMapReadyCallback {
public View mapView = null;
public WrapperView wrapperView = null;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
mapView = super.onCreateView(inflater, parent, savedInstanceState);
wrapperView = new WrapperView(getActivity());
wrapperView.addView(mapView);
SupportMapFragment mapFragment = (SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
return wrapperView;
}
@Override
public View getView() {
return mapView;
}
@Override
public void onMapReady(GoogleMap googleMap) {
wrapperView.setGoogleMap(googleMap);
}
自定义视图
public class WrapperView extends FrameLayout {
private GoogleMap googleMap;
Activity activity = null;
ScaleGestureDetector scaleGestureDetector;
public WrapperView(Activity activity) {
super(activity);
this.activity=activity;
scaleGestureDetector = new ScaleGestureDetector(activity ,new MyOnScaleGestureListener());
}
public void setGoogleMap(GoogleMap map){
googleMap = map;
}
private boolean isZoomInProgress(MotionEvent event){
if(event.getPointerCount()>1){
return true;
}
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event){
return isZoomInProgress(event);
}
@Override
public boolean onTouchEvent(MotionEvent event){
return scaleGestureDetector.onTouchEvent(event);
}
public class MyOnScaleGestureListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
float previousSpan = detector.getPreviousSpan();
float currentSpan = detector.getCurrentSpan();
float targetSpan;
if(previousSpan>currentSpan){
targetSpan = previousSpan-currentSpan;
}else{
targetSpan = currentSpan-previousSpan;
}
float scaleFactor = detector.getScaleFactor();
if (scaleFactor > 1) {
if(googleMap.getCameraPosition().zoom!=googleMap.getMaxZoomLevel()) {
for(int j=0;j<(targetSpan*2);j++){
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(googleMap.getCameraPosition().target, googleMap.getCameraPosition().zoom + 0.002f));
}
}
} else {
if (googleMap.getCameraPosition().zoom != googleMap.getMinZoomLevel()) {
for(int j=0;j<(targetSpan*2);j++){
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(googleMap.getCameraPosition().target, googleMap.getCameraPosition().zoom - 0.002f));
}
}
}
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {}
}
public类WrapperView扩展了FrameLayout{
私人谷歌地图谷歌地图;
活动=空;
scalegestruedetector scalegestruedetector;
公共包装器视图(活动){
超级(活动);
这个。活动=活动;
scalegestruedetector=新的scalegestruedetector(活动,新的MyOnScaleGestureListener());
}
公共无效设置谷歌地图(谷歌地图){
谷歌地图=地图;
}
私有布尔值isZoomInProgress(运动事件){
if(event.getPointerCount()>1){
返回true;
}
返回false;
}
@凌驾
公共布尔值onInterceptTouchEvent(MotionEvent){
返回isZoomInProgress(事件);
}
@凌驾
公共布尔onTouchEvent(运动事件){
返回scalegestruedetector.onTouchEvent(事件);
}
公共类MyOnScaleGestureListener扩展
ScaleGetStureDetector.SimpleOnScaleGetStureListener{
@凌驾
公共布尔标度(scalegestruedetector检测器){
float previousSpan=检测器。getPreviousSpan();
float currentSpan=检测器。getCurrentSpan();
浮动目标跨度;
如果(以前的span>currentSpan){
targetSpan=上一个SPAN currentSpan;
}否则{
targetSpan=当前span前一span;
}
float scaleFactor=detector.getScaleFactor();
如果(缩放因子>1){
if(googleMap.getCameraPosition().zoom!=googleMap.getMaxZoomLevel()){
对于(int j=0;j谢谢你的回答。是的,这就是我想我需要做的。我尝试了一些像你说的那样进行重新定心的黑客方法。你完全正确,超级强基。哈坎,你可以添加更多细节。我在我的活动中添加了地图。使用,我想在其中添加上述功能。我最近以更好的方式解决了这个问题y、 我将编辑我的答案以反映所有这些更改,但我今天不能。不幸的是,Yok。如果您能提供帮助,这将是很好的。我现在陷入了这一点:)谢谢。@Odaym。如果我将得到任何新的更新,我将把它放在您的编辑中并进行说明。它现在正在工作:)谢谢帮助,
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"/>
...
public class CustomMapFragment extends SupportMapFragment implements OnMapReadyCallback {
public View mapView = null;
public WrapperView wrapperView = null;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
mapView = super.onCreateView(inflater, parent, savedInstanceState);
wrapperView = new WrapperView(getActivity());
wrapperView.addView(mapView);
SupportMapFragment mapFragment = (SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
return wrapperView;
}
@Override
public View getView() {
return mapView;
}
@Override
public void onMapReady(GoogleMap googleMap) {
wrapperView.setGoogleMap(googleMap);
}
public class WrapperView extends FrameLayout {
private GoogleMap googleMap;
Activity activity = null;
ScaleGestureDetector scaleGestureDetector;
public WrapperView(Activity activity) {
super(activity);
this.activity=activity;
scaleGestureDetector = new ScaleGestureDetector(activity ,new MyOnScaleGestureListener());
}
public void setGoogleMap(GoogleMap map){
googleMap = map;
}
private boolean isZoomInProgress(MotionEvent event){
if(event.getPointerCount()>1){
return true;
}
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event){
return isZoomInProgress(event);
}
@Override
public boolean onTouchEvent(MotionEvent event){
return scaleGestureDetector.onTouchEvent(event);
}
public class MyOnScaleGestureListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
float previousSpan = detector.getPreviousSpan();
float currentSpan = detector.getCurrentSpan();
float targetSpan;
if(previousSpan>currentSpan){
targetSpan = previousSpan-currentSpan;
}else{
targetSpan = currentSpan-previousSpan;
}
float scaleFactor = detector.getScaleFactor();
if (scaleFactor > 1) {
if(googleMap.getCameraPosition().zoom!=googleMap.getMaxZoomLevel()) {
for(int j=0;j<(targetSpan*2);j++){
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(googleMap.getCameraPosition().target, googleMap.getCameraPosition().zoom + 0.002f));
}
}
} else {
if (googleMap.getCameraPosition().zoom != googleMap.getMinZoomLevel()) {
for(int j=0;j<(targetSpan*2);j++){
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(googleMap.getCameraPosition().target, googleMap.getCameraPosition().zoom - 0.002f));
}
}
}
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {}
}
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map"
android:name="yourpackage.CustomMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" />