如何在滚动视图中设置谷歌地图片段

Mal*_*alo 36 android google-maps android-fragments

我想设置内垂直一个谷歌地图片段ScrollView,当我做的地图不垂直缩放,我怎么可以覆盖触摸事件监听器MapView上的监听器ScrollView

这是我的xml代码:

  <ScrollView  android:layout_height="wrap_content"
    android:layout_width="fill_parent"
     android:layout_above="@id/footer"
    android:layout_below="@id/title_horizontalScrollView">

   ///other things



<fragment 
    android:id="@+id/map"
    android:layout_width="fill_parent"
    android:layout_height="300dp"
    class="com.google.android.gms.maps.SupportMapFragment"
    />

  //other things
Run Code Online (Sandbox Code Playgroud)

Alo*_*air 107

创建一个自定义的SupportMapFragmet,以便我们可以覆盖其触摸事件:

WorkaroundMapFragment.java

import android.content.Context;
import android.os.Bundle;
import android.widget.FrameLayout;

import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import com.google.android.gms.maps.SupportMapFragment;

public class WorkaroundMapFragment extends SupportMapFragment {
    private OnTouchListener mListener;

    @Override
    public View onCreateView(LayoutInflater layoutInflater, ViewGroup viewGroup, Bundle savedInstance) {
        View layout = super.onCreateView(layoutInflater, viewGroup, savedInstance);

        TouchableWrapper frameLayout = new TouchableWrapper(getActivity());

        frameLayout.setBackgroundColor(getResources().getColor(android.R.color.transparent));

        ((ViewGroup) layout).addView(frameLayout,
                new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

        return layout;
    }

    public void setListener(OnTouchListener listener) {
        mListener = listener;
    }

    public interface OnTouchListener {
        public abstract void onTouch();
    }

    public class TouchableWrapper extends FrameLayout {

        public TouchableWrapper(Context context) {
            super(context);
        }

        @Override
        public boolean dispatchTouchEvent(MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    mListener.onTouch();
                    break;
                case MotionEvent.ACTION_UP:
                    mListener.onTouch();
                    break;
            }
            return super.dispatchTouchEvent(event);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在上面的类中,我们通过使用扩展FrameLayout的TouchableWrapper类拦截触摸事件.还有一个自定义侦听器OnTouchListener将触摸事件分派给处理地图的主要活动MyMapActivity.当触摸事件发生时,将调用dispatchTouchEvent并且监听器mListener将处理它.

然后用x替换xml中的fragment类class="packagename.WorkaroundMapFragment"而不是com.google.android.gms.maps.SupportMapFragment

然后在您的活动初始化地图中,如下所示:

private GoogleMap mMap;
Run Code Online (Sandbox Code Playgroud)

在onCreate里面这样做:

  // check if we have got the googleMap already
  if (mMap == null) {
        SupportMapFragment mapFragment = (WorkaroundMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(new OnMapReadyCallback() {
            Override
                public void onMapReady(GoogleMap googleMap)
                    {
                        mMap = googleMap;
                        mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
                        mMap.getUiSettings().setZoomControlsEnabled(true);

                        mScrollView = findViewById(R.id.scrollMap); //parent scrollview in xml, give your scrollview id value
                        ((WorkaroundMapFragment) getChildFragmentManager().findFragmentById(R.id.map))
                                .setListener(new WorkaroundMapFragment.OnTouchListener() {
                            @Override
                            public void onTouch()
                                {
                                        mScrollView.requestDisallowInterceptTouchEvent(true);
                                }
                            });
                    }
        });
    }
Run Code Online (Sandbox Code Playgroud)

更新:根据@ javacoder123的回答更新到getMapAsync的答案


小智 27

刚做CustomScrollView.class,

public class CustomScrollView extends ScrollView {

public CustomScrollView(Context context) {
    super(context);
}

public CustomScrollView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public CustomScrollView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    final int action = ev.getAction();
    switch (action) {
        case MotionEvent.ACTION_DOWN:
            //Log.i("CustomScrollView", "onInterceptTouchEvent: DOWN super false" );
            super.onTouchEvent(ev);
            break;

        case MotionEvent.ACTION_MOVE:
            return false; // redirect MotionEvents to ourself

        case MotionEvent.ACTION_CANCEL:
            // Log.i("CustomScrollView", "onInterceptTouchEvent: CANCEL super false" );
            super.onTouchEvent(ev);
            break;

        case MotionEvent.ACTION_UP:
            //Log.i("CustomScrollView", "onInterceptTouchEvent: UP super false" );
            return false;

        default:
            //Log.i("CustomScrollView", "onInterceptTouchEvent: " + action );
            break;
    }

    return false;
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    super.onTouchEvent(ev);
    //Log.i("CustomScrollView", "onTouchEvent. action: " + ev.getAction() );
    return true;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后在xml中

<com.app.ui.views.CustomScrollView
     android:id="@+id/scrollView"
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:fillViewport="true"
     android:orientation="vertical">
</com.app.ui.views.CustomScrollView>
Run Code Online (Sandbox Code Playgroud)

如果xml beffore没有工作改变这个...

<com.myproyect.myapp.CustomScrollView
        android:id="@+id/idScrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        android:descendantFocusability="beforeDescendants"
        >
</com.myproyect.myapp.CustomScrollView>
Run Code Online (Sandbox Code Playgroud)

如何使用programmaticaly

CustomScrollView myScrollView = (CustomScrollView) findViewById(R.id.idScrollView);
Run Code Online (Sandbox Code Playgroud)


Dee*_*Shu 8

我使用谷歌地图侦听器来解决滚动视图谷歌地图的滚动问题。

    googleMap?.setOnCameraMoveStartedListener {
        mapView.parent.requestDisallowInterceptTouchEvent(true)

    }

    googleMap?.setOnCameraIdleListener {
        mapView.parent.requestDisallowInterceptTouchEvent(false)

    }
Run Code Online (Sandbox Code Playgroud)

通过在您使用开始移动地图时使用它,它禁止父滚动,当您停止移动地图时,它允许滚动。


jua*_*njo 5

这是Alok Nair 回答的 Kotlin 版本,我不得不说我是相对较新的 Kotlin 代码编写者,感谢任何评论。

自定义 SupportMapFragmet:

class FocusMapFragment: SupportMapFragment() {
    var listener: OnTouchListener? = null
    lateinit var frameLayout: TouchableWrapper

    override fun onAttach(context: Context) {
        super.onAttach(context)

        frameLayout = TouchableWrapper(context)
        frameLayout.setBackgroundColor(ContextCompat.getColor(context, android.R.color.transparent))
    }

    override fun onCreateView(inflater: LayoutInflater, viewGroup: ViewGroup?, bundle: Bundle?): View? {
        val layout = super.onCreateView(inflater, viewGroup, bundle)

        val params = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
        (layout as? ViewGroup)?.addView(frameLayout, params)

        return layout
    }

    interface OnTouchListener {
        fun onTouch()
    }

    inner class TouchableWrapper(context: Context): FrameLayout(context) {
        override fun dispatchTouchEvent(event: MotionEvent?): Boolean {
            when (event?.action) {
                MotionEvent.ACTION_DOWN, MotionEvent.ACTION_UP -> listener?.onTouch()
            }
            return super.dispatchTouchEvent(event)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后更改xml中的fragment类:

android:name="packagename.FocusMapFragment"
Run Code Online (Sandbox Code Playgroud)

最后当你初始化地图时:

override fun onMapReady(googleMap: GoogleMap) {
    this.googleMap = googleMap

    (childFragmentManager.findFragmentById(R.id.mapView) as? FocusMapFragment)?.let {
        it.listener = object: FocusMapFragment.OnTouchListener {
            override fun onTouch() {
                scrollView?.requestDisallowInterceptTouchEvent(true)
            }
        }
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)

我在 API 28 和 29 中测试了这段代码,我在任何地方都找不到 Kotlin 版本,所以我认为它可能对某些人有用。