【问题标题】:Horizontally Scrolling WebView Inside ViewPager在 ViewPager 内水平滚动 WebView
【发布时间】:2017-01-26 14:06:35
【问题描述】:

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

我们看到的问题是,当水平滚动时,那些滚动事件(或拖动,或甩动)被 ViewPager 拦截,然后在动作方向提示页面切换。

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

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

  1. 为什么没有像getContentHeight() 那样获取WebView 的HTML 内容的实际内容宽度的方法?这将为我们提供我们需要的东西,但不幸的是,API 中没有提供它。
  2. 有没有人看到实际有效的解决此问题的方法?

【问题讨论】:

  • 这是一个有用的链接。 Extended Webview
  • 谢谢,但该链接在问题中。没有为我工作。下面的答案是。
  • 不客气 :)

标签: android webview android-viewpager


【解决方案1】:

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

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 的滚动状态以确保它处于空闲状态。

您需要将一个属性添加到您的自定义 ViewPager 并使用您正在使用的 ViewPager 实例上的 OnPageChangedListener 进行切换。

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:

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

        }

    })

【讨论】:

【解决方案2】:

ViewPager 是 WebView 的父级。您可以尝试检测 ViewPager 中的滑动动作并将其直接传递给它的孩子。

您可以查看Managing Touch Events 的官方文档,也可以查看this Stack Overflow 讨论。检查接受的答案,更具体地说是 onInterceptTouchEvent() 方法。

这可以给你一些想法。

【讨论】:

  • 不幸的是,这不是我正在寻找的解决方案。这是确定 ViewPager 是否已达到其外部限制。我试图检测动作何时超出 WebView 可见区域的范围,并确定是否还有更多滚动区域(应该消耗动作)或者我们是否已经到达该滚动区域的末尾(动作应该传播到 ViewPager)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-30
相关资源
最近更新 更多