Scroll 颤振:改变小部件不透明度和卷轴颜色的最佳方式
我的目标是在用户向下滚动时更改appbar的颜色和不透明度 我的逻辑是:Scroll 颤振:改变小部件不透明度和卷轴颜色的最佳方式,scroll,colors,flutter,opacity,flutter-appbar,Scroll,Colors,Flutter,Opacity,Flutter Appbar,我的目标是在用户向下滚动时更改appbar的颜色和不透明度 我的逻辑是: 滚动偏移量=0:appbar为红色,不透明度=1 0\u ProductDetailsState(); } 类_ProductDetailsState扩展状态 使用TickerProviderStateMixin{ AnimationController _ColorAnimationController; AnimationController _TextAnimationController; 动画(彩色之间),;
- 滚动偏移量=0:appbar为红色,不透明度=1
- 0<滚动偏移<40:appbar为蓝色,不透明度=0.4
- 40 runApp(MyApp());
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“颤振演示”,
主题:主题数据(
主样本:颜色。蓝色,
),
主页:MyHomePage(标题:“颤振演示主页”),
);
}
}
类MyHomePage扩展StatefulWidget{
MyHomePage({Key,this.title}):超级(Key:Key);
最后的字符串标题;
@凌驾
_MyHomePageState createState()=>\u MyHomePageState();
}
类_MyHomePageState扩展状态{
var_gradientColor1=颜色。红色[400];
var_gradientColor2=颜色。红色[800];
ScrollController\u scrollViewController;
void changeColor(){
如果((_scrollViewController.offset==0)和(_gradientColor1!=Colors.red[400])){
设置状态(){
_gradientColor1=颜色。红色[400];
_gradientColor2=颜色。红色[800];
});
}否则如果(_scrollViewController.offset我认为最好的方法是使用
,您将看到主体中的第一个容器不会更改其颜色,因为小部件状态没有更改 结果是: 代码:AnimatedBuilder
import 'dart:math'; import 'package:flutter/material.dart'; class ProductDetails extends StatefulWidget { @override _ProductDetailsState createState() => _ProductDetailsState(); } class _ProductDetailsState extends State<ProductDetails> with TickerProviderStateMixin { AnimationController _ColorAnimationController; AnimationController _TextAnimationController; Animation _colorTween, _iconColorTween; Animation<Offset> _transTween; @override void initState() { _ColorAnimationController = AnimationController(vsync: this, duration: Duration(seconds: 0)); _colorTween = ColorTween(begin: Colors.transparent, end: Color(0xFFee4c4f)) .animate(_ColorAnimationController); _iconColorTween = ColorTween(begin: Colors.grey, end: Colors.white) .animate(_ColorAnimationController); _TextAnimationController = AnimationController(vsync: this, duration: Duration(seconds: 0)); _transTween = Tween(begin: Offset(-10, 40), end: Offset(-10, 0)) .animate(_TextAnimationController); super.initState(); } bool _scrollListener(ScrollNotification scrollInfo) { if (scrollInfo.metrics.axis == Axis.vertical) { _ColorAnimationController.animateTo(scrollInfo.metrics.pixels / 350); _TextAnimationController.animateTo( (scrollInfo.metrics.pixels - 350) / 50); return true; } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Color(0xFFEEEEEE), body: NotificationListener<ScrollNotification>( onNotification: _scrollListener, child: Container( height: double.infinity, child: Stack( children: <Widget>[ SingleChildScrollView( child: Column( children: <Widget>[ Container( height: 150, color: Color((Random().nextDouble() * 0xFFFFFF).toInt() << 0) .withOpacity(1), width: 250, ), Container( height: 150, color: Colors.pink, width: 250, ), Container( height: 150, color: Colors.deepOrange, width: 250, ), Container( height: 150, color: Colors.red, width: 250, ), Container( height: 150, color: Colors.white70, width: 250, ), ], ), ), Container( height: 80, child: AnimatedBuilder( animation: _ColorAnimationController, builder: (context, child) => AppBar( backgroundColor: _colorTween.value, elevation: 0, titleSpacing: 0.0, title: Transform.translate( offset: _transTween.value, child: Text( "اسم کالا اینجا", style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16), ), ), iconTheme: IconThemeData( color: _iconColorTween.value, ), actions: <Widget>[ IconButton( icon: Icon( Icons.local_grocery_store, ), onPressed: () { // Navigator.of(context).push(TutorialOverlay()); }, ), IconButton( icon: Icon( Icons.more_vert, ), onPressed: () {}, ), ], ), ), ), ], ), ), ), ); } }
用户滚动的每一帧都会调用import'dart:math'; 进口“包装:颤振/材料.省道”; 类ProductDetails扩展了StatefulWidget{ @凌驾 _ProductDetailsState createState()=>\u ProductDetailsState(); } 类_ProductDetailsState扩展状态 使用TickerProviderStateMixin{ AnimationController _ColorAnimationController; AnimationController _TextAnimationController; 动画(彩色之间),; 动画(transTween),; @凌驾 void initState(){ _彩色动画控制器= AnimationController(vsync:this,duration:duration(秒:0)); _colorTween=colorTween(开始:Colors.transparent,结束:Color(0xFFee4c4f)) .设置动画(_ColorAnimationController); _iconColorTween=ColorTween(开始:Colors.grey,结束:Colors.white) .设置动画(_ColorAnimationController); _文本动画控制器= AnimationController(vsync:this,duration:duration(秒:0)); _transTween=Tween(开始:偏移(-10,40),结束:偏移(-10,0)) .animate(_TextAnimationController); super.initState(); } bool\u scrollListener(ScrollNotification scrollInfo){ if(scrollInfo.metrics.axis==axis.vertical){ _ColorAnimationController.animateTo(scrollInfo.metrics.pixels/350); _TextAnimationController.animateTo( (scrollInfo.metrics.pixels-350)/50); 返回true; } } @凌驾 小部件构建(构建上下文){ 返回脚手架( 背景颜色:颜色(0xffeeee), 正文:NotificationListener( onNotification:\u滚动侦听器, 子:容器( 高度:双无限, 子:堆栈( 儿童:[ SingleChildScrollView( 子:列( 儿童:[ 容器( 身高:150, 颜色: 颜色((Random().nextDouble()*0xFFFFFF).toInt()应用程序栏( 背景颜色:_colorTween.value, 海拔:0, 标题间距:0.0, 标题:Transform.translate( 偏移量:_transTween.value, 子:文本( "اسم کالا اینجا", 样式:TextStyle( 颜色:颜色,白色, fontWeight:fontWeight.bold, 尺寸:16),, ), ), iconTheme:IconThemeData( 颜色:_iconColorTween.value, ), 行动:[ 图标按钮( 图标:图标( Icons.local_杂货店, ), 已按下:(){ //Navigator.of(context.push(TutorialOverlay()); }, ), 图标按钮( 图标:图标( 图标。更多信息, ), 按下:(){}, ), ], ), ), ), ], ), ), ), ); } }
。可能会添加一个检查,检查颜色是否已经是您想要设置的颜色,然后不要调用setState
。例如,在第一个setState
中,检查颜色是否也不是if
和颜色。红色[400]
。这样你就不会有那么多调用颜色。红色[800]
@tudorprodan的调用了,我已经在每个if中进行了检查,即:_gradientColor1!=Colors.red[400]setState
import 'dart:math'; import 'package:flutter/material.dart'; class ProductDetails extends StatefulWidget { @override _ProductDetailsState createState() => _ProductDetailsState(); } class _ProductDetailsState extends State<ProductDetails> with TickerProviderStateMixin { AnimationController _ColorAnimationController; AnimationController _TextAnimationController; Animation _colorTween, _iconColorTween; Animation<Offset> _transTween; @override void initState() { _ColorAnimationController = AnimationController(vsync: this, duration: Duration(seconds: 0)); _colorTween = ColorTween(begin: Colors.transparent, end: Color(0xFFee4c4f)) .animate(_ColorAnimationController); _iconColorTween = ColorTween(begin: Colors.grey, end: Colors.white) .animate(_ColorAnimationController); _TextAnimationController = AnimationController(vsync: this, duration: Duration(seconds: 0)); _transTween = Tween(begin: Offset(-10, 40), end: Offset(-10, 0)) .animate(_TextAnimationController); super.initState(); } bool _scrollListener(ScrollNotification scrollInfo) { if (scrollInfo.metrics.axis == Axis.vertical) { _ColorAnimationController.animateTo(scrollInfo.metrics.pixels / 350); _TextAnimationController.animateTo( (scrollInfo.metrics.pixels - 350) / 50); return true; } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Color(0xFFEEEEEE), body: NotificationListener<ScrollNotification>( onNotification: _scrollListener, child: Container( height: double.infinity, child: Stack( children: <Widget>[ SingleChildScrollView( child: Column( children: <Widget>[ Container( height: 150, color: Color((Random().nextDouble() * 0xFFFFFF).toInt() << 0) .withOpacity(1), width: 250, ), Container( height: 150, color: Colors.pink, width: 250, ), Container( height: 150, color: Colors.deepOrange, width: 250, ), Container( height: 150, color: Colors.red, width: 250, ), Container( height: 150, color: Colors.white70, width: 250, ), ], ), ), Container( height: 80, child: AnimatedBuilder( animation: _ColorAnimationController, builder: (context, child) => AppBar( backgroundColor: _colorTween.value, elevation: 0, titleSpacing: 0.0, title: Transform.translate( offset: _transTween.value, child: Text( "اسم کالا اینجا", style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16), ), ), iconTheme: IconThemeData( color: _iconColorTween.value, ), actions: <Widget>[ IconButton( icon: Icon( Icons.local_grocery_store, ), onPressed: () { // Navigator.of(context).push(TutorialOverlay()); }, ), IconButton( icon: Icon( Icons.more_vert, ), onPressed: () {}, ), ], ), ), ), ], ), ), ), ); } }