Kaartfragment in ScrollView

Ik heb een van de nieuwe MapFragmenten in een ScrollView. Eigenlijk is het een SupportMapFragment, maar toch. Het werkt, maar er zijn twee problemen:

  1. Als je scrolt, blijft er een zwart masker achter. Het zwart dekt precies het gebied waar de kaart was, behalve een gat waar de +/- zoomknoppen zaten. Zie screenshot hieronder. Dit is op Android 4.0.

  2. De weergave gebruikt requestDisallowInterceptTouchEvent()niet wanneer de gebruiker interactie heeft met de kaart om te voorkomen dat de ScrollViewaanrakingen onderschept, dus als u verticaal probeert te pannen in de kaart, het scrolt gewoon de bevattende ScrollView. Ik zou in theorie een weergaveklasse MapViewkunnen afleiden en die functionaliteit kunnen toevoegen, maar hoe kan ik MapFragmentertoe brengen mijn aangepaste MapViewte gebruiken in plaats van de standaardversie ?


Antwoord 1, autoriteit 100%

Het lijkt het probleem op te lossen door een transparante afbeelding toe te passen op het mapview-fragment. Het is niet de mooiste, maar het lijkt te werken. Hier is een XML-fragment dat dit laat zien:

<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>

Antwoord 2, autoriteit 68%

Voor mij heeft het toevoegen van een transparante ImageView niet geholpen om het zwarte masker volledig te verwijderen. De bovenste en onderste delen van de kaart vertoonden nog steeds het zwarte masker tijdens het scrollen.

Dus de oplossing daarvoor vond ik in dit antwoord met een kleine verandering.
Ik heb toegevoegd,

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

naar mijn kaartfragment omdat het verticale scrollview was. Dus mijn lay-out zag er nu zo uit:

<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>   

Om het tweede deel van de vraag op te lossen heb ik requestDisallowInterceptTouchEvent(true)ingesteld voor mijn hoofd ScrollView. Toen de gebruiker de transparante afbeelding aanraakte en bewoog, schakelde ik de aanraking van de transparante afbeelding uit voor MotionEvent.ACTION_DOWNen MotionEvent.ACTION_MOVEzodat het kaartfragment Touch Events kan opnemen.

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

Dit werkte voor mij. Ik hoop dat het je helpt..


Antwoord 3, autoriteit 15%

Dit heeft waarschijnlijk zijn wortels op dezelfde plaats als de oorzaak van het probleem in deze vraag. De oplossing daar is om een ​​transparant frame te gebruiken, dat iets lichter is dan een transparante afbeelding.


Antwoord 4, autoriteit 9%

Klaar na veel R&D:

fragment_one.xml zou er als volgt uit moeten zien:

<?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>

Uw Java-klasse van FragmentOne.java ziet er als volgt uit:

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

Antwoord 5, autoriteit 4%

Ik heb deze structuren gebruikt en ik heb het probleem overwonnen.

Ik heb een containerweergave gebruikt voor kaartfragmenten.

<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>

De containerklasse:

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

Antwoord 6, autoriteit 4%

Je hoeft niet te worstelen met customScrollViews en transparante lay-outbestanden. gebruik gewoon een lichtere versie van Google Maps en uw probleem zal worden opgelost.

 map:liteMode="true"

voeg bovenstaande eigenschap toe in kaartfragment in uw lay-outbestand. en probleem zal worden opgelost.


Antwoord 7

Voor het tweede deel van de vraag: u kunt een fragmentklasse afleiden uit SupportMapFragment en die in plaats daarvan in uw lay-out gebruiken. U kunt dan Fragment#onCreateView, en start daar uw aangepaste MapView.

Als dat niet werkt, kun je altijd je eigen fragment maken – dan hoef je alleen maar zelf te zorgen voor het aanroepen van alle levenscyclusmethoden (onCreate, onResume, etc). Dit antwoordbevat meer details.


Antwoord 8

<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>

Other episodes