在 ViewPager 中水平滚动 WebView [英] Horizontally Scrolling WebView Inside ViewPager

查看:20
本文介绍了在 ViewPager 中水平滚动 WebView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个一些问题 询问 这个问题,但没有人给出真正适合我们的解决方案.我们有一个 ViewPager 包含动态数量的 webviews(在片段内),有时需要水平滚动.

There have been a few questions asked on this issue, but none have given a true solution that is working for us. We have a ViewPager containing a dynamic number of webviews (inside fragments) that will sometimes need to be scrolled horizontally.

我们看到的问题是,当水平滚动时,那些滚动事件(或拖动,或投掷)被 ViewPager 拦截,然后它会提示在动作方向上进行页面切换.

The problem we're seeing is that when scrolling horizontally, those scroll events (or drag, or fling) are being intercepted by the ViewPager, which then prompts a page switch in the direction of the action.

WebView 要么没有向其父级报告其内容的宽度,要么 ViewPager 在它应该之前不加选择地捕获操作.

The WebView is either not reporting the width of its content to its parent, or the ViewPager is indiscriminately capturing the actions before it should.

我尝试使用 computeHorizo​​ntalScroll() 解决方案,这似乎很有希望,但该方法总是返回 0,对我没有好处.

I tried using the computeHorizontalScroll() solutions, which seemed promising, but that method is always returning 0 and does me no good.

  1. 为什么没有一种方法可以像 getContentHeight()?这将为我们提供我们需要的东西,但遗憾的是 API 中没有提供.
  2. 有没有人看到过针对此问题的实际可行的解决方法?
  1. Why is there not a method to get the actual content width of the WebView's HTML content like there is with getContentHeight()? This would give us what we need, but unfortunately it's not provided in the API.
  2. Has anyone seen a workaround for this issue that actually works?

推荐答案

因此,我最终开发了一个解决方案,即在触发 WebView 的 overScrollBy 事件时禁止将触摸事件传播到 ViewPager 和滚动页面.您可以通过检查事件的 deltaX 来确定要滚动的方向.这是一个 kotlin 解决方案:

So, I ended up developing a solution by disallowing propagation of touch events to the ViewPager and scrolling pages when the overScrollBy event of the WebView is triggered. You can determine the direction you want to scroll in by checking the deltaX of the event. Here's a kotlin solution:

override fun overScrollBy(deltaX: Int, deltaY: Int, scrollX: Int, scrollY: Int, scrollRangeX: Int, scrollRangeY: Int, maxOverScrollX: Int, maxOverScrollY: Int, isTouchEvent: Boolean): Boolean {
    if(parent.parent is WebViewPager) {
        val viewPager: WebViewPager = (parent.parent as WebViewPager)
        if(viewPager.scrollState == ViewPager.SCROLL_STATE_IDLE) {
            if(deltaX > 0) {
                if(checkAdapterLimits(1, viewPager.currentItem)) //right
                    (parent.parent as ViewPager).setCurrentItem(viewPager.currentItem + 1,true)
            }
            else {
                if(checkAdapterLimits(-1, viewPager.currentItem)) //left
                    (parent.parent as ViewPager).setCurrentItem(viewPager.currentItem - 1,true)
            }
        }
    }
    return false
}

override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
    parent.requestDisallowInterceptTouchEvent(true)

    return super.onInterceptTouchEvent(event)
}

private fun checkAdapterLimits(direction: Int, position: Int) : Boolean {
    return if(direction < 0) //left
        position >= 1
    else //right
        position < (parent.parent as ViewPager).adapter.count - 1

}

已编辑,为了一次停止滚动到一页,您需要检查 ViewPager 的滚动状态以确保它处于空闲状态.

Edited, in order to stop scrolling to just one page at a time, you need to check the scroll state of the ViewPager to make sure it's idle.

您需要向自定义 ViewPager 添加一个属性,并使用您正在使用的 ViewPager 实例上的 OnPageChangedListener 切换它.

You'll need to add a property to your custom ViewPager and toggle it with an OnPageChangedListener on the ViewPager instance you're using.

ViewPager:

class WebViewPager(context: Context, attrs: AttributeSet) : ViewPager(context, attrs) {

var scrollState: Int = SCROLL_STATE_IDLE

fun setDurationScroll(millis: Int) {
    try {
        val viewpager = ViewPager::class.java
        val scroller = viewpager.getDeclaredField("mScroller")
        scroller.isAccessible = true
        scroller.set(this, OwnScroller(context, millis))
    } catch (e: Exception) {
        e.printStackTrace()
    }

}

inner class OwnScroller(context: Context, durationScroll: Int) : Scroller(context, DecelerateInterpolator()) {

    private var durationScrollMillis = 1

    init {
        this.durationScrollMillis = durationScroll
    }

    override fun startScroll(startX: Int, startY: Int, dx: Int, dy: Int, duration: Int) {
        super.startScroll(startX, startY, dx, dy, durationScrollMillis)
    }
}

}

OnPageChangedListener:

OnPageChangedListener:

viewPager!!.setDurationScroll(300)
    viewPager!!.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {

        override fun onPageScrollStateChanged(state: Int) {
            viewPager.scrollState = state
        }

        override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {

        }
        override fun onPageSelected(position: Int) {

        }

    })

这篇关于在 ViewPager 中水平滚动 WebView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆