J'aimerais avoir un MapView dans un ScrollView, mais lorsque j'essaie de faire défiler la carte, le ScrollView est prioritaire! Existe-t-il un moyen de donner la priorité à MapView lors du défilement dans la carte, et à ScrollView sinon?
Merci!
J'ai le même problème depuis 10 jours, mais j'ai trouvé une solution il y a quelques minutes!.
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
// Disallow ScrollView to intercept touch events.
this.getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_UP:
// Allow ScrollView to intercept touch events.
this.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
// Handle MapView's touch events.
super.onTouchEvent(ev);
return true;
}
Un moyen plus simple et plus efficace de le faire sans manipuler d’événements tactiles individuels . Cela fonctionnera si vous utilisez MapView:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
/**
* Request all parents to relinquish the touch events
*/
getParent().requestDisallowInterceptTouchEvent(true);
return super.dispatchTouchEvent(ev);
}
Classe complète:
public class CustomMapView extends MapView {
public CustomMapView(Context context) {
super(context);
}
public CustomMapView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomMapView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomMapView(Context context, GoogleMapOptions options) {
super(context, options);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
/**
* Request all parents to relinquish the touch events
*/
getParent().requestDisallowInterceptTouchEvent(true);
return super.dispatchTouchEvent(ev);
}
}
Si vous utilisez un MapFragment, vous pouvez placer le fragment dans une vue personnalisée et dans la dispatchTouchEvent()
faire l'appel requestDisallowInterceptTouchEvent
.
Faites votre propre carte et utilisez-la. Cela fonctionne pleinement pour moi.
public class CustomMapView extends MapView {
public CustomMapView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_UP:
System.out.println("unlocked");
this.getParent().requestDisallowInterceptTouchEvent(false);
break;
case MotionEvent.ACTION_DOWN:
System.out.println("locked");
this.getParent().requestDisallowInterceptTouchEvent(true);
break;
}
return super.dispatchTouchEvent(ev);
}}
Dans votre mise en page XML,
<com.yourpackage.xxxx.utils.CustomMapView
Android:id="@+id/customMap"
Android:layout_width="match_parent"
Android:layout_height="400dp"
Android:layout_marginLeft="5dp"
Android:layout_marginRight="5dp"
/>
Pour ceux qui veulent tout le code de travail. C'est ici
Classe d'affichage de la carte personnalisée
public class CustomMapView extends MapView {
private ViewParent mViewParent;
public CustomMapView(Context context) {
super(context);
}
public CustomMapView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomMapView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomMapView(Context context, GoogleMapOptions options) {
super(context, options);
}
public void setViewParent(@Nullable final ViewParent viewParent) { //any ViewGroup
mViewParent = viewParent;
}
@Override
public boolean onInterceptTouchEvent(final MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (null == mViewParent) {
getParent().requestDisallowInterceptTouchEvent(true);
} else {
mViewParent.requestDisallowInterceptTouchEvent(true);
}
break;
case MotionEvent.ACTION_UP:
if (null == mViewParent) {
getParent().requestDisallowInterceptTouchEvent(false);
} else {
mViewParent.requestDisallowInterceptTouchEvent(false);
}
break;
default:
break;
}
return super.onInterceptTouchEvent(event);
}
}
Présentation de l'activité xml
<ScrollView
Android:layout_width="match_parent"
Android:layout_height="wrap_content">
<location.to.your.CustomMapView
Android:id="@+id/mapView"
Android:layout_width="match_parent"
Android:layout_height="250dp"
/>
</ScrollView>
Instanciation de la classe de carte personnalisée dans votre activité ou fragment
CustomMapView mapView = (CustomMapView) findViewById(R.id.mapView);
C'est ça profiter
Vous pouvez créer un MapView personnalisé comme ceci:
public class CustomMapView extends MapView {
private MapFragment.ControlLock mCallbackControl;
public CustomMapView(Context context) {
this(context, null);
}
public CustomMapView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomMapView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomMapView(Context context, GoogleMapOptions options) {
super(context, options);
}
public void setCallback(MapFragment.ControlLock callbackControl) {
this.mCallbackControl = callbackControl;
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
System.out.println("unlocked");
mCallbackControl.unlock(); /* Interface */
break;
case MotionEvent.ACTION_DOWN:
System.out.println("locked");
mCallbackControl.lock(); /* Interface */
break;
}
return super.dispatchTouchEvent(event);
}
}
J'ai essayé de surcharger MapView.onTouchEvent (...), mais cela n'a pas fonctionné pour moi . Voici un code qui fonctionne bien (qui annule MapView.onInterceptTouchEvent (...)):
public class MyMapView extends MapView {
private ViewParent mViewParent;
//add constructors here
public void setViewParent(@Nullable final ViewParent viewParent) { //any ViewGroup
mViewParent = viewParent;
}
@Override
public boolean onInterceptTouchEvent(final MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (null == mViewParent) {
getParent().requestDisallowInterceptTouchEvent(true);
} else {
mViewParent.requestDisallowInterceptTouchEvent(true);
}
break;
case MotionEvent.ACTION_UP:
if (null == mViewParent) {
getParent().requestDisallowInterceptTouchEvent(false);
} else {
mViewParent.requestDisallowInterceptTouchEvent(false);
}
break;
default:
break;
}
return super.onInterceptTouchEvent(event);
}
}
Vous pouvez simplement mettre MapView dans une disposition elle-même et remplacer onTouch ou définir un écouteur de clic - le moyen le plus simple pour moi, car j'avais besoin de toucher à la totalité de MapView dans mon ScrollView.
Si vous avez MapView en mode défilement, vous devez explicitement mentionner les paramètres suivants à MapView:
mMapView.setClickable(true);
mMapView.setFocusable(true);
mMapView.setDuplicateParentStateEnabled(false);
Si quelqu'un veut cette classe en kotlin.
J'ai utilisé dispatchTouchEvent
comme suggéré par @rotem
class CustomMapView : MapView {
constructor(context: Context):
super(context)
constructor(context: Context, googleMapOptions: GoogleMapOptions):
super(context, googleMapOptions)
constructor(context: Context, attributeSet: AttributeSet):
super(context, attributeSet)
constructor(context: Context, attributeSet: AttributeSet, int: Int):
super(context, attributeSet, int)
override fun dispatchTouchEvent(event: MotionEvent?): Boolean {
Log.d("CustomWebView", "touchevent")
when(event?.action) {
MotionEvent.ACTION_UP -> {
Log.d("CustomWebView", "disallow Intercept")
parent.requestDisallowInterceptTouchEvent(false)
}
MotionEvent.ACTION_DOWN -> {
Log.d("CustomWebView", "allow Intercept")
parent.requestDisallowInterceptTouchEvent(true)
}
}
return super.dispatchTouchEvent(event)
}
}