有没有一种方法可以让小部件主体在键盘显示时占用的空间比可用空间少一点(考虑到键盘上方固定的BottomSheet)?
我有一个底部的工作表,我显示每当键盘可用,占用65 px的空间。
下面是一个TextFormField,下面有一个按钮。TextFormField会在我键入时添加额外的行,当我没有打开共享表时,最后一行在屏幕上保持可见。
我希望这个预期的空间是65 px短,所以TextField开始滚动65 px更快(占底部工作表附加在键盘上)。
有什么办法能让这件事成功吗?我当前的代码看起来应该可以工作,但是小部件仍然具有相同的滚动行为,就好像底部工作表不存在一样。
我尝试过的其他所有方法(为我的BoxConstraints小部件使用maxHeight,在列外添加Expanded小部件)都只会导致一堆错误,小部件无法正确加载。
当前小部件(Scaffold Stateful Widget是所有这些配置的地方):
class TweetDraftPage extends StatelessWidget {
Thread? thread;
TweetDraftPage({this.thread, super.key});
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<ThreadWatcherBloc>(
create: (context) => getIt<ThreadWatcherBloc>(),
),
BlocProvider<ThreadEditorBloc>(
create: (context) => ThreadEditorBloc(
getIt<ThreadRepository>(),
thread,
getIt<ThreadWatcherBloc>(),
),
),
],
child: TweetDraftPageScaffold(),
);
}
}
class TweetDraftPageScaffold extends StatefulWidget {
const TweetDraftPageScaffold({
super.key,
});
@override
State<TweetDraftPageScaffold> createState() => _TweetDraftPageScaffoldState();
}
class _TweetDraftPageScaffoldState extends State<TweetDraftPageScaffold>
with WidgetsBindingObserver {
bool isKeyboardVisible = false;
double keyboardHeight = 0;
final double bottomSheetHeight = 65;
@override
void initState() {
super.initState();
WidgetsBinding.instance?.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance?.removeObserver(this);
super.dispose();
}
@override
void didChangeMetrics() {
final mediaQueryData = MediaQuery.of(context);
final keyboardVisibleHeight = mediaQueryData.viewInsets.bottom;
setState(() {
isKeyboardVisible = keyboardVisibleHeight > 0;
keyboardHeight = keyboardVisibleHeight;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).canvasColor,
appBar: AppBar(
title: const Text(
'Edit Tweet',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
body: Padding(
padding: const EdgeInsets.all(16),
child: LayoutBuilder(builder: (context, constraints) {
final double availableHeight = math.max(
constraints.maxHeight -
keyboardHeight -
(isKeyboardVisible ? bottomSheetHeight : 0),
0,
);
return SingleChildScrollView(
child: ConstrainedBox(
constraints:
BoxConstraints(minHeight: availableHeight),
child: Column(
children: [
// for each TweetEditorBloc in ThreadEditorBloc, create a BlocProvider
// with the TweetEditorBloc, and a child of TweetDraft
BlocConsumer<ThreadEditorBloc, ThreadEditorState>(
listenWhen: (p, c) =>
c.threadSaved != null && c.threadSaved != p.threadSaved,
listener: (context, state) {
Navigator.pop(context);
},
buildWhen: (p, c) =>
p.tweetEditorBlocs.length != c.tweetEditorBlocs.length,
builder: (context, state) {
return Form(
child: Column(
children: [
for (var i = 0;
i < state.tweetEditorBlocs.length;
i++)
BlocProvider<TweetEditorBloc>(
create: (context) => state.tweetEditorBlocs[i],
child: TweetDraft(),
),
],
),
);
},
),
SizedBox(height: 8),
ElevatedButton(
onPressed: () {
context
.read<ThreadEditorBloc>()
.add(const ThreadEditorEvent.saveThread());
context
.read<ThreadWatcherBloc>()
.add(const ThreadWatcherEvent.refresh());
},
child: Text('Save Draft')),
],
),
),
);
}),
),
bottomSheet: isKeyboardVisible
? BottomSheet(
constraints: BoxConstraints(maxHeight: bottomSheetHeight),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.zero),
enableDrag: false,
clipBehavior: Clip.none,
onClosing: () => null,
builder: (context) => Padding(
padding: EdgeInsets.fromLTRB(5, 0, 5, 0),
child: CharacterCounter()))
: null,
);
}
}
图片
这是页面开始时的样子:
当我输入时,它会添加额外的行;如果它只是键盘,它会自动滚动,以便底部行(我正在键入的地方)总是可见的。在本例中,我输入的是第12行,它就在屏幕之外:
1条答案
按热度按时间ttp71kqs1#
这里的主要问题是,我基本上是减去键盘的高度两次。
我所做的主要更改是(1)更新
LayoutBuilder
,使availableHeight只减去底部共享表的高度,而不是减去键盘高度,以及(2)将ConstrainedBox
移动到SingleChildScrollView
之外我认为布局构建器中的约束已经考虑了keyboardHeight,所以我需要做的就是减去底部的共享表。