ruta - mapview android studio
Cómo configurar el fragmento del mapa de Google dentro de la vista de desplazamiento (6)
Quiero establecer un fragmento de mapa de Google dentro de
ScrollView
vertical, cuando hago que el mapa no haga zoom verticalmente, ¿cómo puedo anular el detector de eventos táctiles en
MapView
sobre el receptor de
ScrollView
?
Este es mi código 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
Como sugirió el
documento de Android
,
Puedes agregar así:
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="3"
android:orientation="horizontal" >
<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
</ScrollView>
Consulte esta respuesta: https://.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 de vista de mapa:
<ScrollView>
...
<FrameLayout
android:layout_width="match_parent"
android:layout_height="300dp">
<FrameLayout
android:id="@+id/fl_google_map"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- workaround to make google map scrollable -->
<View
android:id="@+id/transparent_touch_panel"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</ScrollView>
Configure 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 con una invocación solo una vez, pero aparentemente tiene que ser llamado para CADA evento táctil, es por eso que debe colocarse dentro de TouchTvent. Y el padre propagará esta solicitud al padre del padre.
Intenté configurar el detector de eventos táctiles para fl_google_map o para mapFragment.getView (). Ninguno de ellos funcionó, por lo que crear una vista transparente para hermanos es una solución tolerable para mí.
Lo he intentado, esta solución funciona perfectamente. Revisa los comentarios debajo de la https://.com/a/17317176/4837103 si no me crees. Prefiero esta forma porque no necesita crear un SupportMapFragmet personalizado.
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 oyente personalizado OnTouchListener para enviar el evento táctil a la actividad principal MyMapActivity que maneja el mapa. Cuando ocurriera un evento táctil, se llamará a dispatchTouchEvent y el oyente mListener lo manejará.
Luego reemplace la clase de fragmento en xml con esta
class="packagename.WorkaroundMapFragment"
lugar de
com.google.android.gms.maps.SupportMapFragment
Luego, en su actividad, inicie el mapa de la siguiente manera:
private GoogleMap mMap;
dentro de onCreate 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 basada en la respuesta de @ javacoder123
Mi sugerencia es utilizar una versión más ligera de Google Map cuando se trata de esta situación. Esto resolvió mi problema.
agregue este atributo en fragmento.
map:liteMode="true"
Y mi problema resuelto. También agregué customScrollView además de esto. pero después de colocar la propiedad liteMode mi problema se resolvió.
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
<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>
si xml beffore no funcionó, cambie a esto ...
<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>
como usar programmaticaly
CustomScrollView myScrollView = (CustomScrollView) findViewById(R.id.idScrollView);
Actualizar
respuesta de 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);
}
});
}
});
}