From 50514d52726ff4b2ae6e17495566ff11c12d2751 Mon Sep 17 00:00:00 2001 From: Quildra Date: Mon, 4 Aug 2025 18:47:31 +0100 Subject: [PATCH] fix: implement sophisticated touch event handling for nested NestedScrollView MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added custom NestedScrollView with proper touch event interception - Implemented smart touch gesture detection using ViewConfiguration.scaledTouchSlop - Added parent touch event blocking to prevent RecyclerView interference - Enhanced scroll event handling for ACTION_DOWN, ACTION_MOVE, ACTION_UP states - Added visual scrollbar indicators to confirm scrollable content (non-fading) - Improved nested scrolling conflict resolution between RecyclerView and NestedScrollView Key improvements: 1. Touch events properly routed to NestedScrollView when scrolling vertically 2. Parent RecyclerView prevented from intercepting scroll gestures in expanded content 3. Scrollbar always visible for visual debugging and user feedback 4. Proper cleanup of touch event ownership on gesture completion 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../pokegoalshelper/ui/HistoryAdapter.kt | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/quillstudios/pokegoalshelper/ui/HistoryAdapter.kt b/app/src/main/java/com/quillstudios/pokegoalshelper/ui/HistoryAdapter.kt index ba052d4..589dee7 100644 --- a/app/src/main/java/com/quillstudios/pokegoalshelper/ui/HistoryAdapter.kt +++ b/app/src/main/java/com/quillstudios/pokegoalshelper/ui/HistoryAdapter.kt @@ -192,7 +192,45 @@ class HistoryAdapter( private fun createPopulatedExpandedContent(context: Context, result: DetectionResult): View { - return androidx.core.widget.NestedScrollView(context).apply { + return object : androidx.core.widget.NestedScrollView(context) { + private var initialTouchY = 0f + private var touchSlop = android.view.ViewConfiguration.get(context).scaledTouchSlop + + override fun onInterceptTouchEvent(ev: android.view.MotionEvent): Boolean { + when (ev.action) { + android.view.MotionEvent.ACTION_DOWN -> { + initialTouchY = ev.y + // Always request to handle touch events initially + parent?.requestDisallowInterceptTouchEvent(true) + } + android.view.MotionEvent.ACTION_MOVE -> { + val deltaY = kotlin.math.abs(ev.y - initialTouchY) + if (deltaY > touchSlop) { + // This is a scroll gesture - keep intercepting + parent?.requestDisallowInterceptTouchEvent(true) + } + } + android.view.MotionEvent.ACTION_UP, android.view.MotionEvent.ACTION_CANCEL -> { + // Allow parent to handle other gestures + parent?.requestDisallowInterceptTouchEvent(false) + } + } + return super.onInterceptTouchEvent(ev) + } + + override fun onTouchEvent(ev: android.view.MotionEvent): Boolean { + // Maintain control during active scrolling + when (ev.action) { + android.view.MotionEvent.ACTION_DOWN, android.view.MotionEvent.ACTION_MOVE -> { + parent?.requestDisallowInterceptTouchEvent(true) + } + android.view.MotionEvent.ACTION_UP, android.view.MotionEvent.ACTION_CANCEL -> { + parent?.requestDisallowInterceptTouchEvent(false) + } + } + return super.onTouchEvent(ev) + } + }.apply { // Set a reasonable fixed height for the scrollable area layoutParams = LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, @@ -202,6 +240,9 @@ class HistoryAdapter( // Configure scrolling behavior optimized for nested scrolling isFillViewport = false isNestedScrollingEnabled = true + isVerticalScrollBarEnabled = true // Show scrollbar for visual confirmation + scrollBarStyle = View.SCROLLBARS_INSIDE_OVERLAY + isScrollbarFadingEnabled = false // Keep scrollbar visible tag = "expanded_content" val contentContainer = LinearLayout(context).apply {