Animation 颤振:检测到滚动时隐藏和显示应用程序栏
我在应用程序中使用了Animation 颤振:检测到滚动时隐藏和显示应用程序栏,animation,scroll,flutter,appbar,Animation,Scroll,Flutter,Appbar,我在应用程序中使用了SilverAppBar,应用程序栏动画有问题。所以,问题是当我在列表的中间,我向上滚动时,应用程序条不会出现,但是它出现在滚动到达项目列表顶部的时候。我已经测试了snap参数,并给出了true,但不是我期望的结果。我有关于为此创建自定义动画的想法,但我在颤振方面不是很有经验,而且如果有一种方法可以添加参数,或者其他适合我的小部件,那就太好了 我正在使用的演示的实际代码: Widget _search() => Container( color: C
SilverAppBar
,应用程序栏动画有问题。所以,问题是当我在列表的中间,我向上滚动时,应用程序条不会出现,但是它出现在滚动到达项目列表顶部的时候。我已经测试了snap
参数,并给出了true
,但不是我期望的结果。我有关于为此创建自定义动画的想法,但我在颤振方面不是很有经验,而且如果有一种方法可以添加参数,或者其他适合我的小部件,那就太好了
我正在使用的演示的实际代码:
Widget _search() => Container(
color: Colors.grey[400],
child: SafeArea(
child: Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
enabled: false,
style: TextStyle(fontSize: 16, color: Colors.white),
decoration: InputDecoration(
prefix: SizedBox(width: 12),
hintText: "Search",
contentPadding:
EdgeInsets.symmetric(horizontal: 32.0, vertical: 14.0),
border: InputBorder.none,
),
),
),
)),
);
Container _buildBody() {
return Container(
child: new GridView.count(
crossAxisCount: 2,
children: List.generate(100, (index) {
return Center(
child: Text(
'Item $index',
style: Theme.of(context).textTheme.headline,
),
);
}),
));
}
@override
Widget build(BuildContext context) {
return new Scaffold(
resizeToAvoidBottomPadding: false,
body: new NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
new SliverAppBar(
title: Text("Demo",
style: TextStyle(
color: Colors.white,
)),
pinned: false,
floating: true,
forceElevated: innerBoxIsScrolled,
),
];
},
body: new Column(children: <Widget>[
_search(),
new Expanded(child: _buildBody())
])));
}
Widget\u search()=>容器(
颜色:颜色。灰色[400],
儿童:安全区(
子:容器(
孩子:填充(
填充:常数边集全部(8.0),
孩子:TextField(
启用:false,
样式:TextStyle(字体大小:16,颜色:Colors.white),
装饰:输入装饰(
前缀:SizedBox(宽度:12),
hintText:“搜索”,
内容填充:
边缘组。对称(水平:32.0,垂直:14.0),
边框:InputBorder.none,
),
),
),
)),
);
容器(buildBody){
返回容器(
子项:新建GridView.count(
交叉轴计数:2,
子项:List.generate(100,(索引){
返回中心(
子:文本(
“项目$index”,
风格:Theme.of(context).textTheme.headline,
),
);
}),
));
}
@凌驾
小部件构建(构建上下文){
归还新脚手架(
resizeToAvoidBottomPadding:false,
正文:新嵌套滚动视图(
班主任:
(BuildContext上下文,boolInnerBoxIsCrowled){
返回[
新滑杆(
标题:文本(“演示”,
样式:TextStyle(
颜色:颜色,白色,
)),
错,,
浮动:是的,
强制提升:内包装箱为羊角形,
),
];
},
正文:新列(子项:[
_搜索(),
新扩展的(子:_buildBody())
])));
}
我现在得到的结果是:
将true
赋予snap
参数后得到的结果:
很多应用程序,比如WhatsApp、Facebook、LinkedIn。。。有这个动画应用程序栏。为了更准确地解释我对这个动画应用程序条的期望,我添加了一个Google Play Store的示例,展示了想要的动画:要让这个功能正常工作,你需要使用
CustomScrollView
小部件,而不是NestedScrollView
以下是一个工作示例:
class MyHomeState extends State<MyHome> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
const SliverAppBar(
pinned: false,
snap: false,
floating: true,
flexibleSpace: FlexibleSpaceBar(
title: Text('Demo'),
),
),
SliverGrid(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200.0,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
childAspectRatio: 4.0,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
alignment: Alignment.center,
color: Colors.teal[100 * (index % 9)],
child: Text('grid item $index'),
);
},
childCount: 50,
),
),
],
)
);
}
}
类MyHomeState扩展状态{
@凌驾
小部件构建(构建上下文){
返回脚手架(
正文:自定义滚动视图(
条子:[
常量滑动条(
错,,
快照:错,
浮动:是的,
flexibleSpace:FlexibleSpaceBar(
标题:文本(“演示”),
),
),
银栅(
gridDelegate:SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent:200.0,
主轴间距:10.0,
交叉轴间距:10.0,
childAspectRatio:4.0,
),
代表:SliverChildBuilderDelegate(
(BuildContext上下文,int索引){
返回容器(
对齐:对齐.center,
颜色:Colors.teal[100*(索引%9)],
子项:文本(“网格项$index”),
);
},
儿童人数:50,
),
),
],
)
);
}
}
我在使用刷新指示器的CustomScrollView和SliverAppbar上遇到了类似的问题,我最终创建了自己的自定义appbar。
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class HomeView extends StatefulWidget {
@override
HomeState createState() => HomeState();
}
class HomeState extends State<HomeView> with SingleTickerProviderStateMixin {
bool _isAppbar = true;
ScrollController _scrollController = new ScrollController();
@override
void initState() {
super.initState();
_scrollController.addListener(() {
if (_scrollController.position.userScrollDirection ==
ScrollDirection.reverse) {
appBarStatus(false);
}
if (_scrollController.position.userScrollDirection ==
ScrollDirection.forward) {
appBarStatus(true);
}
});
}
void appBarStatus(bool status) {
setState(() {
_isAppbar = status;
});
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: AnimatedContainer(
height: _isAppbar ? 55.0 : 0.0,
duration: Duration(milliseconds: 200),
child: CustomAppBar(),
),
),
body: ListView.builder(
controller: _scrollController,
itemCount: 20,
itemBuilder: (BuildContext context, int index) {
return container();
},
),
),
);
}
}
Widget container() {
return Container(
height: 80.0,
color: Colors.pink,
margin: EdgeInsets.all(8.0),
width: 100,
child: Center(
child: Text(
'Container',
style: TextStyle(
fontSize: 18.0,
),
)),
);
}
class CustomAppBar extends StatefulWidget {
@override
AppBarView createState() => new AppBarView();
}
class AppBarView extends State<CustomAppBar> {
@override
Widget build(BuildContext context) {
return AppBar(
backgroundColor: Colors.white,
leading: InkWell(
onTap: () => {},
child: new Padding(
padding: const EdgeInsets.all(8.0),
child: CircleAvatar(
backgroundColor: Colors.white,
child: ClipOval(
child: Image.network(
'https://images.squarespace-cdn.com/content/5aee389b3c3a531e6245ae76/1530965251082-9L40PL9QH6PATNQ93LUK/linkedinPortraits_DwayneBrown08.jpg?format=1000w&content-type=image%2Fjpeg'),
),
),
),
),
actions: <Widget>[
IconButton(
alignment: Alignment.centerLeft,
icon: Icon(
Icons.search,
color: Colors.black,
),
onPressed: () {},
),
],
title: Container(
alignment: Alignment.centerLeft,
child: Text("Custom Appbar", style: TextStyle(color: Colors.black),)
),
);
}
}
导入“包装:颤振/材料.省道”;
导入“package:flatter/rendering.dart”;
类HomeView扩展了StatefulWidget{
@凌驾
HomeState createState()=>HomeState();
}
类HomeState使用SingleTickerProviderStateMixin扩展状态{
bool_isAppbar=true;
ScrollController_ScrollController=新的ScrollController();
@凌驾
void initState(){
super.initState();
_scrollController.addListener((){
如果(_scrollController.position.userScrollDirection==
滚动方向(反向){
appBarStatus(假);
}
如果(_scrollController.position.userScrollDirection==
滚动方向(前进){
appBarStatus(真实);
}
});
}
无效appBarStatus(布尔状态){
设置状态(){
_isAppbar=状态;
});
}
@凌驾
小部件构建(构建上下文){
返回安全区(
孩子:脚手架(
appBar:首选大小(
preferredSize:Size.fromHeight(kToolbarHeight),
子:动画容器(
高度:_isAppbar?55.0:0.0,
持续时间:持续时间(毫秒:200),
子项:CustomAppBar(),
),
),
正文:ListView.builder(
控制器:\ u滚动控制器,
物品计数:20,
itemBuilder:(构建上下文,int索引){
返回容器();
},
),
),
);
}
}
小部件容器(){
返回容器(
身高:80.0,
颜色:颜色。粉红色,
边距:所有边集(8.0),
宽度:100,
儿童:中心(
子:文本(
"货柜",,
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: CustomSliverAppbar(),
);
}
}
class CustomSliverAppbar extends StatefulWidget {
@override
_CustomSliverAppbarState createState() => _CustomSliverAppbarState();
}
class _CustomSliverAppbarState extends State<CustomSliverAppbar>
with SingleTickerProviderStateMixin {
TabController _tabController;
@override
void initState() {
_tabController = TabController(
initialIndex: 0,
length: 2,
vsync: this,
);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
floatHeaderSlivers: true,
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
title: Text(
"WhatsApp type sliver appbar",
),
centerTitle: true,
pinned: true,
floating: true,
bottom: TabBar(
indicatorColor: Colors.black,
labelPadding: const EdgeInsets.only(
bottom: 16,
),
controller: _tabController,
tabs: [
Text("TAB A"),
Text("TAB B"),
]),
),
];
},
body: TabBarView(
controller: _tabController,
children: [
TabA(),
const Center(
child: Text('Display Tab 2',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
),
],
),
),
);
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
}
class TabA extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scrollbar(
child: ListView.separated(
separatorBuilder: (context, child) => Divider(
height: 1,
),
padding: EdgeInsets.all(0.0),
itemCount: 30,
itemBuilder: (context, i) {
return Container(
height: 100,
width: double.infinity,
color: Colors.primaries[Random().nextInt(Colors.primaries.length)],
);
},
),
);
}
}