fix(player): 评论面板固定半屏高度

This commit is contained in:
Zhou Weidong committed 2026-10-21 13:20:28 +08:00
1 parent fc877f25bf
commit 50edbf40c4
2 files changed
+34 -100

No files matched your search

@@ -21,8 +21,6 @@ import '../../../core/widgets/empty_state.dart';
import '../../../l10n/app_localizations.dart'; import '../../../l10n/app_localizations.dart';
import 'comment_tile.dart'; import 'comment_tile.dart';
const double _minSheetHeight = 280;
const double _maxSheetHeight = 520;
const int _maxCommentLength = 300; const int _maxCommentLength = 300;
const double _composerRadius = 22; const double _composerRadius = 22;
const double _composerHeight = 44; const double _composerHeight = 44;
@@ -50,14 +48,11 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
final _input = TextEditingController(); final _input = TextEditingController();
final _inputFocus = FocusNode(); final _inputFocus = FocusNode();
final _keyboardInset = KeyboardInsetNotifier.instance; final _keyboardInset = KeyboardInsetNotifier.instance;
final _sheetMeasureKey = GlobalKey();
late final CommentRepository _comments; late final CommentRepository _comments;
late final CommentController _controller; late final CommentController _controller;
DramaComment? _replyTo; DramaComment? _replyTo;
int? _serverCount; int? _serverCount;
int _countRequest = 0; int _countRequest = 0;
double? _sheetHeightWithoutKeyboard;
bool _sheetMeasureScheduled = false;
@override @override
void initState() { void initState() {
@@ -105,27 +100,6 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
_keyboardInset.value / MediaQuery.devicePixelRatioOf(context), _keyboardInset.value / MediaQuery.devicePixelRatioOf(context),
); );
void _measureSheetWithoutKeyboard(double keyboardHeight) {
if (keyboardHeight > 0 || _inputFocus.hasFocus || _sheetMeasureScheduled) {
return;
}
_sheetMeasureScheduled = true;
WidgetsBinding.instance.addPostFrameCallback((_) {
_sheetMeasureScheduled = false;
if (!mounted) return;
if (_inputFocus.hasFocus || _keyboardHeight(context) > 0) return;
final box = _sheetMeasureKey.currentContext?.findRenderObject();
if (box is! RenderBox || !box.hasSize) return;
final height = box.size.height;
if (!height.isFinite ||
(_sheetHeightWithoutKeyboard != null &&
(height - _sheetHeightWithoutKeyboard!).abs() < 0.5)) {
return;
}
setState(() => _sheetHeightWithoutKeyboard = height);
});
}
Future<void> _post() async { Future<void> _post() async {
if (_controller.submitting) return; if (_controller.submitting) return;
if (!await ensureSignedIn(context) || !mounted) return; if (!await ensureSignedIn(context) || !mounted) return;
@@ -190,20 +164,14 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final screenLimit = MediaQuery.sizeOf(context).height - 24; final screenHeight = MediaQuery.sizeOf(context).height;
final maxHeight = screenLimit < _maxSheetHeight final topSafeArea = MediaQuery.paddingOf(context).top;
? screenLimit final halfHeight = (screenHeight * 0.5).roundToDouble();
: _maxSheetHeight; final maxHeight = math.max(0.0, screenHeight - topSafeArea);
final sheetHeight = math.min(halfHeight, maxHeight);
final inputFocused = _inputFocus.hasFocus; final inputFocused = _inputFocus.hasFocus;
final keyboardHeight = _keyboardHeight(context); final keyboardHeight = _keyboardHeight(context);
final keyboardOpen = keyboardHeight > 0;
final expanded = inputFocused; final expanded = inputFocused;
final availableHeight = math.max(0.0, screenLimit - keyboardHeight);
final keyboardPanelHeight = math.min(
_sheetHeightWithoutKeyboard ?? maxHeight,
availableHeight,
);
_measureSheetWithoutKeyboard(keyboardHeight);
return Stack( return Stack(
fit: StackFit.expand, fit: StackFit.expand,
children: [ children: [
@@ -225,53 +193,31 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
onTap: () {}, onTap: () {},
child: KeyedSubtree( child: KeyedSubtree(
key: const Key('player-comments-sheet'), key: const Key('player-comments-sheet'),
child: Container( child: SizedBox(
decoration: const BoxDecoration( key: const Key('comment-sheet-constraints'),
color: AppColors.card, height: sheetHeight,
borderRadius: BorderRadius.vertical( child: Container(
top: Radius.circular(_sheetRadius), decoration: const BoxDecoration(
color: AppColors.card,
borderRadius: BorderRadius.vertical(
top: Radius.circular(_sheetRadius),
),
), ),
), child: SafeArea(
child: SafeArea( top: false,
top: false, child: ListenableBuilder(
child: ListenableBuilder( listenable: _controller,
listenable: _controller, builder: (context, _) {
builder: (context, _) { return Padding(
final minHeight = _controller.comments.isEmpty padding: const EdgeInsets.symmetric(horizontal: 16),
? (_minSheetHeight < maxHeight child: _content(
? _minSheetHeight context,
: maxHeight) expanded: expanded,
: 0.0; keyboardHeight: keyboardHeight,
return AnimatedSize(
duration: const Duration(milliseconds: 200),
curve: Curves.easeOut,
alignment: Alignment.bottomCenter,
child: KeyedSubtree(
key: const Key('comment-sheet-constraints'),
child: ConstrainedBox(
key: _sheetMeasureKey,
constraints: keyboardOpen
? BoxConstraints.tightFor(
height: keyboardPanelHeight,
)
: BoxConstraints(
minHeight: minHeight,
maxHeight: maxHeight,
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16,
),
child: _content(
context,
expanded: expanded,
keyboardHeight: keyboardHeight,
),
),
), ),
), );
); },
}, ),
), ),
), ),
), ),
@@ -334,8 +280,7 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
], ],
), ),
), ),
Flexible( Expanded(
fit: FlexFit.loose,
child: _list( child: _list(
l10n, l10n,
composerReserve: composerReserve, composerReserve: composerReserve,
@@ -395,7 +340,6 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
} }
return ListView.builder( return ListView.builder(
key: const Key('comment-list'), key: const Key('comment-list'),
shrinkWrap: true,
padding: EdgeInsets.only( padding: EdgeInsets.only(
top: 4, top: 4,
bottom: composerReserve + keyboardHeight, bottom: composerReserve + keyboardHeight,
+5 -15
View File
@@ -581,7 +581,7 @@ void main() {
expect(find.byIcon(Icons.more_horiz_rounded), findsNothing); expect(find.byIcon(Icons.more_horiz_rounded), findsNothing);
}); });
testWidgets('should_size_short_list_to_content', (tester) async { testWidgets('should_use_half_screen_height_for_one_comment', (tester) async {
tester.view.physicalSize = const Size(390, 844); tester.view.physicalSize = const Size(390, 844);
tester.view.devicePixelRatio = 1; tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize); addTearDown(tester.view.resetPhysicalSize);
@@ -589,10 +589,7 @@ void main() {
final repository = FakeCommentRepository( final repository = FakeCommentRepository(
pages: [ pages: [
CommentPage( CommentPage(
comments: [ comments: [commentFixture(id: '10', content: 'One comment')],
commentFixture(id: '10', content: 'Short list one'),
commentFixture(id: '11', content: 'Short list two'),
],
), ),
], ],
); );
@@ -600,14 +597,7 @@ void main() {
await _pumpSheet(tester, repository: repository); await _pumpSheet(tester, repository: repository);
final sheet = find.byKey(const Key('player-comments-sheet')); final sheet = find.byKey(const Key('player-comments-sheet'));
expect(tester.getSize(sheet).height, lessThan(520)); expect(tester.getSize(sheet).height, closeTo(844 / 2, 0.1));
final lastCommentBottom = tester
.getBottomLeft(find.byKey(const Key('comment-item-11')))
.dy;
final composerTop = tester
.getTopLeft(find.byKey(const Key('comment-composer')))
.dy;
expect(composerTop - lastCommentBottom, lessThan(80));
}); });
testWidgets('should_keep_minimum_height_for_empty_state', (tester) async { testWidgets('should_keep_minimum_height_for_empty_state', (tester) async {
@@ -627,7 +617,7 @@ void main() {
addTearDown(tester.view.resetPhysicalSize); addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio); addTearDown(tester.view.resetDevicePixelRatio);
final repository = FakeCommentRepository( final repository = FakeCommentRepository(
pages: [CommentPage(comments: _comments(30))], pages: [CommentPage(comments: _comments(20))],
); );
await _pumpSheet(tester, repository: repository); await _pumpSheet(tester, repository: repository);
@@ -649,7 +639,7 @@ void main() {
expect(position.pixels, greaterThan(0)); expect(position.pixels, greaterThan(0));
expect( expect(
tester.getSize(find.byKey(const Key('player-comments-sheet'))).height, tester.getSize(find.byKey(const Key('player-comments-sheet'))).height,
520, closeTo(844 / 2, 0.1),
); );
}); });