Scroll Webview in Viewpager
Asked Answered
B

3

16

I have a WebView in a ViewPager. And the ViewPager seems to consume all the horizontal scrolling, so that I can't scroll in the WebView (vertical works).

How can I achieve that the WebView has got priority consuming the horizontal scrolling?

Blacklist answered 9/1, 2012 at 0:8 Comment(2)
You will have to override the view pager, I'm not home hope I remember when I get thereCentaur
hey :) something new with this, also stuck with the same problem... :)Tiphanie
T
9

don't ask me why this code gets formatted like this,

1. implement a custom ViewPager Instance like this:

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;

public class CustomViewPager extends ViewPager {

    private MagazineWebView_WithoutFlipWebView mCurrentPageWebView_; //custom webview

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

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {

        if (Constants.LOGGING) {
            Log.v(Constants.LOG_OEAMTC_APP, "CustomViewPager - onInterceptTouchEvent");
        }

        // if view zoomed out (view starts at 33.12... scale level) ... allow
        // zoom within webview, otherwise disallow (allow viewpager to change
        // view)
        if (mCurrentPageWebView_ != null && (mCurrentPageWebView_.getScale() * 100) > 34) {
            Log.v(Constants.LOG_OEAMTC_APP, "CustomViewPager - intrcepted: " + String.valueOf((mCurrentPageWebView_.getScale() * > 100)));
            this.requestDisallowInterceptTouchEvent(true);
        }
        else {
            if (mCurrentPageWebView_ != null) {
                Log.v(Constants.LOG_OEAMTC_APP,
                        "CustomViewPager - not intrcepted: " + String.valueOf(mCurrentPageWebView_.getScale() * 100));
            }
            this.requestDisallowInterceptTouchEvent(false);
        }

        return super.onInterceptTouchEvent(event);
    }

    public MagazineWebView_WithoutFlipWebView getCurrentPageWebView() {
        return mCurrentPageWebView_;
    }

    public void setCurrentPageWebView(MagazineWebView_WithoutFlipWebView currentPageWebView) {
        mCurrentPageWebView_ = currentPageWebView;
    }
}

2. in your main (ViewPager) Activity add the following lines to the view pager

mViewPager_ = new AwesomePagerAdapter();
viewpapgerInLayout = (CustomViewPager) findViewById(R.id.awesomepager);
viewpapgerInLayout.setAdapter(mViewPager_);
viewpapgerInLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageSelected(int position) {
        viewpapgerInLayout.setCurrentPageWebView(mLstPagesWebviews_.get(position));
    }
    
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
    }
    
    @Override
    public void onPageScrollStateChanged(int state) {
    
    }
});

3. finally, run it :=) if the zoom level is at initial zoom, changes pages is allowed, all the other time you can navigate your web view

Ps.: Don't forget to change your ViewPager in your *.xml file with the CustomViewPager Class you just created

good luck :)

Tiphanie answered 20/1, 2012 at 15:12 Comment(2)
is it possible to change the code so that if the webview is totally scrolled to one side and then if i scroll further more in the direction the viewpager consumes the scroll even if the webview doesn´t have the inital zoom level ?Blacklist
yes i think that me be possible, you have just to adapt the code (for me it's not necessary), but maybe for others it would be great if you share your code. theoretically just access the X,Y axes of the webview and check if you are on a border or not, if so, let the viewpager change the page :) good luck :=) (vote your this answer if you like it)Tiphanie
V
2

Late to this question and I come up with a different approach to fix this issue by override the WebView onTouchEvent method. It works on both ViewPager and ViewPager2. Hope this would help the future SO.

Note: Replace your WebView with NestedScrollWebView

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.webkit.WebView
import androidx.core.view.NestedScrollingChild
import androidx.core.view.NestedScrollingChildHelper
import androidx.core.view.ViewCompat

class NestedScrollWebView : WebView, NestedScrollingChild {

    companion object {
        val TAG: String = NestedScrollWebView::class.java.simpleName
    }

    private var lastMotionX: Int = 0
    private var lastMotionY: Int = 0

    private val scrollOffset = IntArray(2)
    private val scrollConsumed = IntArray(2)

    private var nestedOffsetY: Int = 0

    private var childHelper = NestedScrollingChildHelper(this)

    constructor(context: Context) : super(context) {
        init()
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        init()
    }

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        init()
    }

    private fun init() {
        isNestedScrollingEnabled = true
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        var result = false

        val trackedEvent = MotionEvent.obtain(event)

        val action = event.actionMasked

        if (action == MotionEvent.ACTION_DOWN) {
            nestedOffsetY = 0
        }

        val x = event.x.toInt()
        val y = event.y.toInt()

        event.offsetLocation(0f, nestedOffsetY.toFloat())

        when (action) {
            MotionEvent.ACTION_DOWN -> {
                lastMotionX = x
                lastMotionY = y
                startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL)
                result = super.onTouchEvent(event)
            }
            MotionEvent.ACTION_MOVE -> {
                var deltaY = lastMotionY - y

                if (kotlin.math.abs(deltaY) > kotlin.math.abs(lastMotionX - x) &&
                    (canScrollVertically(1) || canScrollVertically(-1))
                ) {
                    requestDisallowInterceptTouchEvent(true)
                }

                if (dispatchNestedPreScroll(0, deltaY, scrollConsumed, scrollOffset)) {
                    deltaY -= scrollConsumed[1]
                    trackedEvent.offsetLocation(0f, scrollOffset[1].toFloat())
                    nestedOffsetY += scrollOffset[1]
                }

                lastMotionY = y - scrollOffset[1]

                val oldY = scrollY
                val newScrollY = Math.max(0, oldY + deltaY)
                val dyConsumed = newScrollY - oldY
                val dyUnconsumed = deltaY - dyConsumed

                if (dispatchNestedScroll(0, dyConsumed, 0, dyUnconsumed, scrollOffset)) {
                    lastMotionY -= scrollOffset[1]
                    trackedEvent.offsetLocation(0f, scrollOffset[1].toFloat())
                    nestedOffsetY += scrollOffset[1]
                }

                result = super.onTouchEvent(trackedEvent)
                trackedEvent.recycle()
            }
            MotionEvent.ACTION_POINTER_DOWN, MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                stopNestedScroll()
                requestDisallowInterceptTouchEvent(false)
                result = super.onTouchEvent(event)
            }
        }
        return result
    }

    // NestedScrollingChild

    override fun setNestedScrollingEnabled(enabled: Boolean) {
        childHelper.isNestedScrollingEnabled = enabled
    }

    override fun stopNestedScroll() {
        childHelper.stopNestedScroll()
    }

    override fun isNestedScrollingEnabled() =
        childHelper.isNestedScrollingEnabled

    override fun startNestedScroll(axes: Int) =
        childHelper.startNestedScroll(axes)

    override fun hasNestedScrollingParent() =
        childHelper.hasNestedScrollingParent()

    override fun dispatchNestedScroll(dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, offsetInWindow: IntArray?) =
        childHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow)

    override fun dispatchNestedPreScroll(dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?) =
        childHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)

    override fun dispatchNestedFling(velocityX: Float, velocityY: Float, consumed: Boolean) =
        childHelper.dispatchNestedFling(velocityX, velocityY, consumed)

    override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float) =
        childHelper.dispatchNestedPreFling(velocityX, velocityY)

}
Vaniavanilla answered 29/9, 2022 at 11:3 Comment(0)
T
1

Try this

WebView mWebView = (WebView) findViewById(R.id.MyWebview);
mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setSupportZoom(true);
mWebView.getSettings().setBuiltInZoomControls(true);
mWebView.getSettings().setUserAgentString("Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3");
Tallou answered 9/1, 2012 at 6:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.