varios studio proyecto marcadores mapas google example ejemplo agregar android google-maps android-mapview google-play-services

android - studio - MapFragment en ScrollView



map fragment android studio (8)

Tengo uno de los nuevos MapFragment en un ScrollView . En realidad es un SupportMapFragment , pero de todos modos. Funciona, pero hay dos problemas:

  1. Cuando se desplaza, deja una máscara negra detrás. El negro cubre exactamente el área donde estaba el mapa, a excepción de un agujero donde estaban los botones +/- del zoom. Vea la captura de pantalla a continuación. Esto es en Android 4.0.

  2. La vista no usa requestDisallowInterceptTouchEvent() cuando el usuario interactúa con el mapa para evitar los toques de interceptación de ScrollView , por lo que si intenta desplazarse verticalmente en el mapa, simplemente desplaza el ScrollView que lo contiene. En teoría, podría derivar una clase de vista MapView y agregar esa funcionalidad, pero ¿cómo puedo hacer que MapFragment use mi MapView personalizado en lugar del estándar?


Aplicar una imagen transparente sobre el fragmento mapview parece resolver el problema. No es el más bonito, pero parece funcionar. Aquí hay un fragmento de XML que muestra esto:

<RelativeLayout android:id="@+id/relativeLayout1" android:layout_width="match_parent" android:layout_height="300dp" > <fragment android:id="@+id/map" android:name="com.google.android.gms.maps.MapFragment" android:layout_width="fill_parent" android:layout_height="fill_parent"/> <ImageView android:id="@+id/imageView123" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/temp_transparent" /> </RelativeLayout>


Esto probablemente tiene sus raíces en el mismo lugar que causa el problema en esta pregunta . La solución es usar un marco transparente, que es un poco más ligero que una imagen transparente.


Hecho después de un montón de I + D:

fragment_one.xml debería verse así:

<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/scrollViewParent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <RelativeLayout android:layout_width="match_parent" android:layout_height="400dip" > <com.google.android.gms.maps.MapView android:id="@+id/mapView" android:layout_width="match_parent" android:layout_height="match_parent" /> <View android:id="@+id/customView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@android:color/transparent" /> </RelativeLayout> <!-- Your other elements are here --> </LinearLayout> </ScrollView>

Su clase de Java de FragmentOne.java se ve así:

private GoogleMap mMap; private MapView mapView; private UiSettings mUiSettings; private View customView

onCreateView

mapView = (MapView) rootView.findViewById(R.id.mapView); mapView.onCreate(savedInstanceState); if (mapView != null) { mMap = mapView.getMap(); mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); mUiSettings = mMap.getUiSettings(); mMap.setMyLocationEnabled(true); mUiSettings.setCompassEnabled(true); mUiSettings.setMyLocationButtonEnabled(false); } scrollViewParent = (ScrollView)rootView.findViewById(R.id.scrollViewParent); customView = (View)rootView.findViewById(R.id.customView); customView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: // Disallow ScrollView to intercept touch events. scrollViewParent.requestDisallowInterceptTouchEvent(true); // Disable touch on transparent view return false; case MotionEvent.ACTION_UP: // Allow ScrollView to intercept touch events. scrollViewParent.requestDisallowInterceptTouchEvent(false); return true; case MotionEvent.ACTION_MOVE: scrollViewParent.requestDisallowInterceptTouchEvent(true); return false; default: return true; } } });


No es necesario luchar con CustomScrollViews y archivos de diseño transparentes. simplemente use una versión más ligera de Google Map y su problema será resuelto.

map:liteMode="true"

agrega la propiedad anterior dentro del fragmento del mapa en tu archivo de diseño. y el problema será arreglado.


Para la segunda parte de la pregunta, puede derivar una clase de fragmento de SupportMapFragment y utilizarlo en su diseño. A continuación, puede anular Fragment#onCreateView y crear una instancia de su MapView personalizado allí.

Si eso no funciona, siempre puedes crear tu propio fragmento; luego, solo tienes que encargarte de llamar a todos los métodos del ciclo de vida (onCreate, onResume, etc.). Esta respuesta tiene más detalles.


Para mí, agregar un ImageView transparente no ayudó a eliminar completamente la máscara negra. Las partes superior e inferior del mapa mostraban la máscara negra mientras se desplazaban.

Entonces la solución para eso, encontré en esta respuesta con un pequeño cambio. Yo añadí,

android:layout_marginTop="-100dp" android:layout_marginBottom="-100dp"

a mi fragmento de mapa ya que era scrollview vertical. Entonces mi diseño ahora se veía de esta manera:

<RelativeLayout android:id="@+id/map_layout" android:layout_width="match_parent" android:layout_height="300dp"> <fragment android:id="@+id/mapview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="-100dp" android:layout_marginBottom="-100dp" android:name="com.google.android.gms.maps.MapFragment"/> <ImageView android:id="@+id/transparent_image" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@color/transparent" /> </RelativeLayout>

Para resolver la segunda parte de la pregunta, establecí requestDisallowInterceptTouchEvent(true) para mi ScrollView principal. Cuando el usuario tocó la imagen transparente y se movió, deshabilité el toque en la imagen transparente para MotionEvent.ACTION_DOWN y MotionEvent.ACTION_MOVE para que el fragmento del mapa pueda tomar Touch Events.

ScrollView mainScrollView = (ScrollView) findViewById(R.id.main_scrollview); ImageView transparentImageView = (ImageView) findViewById(R.id.transparent_image); transparentImageView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: // Disallow ScrollView to intercept touch events. mainScrollView.requestDisallowInterceptTouchEvent(true); // Disable touch on transparent view return false; case MotionEvent.ACTION_UP: // Allow ScrollView to intercept touch events. mainScrollView.requestDisallowInterceptTouchEvent(false); return true; case MotionEvent.ACTION_MOVE: mainScrollView.requestDisallowInterceptTouchEvent(true); return false; default: return true; } } });

Esto funcionó para mí. Espero que te ayude ...


Usé estas estructuras y superé el problema.

Usé una vista de contenedor para el fragmento de mapas.

<ScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:text="Another elements in scroll view1" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <com.erolsoftware.views.MyMapFragmentContainer android:orientation="vertical" android:layout_width="match_parent" android:layout_height="250dp"> <fragment xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/eventMap" tools:context="com.erolsoftware.eventapp.EventDetails" android:name="com.google.android.gms.maps.SupportMapFragment"/> </com.erolsoftware.views.MyMapFragmentContainer> <TextView android:text="Another elements in scroll view2" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> </ScrollView>

La clase de contenedor:

public class MyMapFragmentContainer extends LinearLayout { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) { ViewParent p = getParent(); if (p != null) p.requestDisallowInterceptTouchEvent(true); } return false; } public MyMapFragmentContainer(Context context) { super(context); } public MyMapFragmentContainer(Context context, AttributeSet attrs) { super(context, attrs); } public MyMapFragmentContainer(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } }


<ScrollView android:layout_width="match_parent" :: :: :: <FrameLayout android:id="@+id/map_add_business_one_rl" android:layout_width="match_parent" android:layout_height="100dp" > <fragment android:id="@+id/map" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="-100dp" android:layout_marginBottom="-100dp" /> </FrameLayout> :: :: :: </ScrollView>