2

Need to reliably detect the left and right swipe on whole NestedScrollView. I tried various options but nothing worked so far! Please refer the code below -

Following is the layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:fitsSystemWindows="false"
    android:orientation="vertical">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:animateLayoutChanges="true">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:contentInsetStartWithNavigation="0dp"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

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

                <TextView
                    android:id="@+id/subtitle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:textAlignment="center"
                    android:textFontWeight="400"
                    android:maxLines="1"
                    android:text="@string/app_name"
                    android:textSize="18sp"
                    tools:ignore="UnusedAttribute" />

            </LinearLayout>

        </androidx.appcompat.widget.Toolbar>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:id="@+id/article"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fadeScrollbars="false"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                app:strokeColor="@null"
                android:id="@+id/coverImage"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:minHeight="350dp"
                android:adjustViewBounds="true"
                android:gravity="center"
                android:scaleType="fitCenter"
                android:src="@mipmap/ic_launcher"
                android:background="@android:color/holo_blue_bright"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                android:contentDescription="@string/app_name" />

            <WebView
                android:id="@+id/webView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layout_constraintTop_toBottomOf="@+id/coverImage"/>

        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

The activity code is as follows

package com.example.nestedswipe

import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.nestedswipe.MainActivity.GestureListener.Companion.SWIPE_THRESHOLD
import com.example.nestedswipe.MainActivity.GestureListener.Companion.SWIPE_VELOCITY_THRESHOLD
import com.example.nestedswipe.databinding.ActivityMainBinding
import kotlin.math.abs

class MainActivity : AppCompatActivity() {

    lateinit var binding: ActivityMainBinding

    @SuppressLint("SetJavaScriptEnabled", "ClickableViewAccessibility")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        val view: View = binding.root
        setContentView(view)

        binding.webView.settings.javaScriptEnabled = true
        binding.webView.loadUrl("https://www.basicwebsiteexample.com/media/")

        val gestureDetector = GestureDetector(this, GestureListener(this))
        binding.article.setOnTouchListener { view, event ->
            Log.d("DEMO", "Article OnTouch")
            gestureDetector.onTouchEvent(event)
        }

        binding.webView.requestDisallowInterceptTouchEvent(true)
        binding.webView.setOnTouchListener { view, event ->
            Log.d("DEMO", "Webview OnTouch")
            gestureDetector.onTouchEvent(event)
        }

    }

    class GestureListener(private var context : Context) : GestureDetector.SimpleOnGestureListener() {
        companion object {
            private const val SWIPE_THRESHOLD = 100
            private const val SWIPE_VELOCITY_THRESHOLD = 100
        }
        override fun onFling(
            e1: MotionEvent,
            e2: MotionEvent,
            velocityX: Float,
            velocityY: Float
        ): Boolean {
            Log.d("DEMO", "onFling")
            var result = false
            try {
                val diffY = e2.y - e1.y
                val diffX = e2.x - e1.x
                if (abs(diffX) > abs(diffY)) {
                    if (abs(diffX) > SWIPE_THRESHOLD && abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        result = if (diffX > 0) {
                            //Toast.makeText(context, "Swipe Right", Toast.LENGTH_SHORT).show()
                            Log.d("DEMO", "Swipe Right")
                            true
                        } else {
                            //Toast.makeText(context, "Swipe Left", Toast.LENGTH_SHORT).show()
                            Log.d("DEMO", "Swipe Left")
                            true
                        }
                    }
                }
            } catch (exception: Exception) {
                exception.printStackTrace()
            }
            return result
        }
    }
}

Build.gradle

    implementation 'androidx.core:core-ktx:1.8.0'
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
    implementation "androidx.constraintlayout:constraintlayout:2.1.4"
    implementation "com.google.android.material:material:1.9.0"

The touch events on Image area are properly detected and swipes are predicted properly. Logcat result is

19:50:44.531  D  Article OnTouch
19:50:44.548  D  Article OnTouch
19:50:44.582  D  Article OnTouch
19:50:44.582  D  onFling
19:50:44.582  D  Swipe Left

However the swipes on the Webview are not reliably detected. Some swipes are detected while other are lost which are proper swipe.

Logcat shows results as below

19:55:54.485  D  Webview OnTouch
19:55:54.530  D  Webview OnTouch
19:55:54.547  D  Webview OnTouch
19:55:54.563  D  Webview OnTouch
19:55:54.579  D  Webview OnTouch
19:55:54.596  D  Article OnTouch
19:55:54.612  D  Article OnTouch
19:55:54.629  D  Article OnTouch
19:55:54.645  D  Article OnTouch
19:55:54.662  D  Article OnTouch
19:55:54.679  D  Article OnTouch
19:55:54.696  D  Article OnTouch
19:55:54.850  D  Article OnTouch
19:55:54.851  D  onFling

I suspect that touch events are getting partially consumed by Webview and Article view. Thus even if Fling is detected, it is partial and thus Swipe event is not recognised.

How to reliably detect the left and right swipe on whole NestedScrollView?

1
  • No reply or comments? So disappointing !! Commented Jun 8, 2023 at 11:48

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.