【发布时间】:2021-06-07 15:50:02
【问题描述】:
第一次观看the short video clip of the app。请注意 sliver 应用栏底部右侧的照片图标按钮。它在向上滚动时缩小/淡化,并在向下滚动时反转。但是,请注意,当我打开键盘,然后关闭键盘时,照片图标按钮不会返回。这是因为小部件没有构建,因此计算该按钮的大小、不透明度和位置的代码永远不会运行。我不知道如何在软键盘关闭时触发小部件的构建。
视频链接:https://drive.google.com/file/d/1YVlvBDYB3EQVpwdMVSIvLaAeWK_VeQCE/view?usp=sharing
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class TestDetailsScreen extends StatefulWidget {
static final String routeName = '/test-details-screen';
@override
_TestDetailsScreenState createState() => _TestDetailsScreenState();
}
class _TestDetailsScreenState extends State<TestDetailsScreen>
with SingleTickerProviderStateMixin {
ScrollController _scrollController;
AnimationController _animationController;
Animation _animation;
@override
void initState() {
super.initState();
_scrollController = new ScrollController();
_scrollController.addListener(() => setState(() {}));
_animationController = AnimationController(
duration: Duration(milliseconds: 250),
vsync: this,
);
_animation = Tween(begin: 1.0, end: 0.0).animate(_animationController);
}
@override
void dispose() {
_scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final double defaultTopMargin = 190.0 - 4.0;
double top = defaultTopMargin;
if (_scrollController.hasClients) {
double offset = _scrollController.offset;
top -= offset;
}
if (top <= 75.0 && _animation.isDismissed) {
_animationController.forward();
} else if (top >= 75.0 && _animation.isCompleted) {
_animationController.reverse();
}
return Scaffold(
body: Stack(
children: [
CustomScrollView(
controller: _scrollController,
slivers: [
SliverAppBar(
pinned: true,
floating: false,
expandedHeight: 190.0,
iconTheme: IconThemeData(
color: Theme.of(context).primaryColorLight,
),
flexibleSpace: FlexibleSpaceBar(
title: Text(
'Add inputs',
style: TextStyle(
color: Theme.of(context).primaryColorLight,
fontSize: 16.0,
),
),
background: Image.asset(
'assets/images/clouds.jpg',
fit: BoxFit.cover,
),
),
actions: [
IconButton(
icon: const Icon(Icons.check),
onPressed: () {},
),
],
),
SliverList(
delegate: SliverChildListDelegate.fixed([
Padding(
padding: const EdgeInsets.only(left: 10, right: 10),
child: SizedBox(
width: double.infinity,
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 25),
child: Card(
color: Theme.of(context).primaryColorLight,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
elevation: 0,
margin: EdgeInsets.all(5),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
TextFormField(
decoration: const InputDecoration(
border: const UnderlineInputBorder(),
labelText: 'Your text',
),
),
TextFormField(
decoration: const InputDecoration(
border: const UnderlineInputBorder(),
labelText: 'Your text',
),
),
],
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Card(
color: Theme.of(context).primaryColorLight,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
elevation: 0,
margin: const EdgeInsets.all(5),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
Align(
alignment: Alignment.topLeft,
child: const Text(
'Additional Details (Optional)',
),
),
Row(
children: [
Expanded(
child: TextFormField(
decoration: const InputDecoration(
border:
const UnderlineInputBorder(),
labelText: 'Your text',
),
),
),
Padding(
padding: const EdgeInsets.all(
10,
),
),
Expanded(
child: TextFormField(
decoration: const InputDecoration(
border:
const UnderlineInputBorder(),
labelText: 'Your text',
),
),
),
],
),
Row(
children: [
Expanded(
child: TextFormField(
decoration: InputDecoration(
border:
const UnderlineInputBorder(),
labelText: 'Your text',
hintStyle: Theme.of(context)
.textTheme
.caption,
),
),
),
Padding(
padding: EdgeInsets.all(
10,
),
),
Expanded(
child: TextFormField(
maxLength: 4,
keyboardType: TextInputType.number,
decoration: const InputDecoration(
border:
const UnderlineInputBorder(),
labelText: 'Your text',
counterText: '',
),
),
),
],
),
Row(
children: [
Expanded(
child: TextFormField(
inputFormatters: [
FilteringTextInputFormatter.allow(
RegExp('[a-zA-Z]'))
],
decoration: const InputDecoration(
border:
const UnderlineInputBorder(),
labelText: 'Your text',
counterText: '',
),
),
),
Padding(
padding: EdgeInsets.all(
10,
),
),
Expanded(
child: FractionallySizedBox(
alignment: Alignment.centerLeft,
child: TextFormField(
keyboardType:
TextInputType.number,
decoration: InputDecoration(
alignLabelWithHint: false,
border:
const UnderlineInputBorder(),
labelText: 'Your choices',
labelStyle: const TextStyle(
height: 1,
),
suffix: const Text(
'Measurement',
style: const TextStyle(
fontSize: 16,
),
),
),
),
),
),
],
),
],
),
),
),
),
Row(
children: [
Expanded(
child: IconButton(
icon: Icon(
Icons.archive,
color: Theme.of(context).primaryColorDark,
),
onPressed: () {},
),
),
Expanded(
child: IconButton(
icon: Icon(
Icons.delete,
color: Theme.of(context).primaryColorDark,
),
onPressed: () {},
),
)
],
)
],
),
),
),
]),
)
],
),
AnimatedBuilder(
animation: _animation,
builder: (BuildContext context, Widget child) {
return Positioned(
top: top <= 50 ? 50 : top,
right: 16.0,
child: new Transform(
transform: new Matrix4.identity()..scale(_animation.value),
alignment: Alignment.center,
child: Opacity(
opacity: _animation.value,
child: new FloatingActionButton(
elevation: 0,
backgroundColor: Theme.of(context).primaryColorDark,
onPressed: () => {},
child: new Icon(
Icons.photo,
color: Theme.of(context).primaryColorLight,
),
),
),
),
);
},
)
],
),
);
}
}
【问题讨论】:
-
问题是两件事 - 键盘关闭时不会构建小部件树,因为没有任何引用 MediaQuery.of(context).viewInsets 如果您添加对此的引用,甚至将变量设置为在 build 方法的顶部,当 mediaquery 的 viewInsets 改变时,widget 树会重建。然而,下一个问题是在键盘关闭后滚动控制器的偏移值保持不变,即使它应该恢复为 0。
标签: android flutter dart flutter-layout flutter-animation