fix(player): 评论面板保持高度并两段式收起

This commit is contained in:
Zhou Weidong committed 2026-10-21 13:04:29 +08:00
1 parent 9876772d06
commit d081cff3e4
3 files changed
+83 -6

No files matched your search

+2
View File
@@ -810,6 +810,8 @@ class PlayerLogic extends ChangeNotifier {
isScrollControlled: true, isScrollControlled: true,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
showDragHandle: false, showDragHandle: false,
isDismissible: false,
enableDrag: false,
builder: (_) => DramaCommentsSheet(drama: drama), builder: (_) => DramaCommentsSheet(drama: drama),
); );
} finally { } finally {
@@ -178,6 +178,14 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
).showSnackBar(SnackBar(content: Text(message))); ).showSnackBar(SnackBar(content: Text(message)));
} }
void _handleDismissLayerTap() {
if (_inputFocus.hasFocus || _keyboardHeight(context) > 0) {
_inputFocus.unfocus();
return;
}
Navigator.pop(context);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final screenLimit = MediaQuery.sizeOf(context).height - 24; final screenLimit = MediaQuery.sizeOf(context).height - 24;
@@ -194,13 +202,25 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
availableHeight, availableHeight,
); );
_measureSheetWithoutKeyboard(keyboardHeight); _measureSheetWithoutKeyboard(keyboardHeight);
return AnimatedPadding( return Stack(
fit: StackFit.expand,
children: [
Positioned.fill(
child: GestureDetector(
key: const Key('player-comments-dismiss-layer'),
behavior: HitTestBehavior.opaque,
onTap: _handleDismissLayerTap,
),
),
Align(
alignment: Alignment.bottomCenter,
child: AnimatedPadding(
duration: const Duration(milliseconds: 200), duration: const Duration(milliseconds: 200),
curve: Curves.easeOut, curve: Curves.easeOut,
padding: EdgeInsets.only(bottom: keyboardHeight), padding: EdgeInsets.only(bottom: keyboardHeight),
child: GestureDetector( child: GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.opaque,
onTap: inputFocused ? _inputFocus.unfocus : null, onTap: () {},
child: SizedBox( child: SizedBox(
key: _sheetMeasureKey, key: _sheetMeasureKey,
child: Container( child: Container(
@@ -228,13 +248,17 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
child: ConstrainedBox( child: ConstrainedBox(
key: const Key('comment-sheet-constraints'), key: const Key('comment-sheet-constraints'),
constraints: keyboardOpen constraints: keyboardOpen
? BoxConstraints.tightFor(height: keyboardPanelHeight) ? BoxConstraints.tightFor(
height: keyboardPanelHeight,
)
: BoxConstraints( : BoxConstraints(
minHeight: minHeight, minHeight: minHeight,
maxHeight: maxHeight, maxHeight: maxHeight,
), ),
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16), padding: const EdgeInsets.symmetric(
horizontal: 16,
),
child: _content( child: _content(
context, context,
expanded: expanded, expanded: expanded,
@@ -249,6 +273,9 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
), ),
), ),
), ),
),
),
],
); );
} }
@@ -509,7 +536,6 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
focused: focused, focused: focused,
), ),
onTap: signedIn ? null : _authenticateForComment, onTap: signedIn ? null : _authenticateForComment,
onTapOutside: (_) => _inputFocus.unfocus(),
onSubmitted: focused ? null : (_) => _post(), onSubmitted: focused ? null : (_) => _post(),
), ),
), ),
@@ -307,12 +307,14 @@ void main() {
final sheet = find.byKey(const Key('player-comments-sheet')); final sheet = find.byKey(const Key('player-comments-sheet'));
final list = find.byKey(const Key('comment-list')); final list = find.byKey(const Key('comment-list'));
final heightBeforeKeyboard = tester.getSize(sheet).height;
tester.view.viewInsets = const FakeViewPadding(bottom: 180); tester.view.viewInsets = const FakeViewPadding(bottom: 180);
await tester.pump(); await tester.pump();
await tester.pump(const Duration(milliseconds: 200)); await tester.pump(const Duration(milliseconds: 200));
expect(sheet, findsOneWidget); expect(sheet, findsOneWidget);
expect(list, findsOneWidget); expect(list, findsOneWidget);
expect(tester.getSize(sheet).height, closeTo(heightBeforeKeyboard, 0.1));
expect(find.byKey(const Key('comment-count-label')), findsOneWidget); expect(find.byKey(const Key('comment-count-label')), findsOneWidget);
final field = tester.widget<TextField>( final field = tester.widget<TextField>(
find.byKey(const Key('comment-input')), find.byKey(const Key('comment-input')),
@@ -378,6 +380,7 @@ void main() {
); );
expect(collapsedField.maxLines, 1); expect(collapsedField.maxLines, 1);
expect(tester.getSize(find.byKey(const Key('comment-input'))).height, 44); expect(tester.getSize(find.byKey(const Key('comment-input'))).height, 44);
expect(tester.getSize(sheet).height, closeTo(heightBeforeKeyboard, 0.1));
expect(tester.getSize(sheet).height, lessThan(520)); expect(tester.getSize(sheet).height, lessThan(520));
final editableAfterKeyboard = tester.state<EditableTextState>( final editableAfterKeyboard = tester.state<EditableTextState>(
find.descendant( find.descendant(
@@ -402,6 +405,52 @@ void main() {
); );
}); });
testWidgets('should_dismiss_from_outside_in_two_steps', (tester) async {
tester.view.physicalSize = const Size(390, 844);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
addTearDown(tester.view.resetViewInsets);
final repository = FakeCommentRepository(
pages: [
CommentPage(
comments: [commentFixture(id: '10', content: 'A comment')],
),
],
);
await _pumpSheet(tester, repository: repository);
final sheet = find.byKey(const Key('player-comments-sheet'));
final input = find.byKey(const Key('comment-input'));
expect(
find.byKey(const Key('player-comments-dismiss-layer')),
findsOneWidget,
);
tester.view.viewInsets = const FakeViewPadding(bottom: 180);
await tester.tap(input);
await tester.pumpAndSettle();
expect(sheet, findsOneWidget);
expect(tester.widget<TextField>(input).focusNode?.hasFocus, isTrue);
await tester.tap(find.byKey(const Key('comment-list')));
await tester.pump();
expect(sheet, findsOneWidget);
await tester.tapAt(const Offset(20, 20));
await tester.pump();
expect(sheet, findsOneWidget);
expect(tester.widget<TextField>(input).focusNode?.hasFocus, isFalse);
tester.view.viewInsets = const FakeViewPadding();
await tester.pumpAndSettle();
expect(sheet, findsOneWidget);
await tester.tapAt(const Offset(20, 20));
await tester.pumpAndSettle();
expect(sheet, findsNothing);
});
testWidgets('should_use_polished_comment_sizes', (tester) async { testWidgets('should_use_polished_comment_sizes', (tester) async {
final repository = FakeCommentRepository( final repository = FakeCommentRepository(
pages: [ pages: [