cómo configurar el fragmento del mapa de google dentro de la vista de desplazamiento

Quiero establecer un fragmento de mapa de Google dentro de ScrollView vertical, cuando lo hago, el mapa no se acerca verticalmente, ¿cómo puedo anular el detector de eventos táctiles en MapView sobre el oyente de ScrollView ?

Este es mi código xml:

   ///other things  //other things 

Cree un SupportMapFragmet personalizado para que podamos anular su evento táctil:

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); } } } 

En esta clase anterior, interceptamos el evento táctil mediante el uso de la clase TouchableWrapper que extiende el FrameLayout. También hay un detector personalizado OnTouchListener para enviar el evento táctil a la actividad principal MyMapActivity que maneja el mapa. Cuando ocurra un evento táctil, se llamará a dispatchTouchEvent y el oyente mListener lo manejará.

A continuación, reemplace la clase fragment en xml con esta class="packagename.WorkaroundMapFragment" lugar de com.google.android.gms.maps.SupportMapFragment

Luego, en su actividad, inicialice el mapa de la siguiente manera:

 private GoogleMap mMap; 

dentro de Crear haz esto:

  // 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); } }); } }); } 

Actualización : respuesta actualizada a getMapAsync según la respuesta de @ javacoder123

Simplemente haga 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; } } 

Luego en xml

   

si xml antes no funcionaba, cambie a esto …

   

cómo usar programáticamente

 CustomScrollView myScrollView = (CustomScrollView) findViewById(R.id.idScrollView); 

Mi sugerencia es utilizar una versión más ligera del mapa de Google cuando se trata de esta situación. esto resolvió mi problema

agrega este atributo en fragmento

  map:liteMode="true" 

y mi problema se resolvió También agregué customScrollView además de esto. pero después de colocar la propiedad liteMode mi problema se resolvió.

Actualizar

La respuesta de @Alok Nair es muy buena, sin embargo, el método .getMap () ya no funciona desde Android 9.2 en adelante. Cambie el método getMap a .getMapAsync y agregue código en el método onMapReady

Solución actualizada, que funciona en fragmentos

 if (gMap == null) { getChildFragmentManager().findFragmentById(R.id.map); SupportMapFragment mapFragment = (WorkaroundMapFragment) getChildFragmentManager().findFragmentById(R.id.map); mapFragment.getMapAsync(new OnMapReadyCallback() { @Override public void onMapReady(GoogleMap googleMap) { gMap = googleMap; gMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); gMap.getUiSettings().setZoomControlsEnabled(true); mScrollView = mView.findViewById(R.id.advertScrollView); //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); } }); } }); } 

Por favor, consulte esta respuesta: https://stackoverflow.com/a/17317176/4837103

Crea una vista transparente con el mismo tamaño de mapFragment, en la misma posición con mapFragment, luego invoca requestDisallowInterceptTouchEvent (true), evitando que sus antepasados ​​intercepten los eventos táctiles.

Agregue una vista transparente sobre el fragmento mapview:

  ...       

Establecer el oyente táctil para esa vista transparente:

  var transparentTouchPanel = view.FindViewById (Resource.Id.transparent_touch_panel); transparentTouchPanel.SetOnTouchListener (this); 

….

 public bool OnTouch (View v, MotionEvent e) { switch (e.Action) { case MotionEventActions.Up: v.Parent.RequestDisallowInterceptTouchEvent (false); break; default: v.Parent.RequestDisallowInterceptTouchEvent (true); break; } return false; } 

Pensé que RequestDisallowInterceptTouchEvent podría funcionar al ser invocado solo una vez, pero aparentemente tiene que ser llamado para CADA evento táctil, es por eso que tiene que estar dentro de TouchEvent. Y el padre propagará esta solicitud al padre del padre.

Intenté establecer el detector de eventos táctiles para fl_google_map o para mapFragment.getView (). Ninguno de ellos funcionó, por lo que crear una vista de hermanos transparente es una solución tolerable para mí.

Lo he intentado, esta solución funciona a la perfección. Verifique los comentarios debajo de la publicación original si no me cree. Prefiero esto porque no necesita crear un SupportMapFragmet personalizado.