2017-01-26 17 views
14

この問題ではfew questionsaskedがありましたが、私たちのために働いている真の解決策は何もありませんでした。 ViewPagerには、水平方向にスクロールする必要がある動的なWebビュー(フラグメント内)が含まれています。横方向にスクロールするWebView ViewPager内

私たちが見ている問題は、水平方向にスクロールすると、ViewPagerでこれらのスクロールイベント(またはドラッグまたはフリンジ)がインターセプトされ、アクションの方向にページ切り替えを促すということです。

WebViewは、そのコンテンツの幅を親に報告していないか、ViewPagerがアクションを無差別に取り込んでいます。

私はcomputeHorizo​​ntalScroll()ソリューションを使用しようとしましたが有望でしたが、そのメソッドは常に0を返しています。

  1. getContentHeight()のようにWebViewのHTMLコンテンツの実際のコンテンツ幅を取得する方法がないのはなぜですか?これは私たちに必要なものを与えますが、残念ながらAPIでは提供されていません。
  2. 実際にこの問題の回避策を見た人は誰ですか?
+0

ここでは、便利なリンクです。 [Extended Webview](https://stackoverflow.com/questions/7774642/scroll-webview-horizo​​ntally-inside-a-viewpager) –

+0

ありがとうございますが、そのリンクは問題です。私のために働かなかった。答えは以下の通りでした。 – airowe

+0

あなたは大歓迎です:) –

答えて

3

私は、WebViewのoverScrollByイベントがトリガーされたときに、ViewPagerへのタッチイベントの伝播を禁止し、ページをスクロールすることによって解決策を開発しました。イベントのデルタXをチェックすることで、スクロールする方向を決定することができます。ここで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) { 

     } 

    }) 
+0

ここに、このソリューションのいくつかの更新点があります。それが役に立てば幸い! https://gist.github.com/airowe/fb5c59f94fdfb5f1eb0b776a398a68f3 – airowe

2

ViewPagerはWebViewの親です。 ViewPagerでスワイプモーションを検出して、その子に直接渡すことができます。

Managing Touch Eventsの公式ドキュメントを確認して、thisスタックオーバーフローの説明を確認できます。受け入れられた回答、具体的にはonInterceptTouchEvent()メソッドを確認してください。

これはあなたにいくつかのアイデアを与えることができます。

+0

残念ながら、これは私が探している解決策ではありません。これは、ViewPagerがその外側限界に達したかどうかを判断しています。私は、アクションがWebViewの可視領域の境界を越えたときを検出し、さらにスクロール領域があるかどうか(アクションが消費されるべきかどうか)、またはスクロール領域の終わりに達したかどうかを判断しようとしていますViewPagerまで伝播する必要があります)。 – airowe

関連する問題