gesture issue with mapview in viewpager page
Asked Answered
L

3

22

My app's main interface is a viewpager where the user just slides the pages horizontally to get to the various pages. One of the pages has a google mapview (pasted below). My problem is that if the user is on the map page and uses a horizontal slide gesture, the page slides to the next page instead of the map moving sideways. It's as if the viewpager is getting the gesture before the map.

If the user is clever and begins sliding the map in a diagonal or vertical direction the map begins moving and then the gesture can continue horizontally. But I would prefer the map move instead of the page on a simple horizontal slide gesture. The page can always be slid using the textview.

Is there any way I can make this happen?
thanks, Gary

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ContentPanel"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

 <TextView
    android:id="@+id/tvMAP"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Map"
    style="@style/bigtype" />


<com.google.android.maps.MapView
    android:id="@+id/mapview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:apiKey="mykeygoeshere"
    android:clickable="true" />

</LinearLayout>
Laird answered 24/8, 2012 at 23:15 Comment(0)
M
48

Of course there is:

public class CustomViewPager extends ViewPager {

    public CustomViewPager(Context context) {
        super(context);
    }

    public CustomViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) {
        if(v instanceof MapView){
            return true;
        }
        return super.canScroll(v, checkV, dx, x, y);
    }

}

This will make the map ignore all the slides inside the map and just care about the slides/draggs outside the map. Hope it helps. (I do this right now for a webview with horizontal scroll)

EDIT: Forgot to mention that instead of the ViewPager you need to use the CustomViewPager in yout layout.

<com.yourpackage.CustomViewPager
            android:id="@+id/viewpager"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" 
        />
Meekins answered 24/8, 2012 at 23:28 Comment(13)
I put your class into my main activity .java file. I changed the xml to call for com.deanblakely.CustomViewPager. Got runtime ClassNotFoundException com.deanblakely.CustomeViewPager. Is there something I forgot to do? (new to android and java).Laird
Well this is suppose to be in a separate class. You need to create a new file and put this code. In this case if you want to put "com.deanblakely.CustomViewPager" then create the file "CustomViewPager" in the folder "deanblakely" inside "com" folder.Meekins
Jorge. Yes, that worked once I put the class into a seperate file. Thanks.Laird
i did this and the view that returns in canScroll its a CustomViewPager not a MapView im touching the map (im using SupportMapFragment)Droll
Its because this approach was used for a Viewpager like you can see after the extend, i do not know if it works with MapView but you can try changing there.Meekins
Interesting... in my case canScroll method is not called altogether.. Dunno whyWivestad
@Wivestad are you sure that you are using the correct view on your layout ?Meekins
How to solve it for ViewPager2?Pieeyed
@AlitonOliveira it should be something similar, thou haven't use that view to be honest.Meekins
@AlitonOliveira did you get the answer for ViewPager2 ViewPager2 is a final class which can't be inherited.Younger
@JorgeAguilar do you have any other solution for this... when ViewPager2 is can't be inheritedYounger
@Younger from a quick look at the source code i can see that the behavior of VP2 is very different and in no way iterates over it's children as the VP did. So the only way i can see this working is by creating your own either LayoutManager or RecyclerView and use reflection to get the existing one inside the VP2 and just wrapped it around your implementation and then you can set your instance to the VP2 and so when it calls to check for canScrollHorizontally/canScrollVertically you do the checks needed and return true/false accordingly. If i get some time ill try to do it but no promiseMeekins
@JorgeAguilar Thanks for your comment.. I solved this issue, by writing custom mapView that extends google's map view and overriding dispatchTouchEvent method. This worked for me like a charm please take a look at my answer for the code..Younger
L
11

If using Google Maps V2, use

scrollingView.getClass().getPackage().getName().startsWith("maps.") in canScroll method:

@Override
protected boolean canScroll(View scrollingView, boolean checkV, int dx, int x, int y) {
    if (scrollingView.getClass().getPackage().getName().startsWith("maps.")) {
        return true;
    }
    return super.canScroll(scrollingView, checkV, dx, x, y);
}

Becase scrollingView is maps.j.b when using maps v2.

Also in my code, these classes are used:

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
Leoine answered 24/8, 2012 at 23:15 Comment(3)
scrollingView.getClass() is null every time for me so this errors.Upali
maybe scrollingView is null or you use anonymous ScrollingView class?Leoine
Documentation on Object.getClass() does not say anything about cases when getClass returns null.Leoine
Y
0

for ViewPager2, you can solve this issue by creating a custom view that extends, google's mapView. and override the dispatchTouchEvent method. The code should be as below

class CustomMapView: MapView {

    private var dontIntercepMove = false

    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        when (ev?.action) {
            MotionEvent.ACTION_DOWN -> dontIntercepMove =  ev.x < LEFT_SCROLL_OFFSET * width ||  ev.x > RIGHT_SCROLL_OFFSET * width
            MotionEvent.ACTION_MOVE -> if (!dontIntercepMove && parent != null) parent.requestDisallowInterceptTouchEvent(true)
        }

        return super.dispatchTouchEvent(ev)
    }
}

This will allow the mapview to scroll when you swipe on it.. and when you swipe on the edges the viewpager will work

Younger answered 24/4, 2022 at 4:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.