9

Below is my code to handle the correct behaviour of my apps actionBar/toolbar/tabBar and nestedScrollView with a ViewPager (webView) inside it. The ViewPager is basically a normal webView.

Everything works fine except my ViewPager can't be scrolled vertically. Only the NestedScrollView is being scrolled. I want the same behaviour as the Facebook app, if you scroll the newsfeed (webView) the tabBar moves the toolbar out of vision vertically.

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".ui.activity.FragmentContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >
                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    app:theme="@style/M.Toolbar"
                    app:popupTheme="@style/M.Toolbar.PopupTheme"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    app:layout_scrollFlags="scroll|enterAlways"
                    >
                </android.support.v7.widget.Toolbar>

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabMode="scrollable"
            android:visibility="gone"
            android:background="@color/background"
            app:background="@color/background"
            />

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:background="@android:color/transparent"
        android:fillViewport="true"
        >

    <com.m.ui.util.EdgeScrollViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        android:visibility="visible"
        >

    </com.m.ui.util.EdgeScrollViewPager>

    </android.support.v4.widget.NestedScrollView>

</android.support.design.widget.CoordinatorLayout>

So in order to be able to scroll my viewPager (webView) I added a new class which extends webView:

public class TouchyWebView extends WebView {

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

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

    public TouchyWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event){
        requestDisallowInterceptTouchEvent(true);
        return super.onTouchEvent(event);
    }
}

This solves the problem with the viewPager (webView) which becomes scrollable. BUT, the NestedScrollView becomes static and refuses to scroll the tabBar/toolbar vertically. So I am stuck with either scrolling the webView OR the tabBar-toolbar. How do I make both viewPager(webView) and NestedScrollView (tabBar/toolbar) scrollable at the same time ?

My webView

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">

    <com.m.ui.base.TouchyWebView
        android:id="@+id/web_webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        android:visibility="visible" />

    <LinearLayout
        android:id="@+id/web_loadingview"
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"
        android:layout_gravity="center">

        <ProgressBar
            style="?android:attr/progressBarStyleLarge"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:indeterminate="true"
            android:visibility="visible"
            android:layout_gravity="center"/>
    </LinearLayout>

</FrameLayout>

Regards

Jesper Martensson
  • 1,268
  • 3
  • 18
  • 43

3 Answers3

6

It works for me, add This line to NestedScrollview in XML File.

 android:fillViewport="true"

then set webview height wrap_content.

<WebView
    android:id="@+id/webview"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>
Shahzad Afridi
  • 1,688
  • 19
  • 22
  • That works! I upvoted because that's what I experimented just 30 seconds before reading this, and Android Studio was installing right when I was reading this. Funny! Nice find! Catch is to use `android:layout_height="wrap_content"` with the Webview. – sud007 Oct 25 '18 at 07:07
6

Please, try this code:

class NestedScrollWebView constructor(
        context: Context,
        attrs: AttributeSet): WebView(context, attrs), NestedScrollingChild2 {

    private var lastMotionY = 0
    private var nestedYOffset = 0
    private val scrollOffset = IntArray(2)
    private val scrollConsumed = IntArray(2)
    private val childHelper = NestedScrollingChildHelper(this)

    init {
        isNestedScrollingEnabled = true
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        if (event == null) return false

        val motionEvent = MotionEvent.obtain(event)
        val currentY = event.y.toInt()

        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                nestedYOffset = 0
                lastMotionY = currentY
                startNestedScroll(View.SCROLL_AXIS_VERTICAL)
            }

            MotionEvent.ACTION_MOVE -> {
                var deltaY = lastMotionY - currentY

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

                lastMotionY = currentY - 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]
                    motionEvent.offsetLocation(0f, scrollOffset[1].toFloat())
                    nestedYOffset += scrollOffset[1]
                }

                motionEvent.recycle()
            }

            MotionEvent.ACTION_POINTER_DOWN,
            MotionEvent.ACTION_UP,
            MotionEvent.ACTION_CANCEL -> stopNestedScroll()

            else -> { }
        }

        return super.onTouchEvent(event)
    }

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

    override fun stopNestedScroll(type: Int) = childHelper.stopNestedScroll(type)

    override fun hasNestedScrollingParent(type: Int) = childHelper.hasNestedScrollingParent(type)

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

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

}

and in the layout leave only WebView:

<com.widget.NestedScrollWebView
    android:id="@+id/webview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />
jayeshsolanki93
  • 2,041
  • 1
  • 17
  • 37
Pavel Dolbik
  • 449
  • 5
  • 8
0

I had a similar problem and solved it with setFillViewport (true) A piece of my code

 NestedScrollView scrollView = (NestedScrollView) findViewById (R.id.nest_scrollview);
    scrollView.setFillViewport (true);

And inside the fragment I had a listView where I sat android:nestedScrollingEnabled="true" .. Fixed the scrolling issue

Rainmaker
  • 7,673
  • 4
  • 38
  • 63