fix(player): 固定评论输入浮层位置避免收键盘跳动
This commit is contained in:
1 parent
e90217bdfd
commit
d2f2459a96
2 files changed
+98
-6
No files matched your search
@@ -20,6 +20,8 @@ const double _sheetRadius = 20;
|
||||
const double _inputRadius = 12;
|
||||
const double _postButtonHeight = 32;
|
||||
const int _maxCommentLength = 300;
|
||||
const Duration _keyboardSettleDelay = Duration(milliseconds: 80);
|
||||
const double _maxKeyboardInsetRatio = 0.6;
|
||||
|
||||
/// 独立评论输入弹窗,复用原评论控制器的发布与列表更新能力。
|
||||
class CommentComposerSheet extends StatefulWidget {
|
||||
@@ -44,11 +46,13 @@ class _CommentComposerSheetState extends State<CommentComposerSheet> {
|
||||
final _input = TextEditingController();
|
||||
final _inputFocus = FocusNode();
|
||||
final _keyboardInset = KeyboardInsetNotifier.instance;
|
||||
Timer? _keyboardSettleTimer;
|
||||
double _pinnedKeyboardInset = 0;
|
||||
int _insetBaseline = 0;
|
||||
bool _pinnedInitialized = false;
|
||||
bool _insetReady = false;
|
||||
bool _useChannelInset = false;
|
||||
bool _keyboardVisible = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -62,9 +66,12 @@ class _CommentComposerSheetState extends State<CommentComposerSheet> {
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
if (_pinnedInitialized) return;
|
||||
_pinnedInitialized = true;
|
||||
_pinnedKeyboardInset = MediaQuery.viewInsetsOf(context).bottom;
|
||||
if (!_pinnedInitialized) {
|
||||
_pinnedInitialized = true;
|
||||
_pinnedKeyboardInset =
|
||||
_normalizeKeyboardInset(MediaQuery.viewInsetsOf(context).bottom) ?? 0;
|
||||
}
|
||||
_trackKeyboardInset(_keyboardHeight(context));
|
||||
}
|
||||
|
||||
Future<void> _prepareInput() async {
|
||||
@@ -89,6 +96,7 @@ class _CommentComposerSheetState extends State<CommentComposerSheet> {
|
||||
_input.removeListener(_onInputChanged);
|
||||
_keyboardInset.removeListener(_onKeyboardInsetChanged);
|
||||
widget.controller.removeListener(_onControllerChanged);
|
||||
_keyboardSettleTimer?.cancel();
|
||||
_inputFocus.unfocus();
|
||||
_input.dispose();
|
||||
_inputFocus.dispose();
|
||||
@@ -108,7 +116,7 @@ class _CommentComposerSheetState extends State<CommentComposerSheet> {
|
||||
if (_keyboardInset.value != _insetBaseline) {
|
||||
_useChannelInset = true;
|
||||
}
|
||||
setState(() {});
|
||||
_trackKeyboardInset(_keyboardHeight(context));
|
||||
}
|
||||
|
||||
double _keyboardHeight(BuildContext context) {
|
||||
@@ -119,6 +127,38 @@ class _CommentComposerSheetState extends State<CommentComposerSheet> {
|
||||
return math.max(viewInset, channelInset);
|
||||
}
|
||||
|
||||
double? _normalizeKeyboardInset(double inset) {
|
||||
final maxInset = MediaQuery.sizeOf(context).height * _maxKeyboardInsetRatio;
|
||||
if (!inset.isFinite || inset > maxInset) return null;
|
||||
return math.max(0, inset).roundToDouble();
|
||||
}
|
||||
|
||||
void _trackKeyboardInset(double inset) {
|
||||
final visible = inset > 0;
|
||||
if (visible == _keyboardVisible) return;
|
||||
_keyboardVisible = visible;
|
||||
_keyboardSettleTimer?.cancel();
|
||||
_keyboardSettleTimer = null;
|
||||
if (!visible) return;
|
||||
_keyboardSettleTimer = Timer(
|
||||
_keyboardSettleDelay,
|
||||
_captureSettledKeyboardInset,
|
||||
);
|
||||
}
|
||||
|
||||
void _captureSettledKeyboardInset() {
|
||||
_keyboardSettleTimer = null;
|
||||
if (!mounted) return;
|
||||
final inset = _keyboardHeight(context);
|
||||
if (inset <= 0) {
|
||||
_keyboardVisible = false;
|
||||
return;
|
||||
}
|
||||
final next = _normalizeKeyboardInset(inset);
|
||||
if (next == null || next == _pinnedKeyboardInset) return;
|
||||
setState(() => _pinnedKeyboardInset = next);
|
||||
}
|
||||
|
||||
Future<void> _submit() async {
|
||||
if (widget.controller.submitting) return;
|
||||
final text = _input.text.trim();
|
||||
@@ -148,8 +188,6 @@ class _CommentComposerSheetState extends State<CommentComposerSheet> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final currentKeyboardInset = _keyboardHeight(context);
|
||||
_pinnedKeyboardInset = math.max(_pinnedKeyboardInset, currentKeyboardInset);
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
final signedIn = context.watch<AuthController>().isSignedIn;
|
||||
final hasContent = _input.text.trim().isNotEmpty;
|
||||
|
||||
Reference in new issue
Block a user