Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NestedScrollView with webView only scrolling NestedScrollView

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

like image 788
Jesper Martensson Avatar asked Nov 28 '17 22:11

Jesper Martensson


People also ask

How do I stop NestedScrollView scrolling?

setnestedscrollingenabled set it to false. try this one add property in recyclerview android:descendantFocusability="blocksDescendants" .

What is the difference between NestedScrollView and ScrollView?

NestedScrollView is just like ScrollView , but it supports acting as both a nested scrolling parent and child on both new and old versions of Android. Nested scrolling is enabled by default.

How to set Nested scroll View in android?

Now go to app -> res -> layout -> activity_main. xml and add the NestedScrollView inside the Android RelativeLayout and inside the NestedScrollView add an Android LinearLayout with orientation as vertical.


1 Answers

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" />
like image 138
Pavel Dolbik Avatar answered Sep 23 '22 02:09

Pavel Dolbik