From 4af12ef9ca1ac022845a8afbd088df8539ecb063 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 25 Aug 2025 01:33:35 +0000 Subject: [PATCH 1/4] Initial plan From d93998be8c1957f43ab68af55aa95d389bd1d9a1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 25 Aug 2025 01:40:03 +0000 Subject: [PATCH 2/4] Add LongPressMove display mode implementation Co-authored-by: Petterpx <41142188+Petterpx@users.noreply.github.com> --- .../floatingx/app/test/ScopeActivity.kt | 3 ++ .../floatingx/app/test/SimpleRvActivity.kt | 6 ++++ .../petterp/floatingx/assist/FxDisplayMode.kt | 8 ++++- .../view/helper/FxViewTouchHelper.kt | 32 ++++++++++++++++--- 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/petterp/floatingx/app/test/ScopeActivity.kt b/app/src/main/java/com/petterp/floatingx/app/test/ScopeActivity.kt index e18c01cb..b8506942 100644 --- a/app/src/main/java/com/petterp/floatingx/app/test/ScopeActivity.kt +++ b/app/src/main/java/com/petterp/floatingx/app/test/ScopeActivity.kt @@ -85,6 +85,9 @@ class ScopeActivity : AppCompatActivity() { addItemView("允许触摸事件(允许拖动)-默认允许") { scopeFx.configControl.setDisplayMode(FxDisplayMode.Normal) } + addItemView("长按移动模式(解决内容滑动冲突)") { + scopeFx.configControl.setDisplayMode(FxDisplayMode.LongPressMove) + } addItemView("隐藏悬浮窗") { scopeFx.hide() } diff --git a/app/src/main/java/com/petterp/floatingx/app/test/SimpleRvActivity.kt b/app/src/main/java/com/petterp/floatingx/app/test/SimpleRvActivity.kt index d4b741bc..47efeced 100644 --- a/app/src/main/java/com/petterp/floatingx/app/test/SimpleRvActivity.kt +++ b/app/src/main/java/com/petterp/floatingx/app/test/SimpleRvActivity.kt @@ -70,6 +70,12 @@ class SimpleRvActivity : AppCompatActivity() { if (customAdapter.sum < 0) customAdapter.sum = 1 customAdapter.notifyDataSetChanged() } + addItemView("设置长按移动模式") { + FloatingX.controlOrNull(TAG)?.configControl?.setDisplayMode(FxDisplayMode.LongPressMove) + } + addItemView("设置普通移动模式") { + FloatingX.controlOrNull(TAG)?.configControl?.setDisplayMode(FxDisplayMode.Normal) + } } } } diff --git a/floatingx/src/main/java/com/petterp/floatingx/assist/FxDisplayMode.kt b/floatingx/src/main/java/com/petterp/floatingx/assist/FxDisplayMode.kt index 4c9f28cb..48f4be37 100644 --- a/floatingx/src/main/java/com/petterp/floatingx/assist/FxDisplayMode.kt +++ b/floatingx/src/main/java/com/petterp/floatingx/assist/FxDisplayMode.kt @@ -12,8 +12,14 @@ enum class FxDisplayMode { ClickOnly, // 展示模式:只用于展示,不响应任何事件不能移动 - DisplayOnly; + DisplayOnly, + + // 长按移动模式:长按后可移动,解决内容滑动冲突 + LongPressMove; val canMove: Boolean get() = this == Normal + + val canLongPressMove: Boolean + get() = this == LongPressMove } diff --git a/floatingx/src/main/java/com/petterp/floatingx/view/helper/FxViewTouchHelper.kt b/floatingx/src/main/java/com/petterp/floatingx/view/helper/FxViewTouchHelper.kt index ea1b48e0..14955de5 100644 --- a/floatingx/src/main/java/com/petterp/floatingx/view/helper/FxViewTouchHelper.kt +++ b/floatingx/src/main/java/com/petterp/floatingx/view/helper/FxViewTouchHelper.kt @@ -24,6 +24,7 @@ class FxViewTouchHelper : FxViewBasicHelper() { private var isEnableClick = true private var mLastTouchDownTime = 0L private var touchDownId = INVALID_TOUCH_ID + private var isLongPressActivated = false @SuppressLint("ClickableViewAccessibility") override fun initConfig(parentView: FxBasicContainerView) { @@ -57,7 +58,12 @@ class FxViewTouchHelper : FxViewBasicHelper() { MotionEvent.ACTION_MOVE -> { if (!isCurrentPointerId(event)) return false - return config.displayMode.canMove && canInterceptEvent(event) + // 长按移动模式:只有在长按激活后才拦截移动事件 + return if (config.displayMode.canLongPressMove) { + isLongPressActivated && canInterceptEvent(event) + } else { + config.displayMode.canMove && canInterceptEvent(event) + } } MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { @@ -105,8 +111,23 @@ class FxViewTouchHelper : FxViewBasicHelper() { private fun touchToMove(event: MotionEvent) { if (!isCurrentPointerId(event)) return checkClickState(event) + // Check if movement is allowed + val canMoveNow = if (config.displayMode.canLongPressMove) { + // For long press move mode, check if long press is activated and enough time has passed + val timeSinceDown = System.currentTimeMillis() - mLastTouchDownTime + if (timeSinceDown >= TOUCH_CLICK_LONG_TIME && !isLongPressActivated) { + isLongPressActivated = true + // Trigger haptic feedback for long press + basicView?.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) + config.fxLog.d("fxView -> long press activated for movement") + } + isLongPressActivated + } else { + config.displayMode.canMove + } + // 不支持move时return掉 - if (!config.displayMode.canMove) return + if (!canMoveNow) return basicView?.onTouchMove(event) val x = basicView?.x ?: 0f val y = basicView?.y ?: 0f @@ -115,7 +136,8 @@ class FxViewTouchHelper : FxViewBasicHelper() { } private fun touchCancel(event: MotionEvent) { - if (config.enableEdgeAdsorption && config.displayMode.canMove) basicView?.moveToEdge() + val canMoveForEdge = config.displayMode.canMove || (config.displayMode.canLongPressMove && isLongPressActivated) + if (config.enableEdgeAdsorption && canMoveForEdge) basicView?.moveToEdge() basicView?.onTouchCancel(event) config.iFxTouchListener?.onUp() performClickAction() @@ -131,7 +153,8 @@ class FxViewTouchHelper : FxViewBasicHelper() { basicView?.postDelayed({ isEnableClick = true }, config.clickTime) } config.iFxClickListener?.onClick(basicView) - } else if (diffTime >= TOUCH_CLICK_LONG_TIME) { + } else if (diffTime >= TOUCH_CLICK_LONG_TIME && !config.displayMode.canLongPressMove) { + // Only trigger long click listener if not in long press move mode (to avoid conflicts) val isHandle = config.iFxLongClickListener?.onLongClick(basicView) ?: false if (isHandle) basicView?.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) } @@ -156,6 +179,7 @@ class FxViewTouchHelper : FxViewBasicHelper() { isClickEvent = false mLastTouchDownTime = 0L touchDownId = INVALID_TOUCH_ID + isLongPressActivated = false } private fun hasMainPointerId() = touchDownId != INVALID_TOUCH_ID From 15db378e11934cd48b82c6e28d4713cc8086e849 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 27 Aug 2025 00:51:27 +0000 Subject: [PATCH 3/4] Improve LongPressMove mode to handle child view click events properly Co-authored-by: Petterpx <41142188+Petterpx@users.noreply.github.com> --- .../floatingx/app/test/ScopeActivity.kt | 15 ++++ .../floatingx/app/test/SimpleRvActivity.kt | 6 ++ .../res/layout/item_floating_clickable.xml | 41 ++++++++++ .../view/helper/FxViewTouchHelper.kt | 78 ++++++++++++++++++- 4 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 app/src/main/res/layout/item_floating_clickable.xml diff --git a/app/src/main/java/com/petterp/floatingx/app/test/ScopeActivity.kt b/app/src/main/java/com/petterp/floatingx/app/test/ScopeActivity.kt index b8506942..b782f484 100644 --- a/app/src/main/java/com/petterp/floatingx/app/test/ScopeActivity.kt +++ b/app/src/main/java/com/petterp/floatingx/app/test/ScopeActivity.kt @@ -88,6 +88,21 @@ class ScopeActivity : AppCompatActivity() { addItemView("长按移动模式(解决内容滑动冲突)") { scopeFx.configControl.setDisplayMode(FxDisplayMode.LongPressMove) } + addItemView("测试长按移动模式 - 带可点击子视图") { + scopeFx.configControl.setDisplayMode(FxDisplayMode.LongPressMove) + scopeFx.updateView(R.layout.item_floating_clickable) + // Add click listeners to test immediate response + scopeFx.setViewLifecycle(object : com.petterp.floatingx.listener.IFxViewLifecycle { + override fun initView(holder: com.petterp.floatingx.view.FxViewHolder) { + holder.getView(R.id.btnClickMe)?.setOnClickListener { + Toast.makeText(this@ScopeActivity, "Button clicked immediately!", Toast.LENGTH_SHORT).show() + } + holder.getView(R.id.tvClickable)?.setOnClickListener { + Toast.makeText(this@ScopeActivity, "Clickable text clicked!", Toast.LENGTH_SHORT).show() + } + } + }) + } addItemView("隐藏悬浮窗") { scopeFx.hide() } diff --git a/app/src/main/java/com/petterp/floatingx/app/test/SimpleRvActivity.kt b/app/src/main/java/com/petterp/floatingx/app/test/SimpleRvActivity.kt index 47efeced..8f44e3a7 100644 --- a/app/src/main/java/com/petterp/floatingx/app/test/SimpleRvActivity.kt +++ b/app/src/main/java/com/petterp/floatingx/app/test/SimpleRvActivity.kt @@ -72,6 +72,7 @@ class SimpleRvActivity : AppCompatActivity() { } addItemView("设置长按移动模式") { FloatingX.controlOrNull(TAG)?.configControl?.setDisplayMode(FxDisplayMode.LongPressMove) + Toast.makeText(this@SimpleRvActivity, "长按移动模式:点击Header或RV即时响应,长按空白区域移动", Toast.LENGTH_LONG).show() } addItemView("设置普通移动模式") { FloatingX.controlOrNull(TAG)?.configControl?.setDisplayMode(FxDisplayMode.Normal) @@ -103,6 +104,11 @@ class SimpleRvActivity : AppCompatActivity() { 500, 200, ) + // Make header clickable to test immediate response in LongPressMove mode + isClickable = true + setOnClickListener { + Toast.makeText(context, "Header clicked immediately!", Toast.LENGTH_SHORT).show() + } } val rv = RecyclerView(context).apply { layoutParams = ViewGroup.LayoutParams( diff --git a/app/src/main/res/layout/item_floating_clickable.xml b/app/src/main/res/layout/item_floating_clickable.xml new file mode 100644 index 00000000..5e1a7472 --- /dev/null +++ b/app/src/main/res/layout/item_floating_clickable.xml @@ -0,0 +1,41 @@ + + + + +