From a444290b2a446306782d8715f0feb146f3abf91f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=E1=BA=A7n=20=C4=90=E1=BA=A1i=20Hi=E1=BB=87p?= Date: Sat, 28 Feb 2026 09:29:47 +0700 Subject: [PATCH 1/3] WheelPicker stops between two items when fling is interrupted by touch --- .../java/com/aigestudio/wheelpicker/WheelPicker.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/WheelPicker/src/main/java/com/aigestudio/wheelpicker/WheelPicker.kt b/WheelPicker/src/main/java/com/aigestudio/wheelpicker/WheelPicker.kt index 3bd3a12..5d9786a 100644 --- a/WheelPicker/src/main/java/com/aigestudio/wheelpicker/WheelPicker.kt +++ b/WheelPicker/src/main/java/com/aigestudio/wheelpicker/WheelPicker.kt @@ -782,8 +782,20 @@ open class WheelPicker @JvmOverloads constructor( if (!scroller.isFinished) { scroller.abortAnimation() isForceFinishScroll = true + + // ✅ FIX: Snap về ô gần nhất ngay khi tay ấn vào lúc đang xoay + val remainder = scrollOffsetY.rem(itemHeight) + val snapOffset = computeDistanceToEndPoint(remainder) + if (snapOffset != 0) { + scrollOffsetY += snapOffset + // Clamp trong giới hạn nếu không cyclic + if (!isCyclic) { + scrollOffsetY = scrollOffsetY.coerceIn(minFlingY, maxFlingY) + } + invalidate() + } } - isScrolling = false // 任何按下操作都意味着之前的自动滚动必须结束(如果还在滚的话) + isScrolling = false lastPointY = event.y.toInt() downPointY = lastPointY } From 44df92a4404bf13296064a3598a5a971b50987fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=E1=BA=A7n=20=C4=90=E1=BA=A1i=20Hi=E1=BB=87p?= Date: Sat, 28 Feb 2026 09:49:16 +0700 Subject: [PATCH 2/3] WheelPicker stops between two items when fling is interrupted by touch --- .../src/main/java/com/aigestudio/wheelpicker/WheelPicker.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WheelPicker/src/main/java/com/aigestudio/wheelpicker/WheelPicker.kt b/WheelPicker/src/main/java/com/aigestudio/wheelpicker/WheelPicker.kt index 5d9786a..b34523e 100644 --- a/WheelPicker/src/main/java/com/aigestudio/wheelpicker/WheelPicker.kt +++ b/WheelPicker/src/main/java/com/aigestudio/wheelpicker/WheelPicker.kt @@ -783,12 +783,12 @@ open class WheelPicker @JvmOverloads constructor( scroller.abortAnimation() isForceFinishScroll = true - // ✅ FIX: Snap về ô gần nhất ngay khi tay ấn vào lúc đang xoay + // FIXED: Captures the nearest square immediately when your finger presses while rotating. val remainder = scrollOffsetY.rem(itemHeight) val snapOffset = computeDistanceToEndPoint(remainder) if (snapOffset != 0) { scrollOffsetY += snapOffset - // Clamp trong giới hạn nếu không cyclic + // Clamp within limits if not cyclic if (!isCyclic) { scrollOffsetY = scrollOffsetY.coerceIn(minFlingY, maxFlingY) } From e41220104cba1728dc01e0323f60770600c1fd5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=E1=BA=A7n=20=C4=90=E1=BA=A1i=20Hi=E1=BB=87p?= Date: Sat, 28 Feb 2026 10:32:24 +0700 Subject: [PATCH 3/3] position and fire callback --- .../com/aigestudio/wheelpicker/WheelPicker.kt | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/WheelPicker/src/main/java/com/aigestudio/wheelpicker/WheelPicker.kt b/WheelPicker/src/main/java/com/aigestudio/wheelpicker/WheelPicker.kt index b34523e..602854e 100644 --- a/WheelPicker/src/main/java/com/aigestudio/wheelpicker/WheelPicker.kt +++ b/WheelPicker/src/main/java/com/aigestudio/wheelpicker/WheelPicker.kt @@ -777,12 +777,12 @@ open class WheelPicker @JvmOverloads constructor( tracker?.addMovement(event) when (event.action) { - MotionEvent.ACTION_DOWN -> { + MMotionEvent.ACTION_DOWN -> { parent?.requestDisallowInterceptTouchEvent(true) if (!scroller.isFinished) { scroller.abortAnimation() isForceFinishScroll = true - + // FIXED: Captures the nearest square immediately when your finger presses while rotating. val remainder = scrollOffsetY.rem(itemHeight) val snapOffset = computeDistanceToEndPoint(remainder) @@ -794,6 +794,20 @@ open class WheelPicker @JvmOverloads constructor( } invalidate() } + + // Calculate position and call fire again — copy logic from CalculateScroll() + val size = data?.size ?: 0 + if (size > 0) { + var position = (-scrollOffsetY / itemHeight + selectedItemPosition) % size + position = if (position < 0) position + size else position + + currentItemPosition = position + onItemSelectedListener?.onItemSelected(this, data!![position], position) + onWheelChangeListener?.onWheelSelected(position) + onWheelChangeListener?.onWheelScrollStateChanged(SCROLL_STATE_IDLE) + } + + invalidate() } isScrolling = false lastPointY = event.y.toInt()