From da78a80e6a88f3585d1594bdc209a7b2697705a1 Mon Sep 17 00:00:00 2001 From: wm Date: Mon, 13 Jul 2026 11:51:53 +0800 Subject: [PATCH] =?UTF-8?q?fix(gesture):=20=E4=BF=AE=E5=A4=8D=E9=B8=BF?= =?UTF-8?q?=E8=92=99=E4=B8=8B=E6=A8=AA=E6=BB=91=E5=88=87=E6=8D=A2=E7=AE=80?= =?UTF-8?q?=E4=BB=8B/=E8=AF=84=E8=AE=BA=E5=8C=BA=E9=9A=BE=E4=BB=A5?= =?UTF-8?q?=E8=A7=A6=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因:鸿蒙 embedding(`FlutterPage`)将 ArkUI PanGesture 默认的 5(vp) 作为 `physicalTouchSlop` 经 viewport metrics 下发,框架除以 DPR 后竖向滚动触发阈值仅约 1.5 逻辑像素(Android 约为 8)。竖向手势几乎瞬间赢得手势竞技场,横向手势(阈值 18~24)只有约 5° 以内的近乎纯水平滑动才能触发,单纯放宽横向判定无效。 - `main.dart`:鸿蒙下全局覆盖 MediaQuery `gestureSettings`,将竖向 touchSlop 恢复为 Android 水平的 8 逻辑像素 - `touchSlopH` 默认值 24→12:与竖向 8 形成约 34° 的主导方向分界(已自定义过该设置的用户不受默认值影响) - 横向方向判定由 `dx > 3·dy` 放宽为 `dx > dy` --- .../horizontal_drag_gesture_recognizer.dart | 4 +++- lib/main.dart | 15 ++++++++++++++- lib/utils/storage_pref.dart | 4 +++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/common/widgets/gesture/horizontal_drag_gesture_recognizer.dart b/lib/common/widgets/gesture/horizontal_drag_gesture_recognizer.dart index c04b8f9624..040feb8a8e 100644 --- a/lib/common/widgets/gesture/horizontal_drag_gesture_recognizer.dart +++ b/lib/common/widgets/gesture/horizontal_drag_gesture_recognizer.dart @@ -62,5 +62,7 @@ bool _computeHitSlop( bool _calc(Offset initialPosition, Offset lastPosition) { final offset = lastPosition - initialPosition; - return offset.dx.abs() > offset.dy.abs() * 3; + // 判定:只要水平位移 > 垂直位移即算横滑(原为 dx > 3·dy,过于苛刻)。 + // 约 45° 以内的滑动都会被判定为横向,让简介/评论区左右切换更容易触发。 + return offset.dx.abs() > offset.dy.abs(); } diff --git a/lib/main.dart b/lib/main.dart index 482e899fde..57f6b96fd0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -30,6 +30,7 @@ import 'package:PiliPlus/utils/utils.dart'; import 'package:catcher_2/catcher_2.dart'; import 'package:dynamic_color/dynamic_color.dart'; import 'package:flutter/foundation.dart'; +import 'package:flutter/gestures.dart' show DeviceGestureSettings; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart'; @@ -325,6 +326,14 @@ class MyApp extends StatelessWidget { final uiScale = ScaledWidgetsFlutterBinding.instance.scaleFactor; final mediaQuery = MediaQuery.of(context); final textScaler = TextScaler.linear(Pref.defaultTextScale); + // 鸿蒙 embedding(FlutterPage/FlutterView)把 ArkUI PanGesture 默认的 + // 5(vp) 当 physicalTouchSlop 下发,框架除以 DPR 后竖向滚动的触发阈值 + // 只有 ~1.5 逻辑像素(Android 约为 8)。竖向手势几乎瞬间赢得竞技场, + // 横向滑动(如简介/评论切换)无论怎么放宽都抢不到。此处恢复为 + // Android 水平,使横竖手势能按主导方向公平竞争。 + final gestureSettings = OS.isHarmony + ? const DeviceGestureSettings(touchSlop: 8) + : mediaQuery.gestureSettings; if (uiScale != 1.0) { child = MediaQuery( data: mediaQuery.copyWith( @@ -334,12 +343,16 @@ class MyApp extends StatelessWidget { viewInsets: mediaQuery.viewInsets / uiScale, viewPadding: mediaQuery.viewPadding / uiScale, devicePixelRatio: mediaQuery.devicePixelRatio * uiScale, + gestureSettings: gestureSettings, ), child: child!, ); } else { child = MediaQuery( - data: mediaQuery.copyWith(textScaler: textScaler), + data: mediaQuery.copyWith( + textScaler: textScaler, + gestureSettings: gestureSettings, + ), child: child!, ); } diff --git a/lib/utils/storage_pref.dart b/lib/utils/storage_pref.dart index afc28cc50f..5da8886379 100644 --- a/lib/utils/storage_pref.dart +++ b/lib/utils/storage_pref.dart @@ -967,8 +967,10 @@ abstract final class Pref { static bool get showDynDispute => _setting.get(SettingBoxKey.showDynDispute, defaultValue: false); + // 竖向滚动 slop 已在 main._builder 统一为 8 逻辑像素(鸿蒙),横向取 12 + // 时约 34° 以内的滑动可赢得竞技场,横竖手势按主导方向竞争。 static double get touchSlopH => - _setting.get(SettingBoxKey.touchSlopH, defaultValue: 24.0); + _setting.get(SettingBoxKey.touchSlopH, defaultValue: 12.0); static bool get saveReply => _setting.get(SettingBoxKey.saveReply, defaultValue: true);