comment mettre fragment de carte de google à l'intérieur de la vue scroll

je veux mettre un fragment de carte Google à l'intérieur de vertical ScrollView, quand je fais la carte ne fait pas de zoom vertical, Comment puis-je outrepasser l'écouteur d'événement touch sur MapView au cours de l'auditeur de ScrollView?

Voici mon code 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
24
demandé sur Shiba Prasad J. 2015-05-29 11:43:01

6 réponses

Créer un personnalisé SupportMapFragmet afin que nous puissions remplacer son événement tactile:

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

dans cette classe ci-dessus, nous interceptons l'événement touch en utilisant la classe TouchableWrapper qui étend le FrameLayout. Il y a aussi un écouteur personnalisé OnTouchListener pour envoyer l'événement touch à L'activité principale MyMapActivity qui gère la carte. Lorsque l'événement de contact s'est produit, dispatchTouchEvent sera appelé et l'écouteur mListener s'en chargera.

alors remplacez la classe fragment dans xml par ceci class="packagename.WorkaroundMapFragment" au lieu de com.google.android.gms.maps.SupportMapFragment

alors dans votre activité initialisez la carte comme suit:

private GoogleMap mMap;

à l'intérieur onCreate faire ceci:

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

mise à Jour : Réponse mis à jour à getMapAsync basé sur la réponse de @javacoder123

81
répondu Alok Nair 2018-06-28 05:10:01

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

puis 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 ne fonctionnait pas, Modifiez ceci...

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

comment utiliser programmaticaly

CustomScrollView myScrollView = (CustomScrollView) findViewById(R.id.idScrollView);
17
répondu Teimoor Alam Khan 2016-12-26 22:52:47

ma suggestion est d'utiliser une version plus légère de google map lorsque vous faites face à cette situation. cela a résolu mon problème.

ajouter cet attribut dans fragment.

 map:liteMode="true"

et mon problème s'est résolu. j'ai aussi ajouté customScrollView en plus de cela. mais après avoir placé la propriété de liteMode mon problème résolu.

1
répondu Hammad Tariq 2017-12-11 11:11:34

mise à Jour

@Alok Nair's réponse est très bonne cependant, le .la méthode getMap () ne fonctionne plus à partir d'android 9.2. Changez la méthode getMap en .getMapAsync et ajouter du code dans la méthode onMapReady

solution mise à jour, qui fonctionne en Fragments

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);
                                }
                            });
                }
            });
        }
0
répondu javacoder123 2018-04-06 21:31:39

reportez-vous à cette réponse: https://stackoverflow.com/a/17317176/4837103

il crée une vue transparente avec la même taille de mapFragment, à la même position avec mapFragment, puis invoque requestdisallowinterceptttouchevent (true), empêchant ses ancêtres d'intercepter les événements tactiles.

ajouter une vue transparente sur le fragment mapview:

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

Définir tactile écouteur pour que transparent vue:

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

j'ai pensé RequestDisallowInterceptTouchEvent pourrait fonctionner avec le fait d'être invoqué une seule fois, mais apparemment il doit être appelé pour chaque événement tactile, c'est pourquoi il doit être mis à l'intérieur onTouchEvent. Et le parent propagera cette requête au parent du parent.

j'ai essayé set touch event listener pour fl_google_map, ou pour le mapFragment.getView (). Ni l'un ni l'autre n'a fonctionné, créant ainsi une transparence frère vue est tolérable solution de contournement pour moi.

j'ai essayé, cette solution fonctionne parfaitement. Vérifiez les commentaires sous le message d'origine si vous ne me croyez pas. Je préfère cette façon parce qu'il n'a pas besoin de créer un SupportMapFragmet personnalisé.

0
répondu Chandler 2018-08-22 04:53:53

Document Android suggéré,

Vous pouvez ajouter l'instar de cette façon:

<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>
-9
répondu Ritesh Gajera 2015-05-29 08:56:59