Dart 如何使用PageController的当前值更新子窗口小部件(加载指示器)?

Dart 如何使用PageController的当前值更新子窗口小部件(加载指示器)?,dart,flutter,loading,Dart,Flutter,Loading,仅当PageController(或PageView)的当前值与其在行中的索引相同时,我才想设置LinearProgressIndicator的动画 正如您在屏幕截图中看到的,我有一个PageView,其中有一行linearproressionindicatorsPageView由其自己的PageController控制,当AnimationController到达其末端时,页面切换 我希望实现类似的效果,即只有当前页面的加载指示器应设置动画 代码 在下面,您可以找到顶部小部件的代码,即Pag

仅当
PageController
(或
PageView
)的当前值与其在
行中的索引相同时,我才想设置
LinearProgressIndicator
的动画

正如您在屏幕截图中看到的,我有一个
PageView
,其中有一行
linearproressionindicator
s
PageView
由其自己的
PageController
控制,当
AnimationController
到达其末端时,页面切换

我希望实现类似的效果,即只有当前页面的
加载指示器
应设置动画

代码 在下面,您可以找到顶部小部件的代码,即
PageView
,底部是
LoadingIndicator
s

导入“包装:颤振/材料.省道”;
类PageViewWithLoadingIndicators扩展StatefulWidget{
最终列表;
最后列出图像;
最终工期总工期;
最后期限过渡期;
最终曲线动画曲线;
带加载指示器的常量页面视图(
{键,
这个.imageURL,
这是一张照片,
this.totalDuration=常数持续时间(秒:10),
this.transitionDuration=常量持续时间(毫秒:700),
this.animationCurve=Curves.easeInOut})
:super(key:key);
@凌驾
PageViewWithLoadingIndicatorState createState()=>PageViewWithLoadingIndicatorState();
}
类PageViewWithLoadingIndicatorsState扩展状态
使用SingleTickerProviderStateMixin{
动画加载动画化;
动画控制器;
页面控制器;
整数计数;
整数指数;
@凌驾
void initState(){
super.initState();
断言(widget.imageUrls.isNotEmpty | | widget.images.isNotEmpty);
count=widget.imageurl.length;
指数=0;
controller=AnimationController(持续时间:widget.totalDuration~/count,vsync:this);
pageController=pageController(初始页:0);
loadingBarAnimation=Tween(开始:0.0,结束:1.0)。动画(控制器)
..addStatusListener((状态){
如果(状态==AnimationStatus.completed){
controller.reset();
设置状态(){
索引++;
});
如果(索引==计数){
设置状态(){
指数=0;
});
}
pageController.animateToPage(索引,
曲线:widget.animationCurve,持续时间:widget.transitionDuration);
}else if(状态==AnimationStatus.discomered){
controller.forward();
}
});
controller.forward();
}
@凌驾
无效处置(){
controller.dispose();
pageController.dispose();
super.dispose();
}
@凌驾
小部件构建(构建上下文){
返回堆栈(
儿童:[
容器(
子:页面视图(
子项:widget.images!=null
?widget.images
:widget.imageURL
.map((f)=>Image.network(
F
适合:BoxFit.cover,
))
.toList(),
物理学:NeverscrollableScroll物理学(),
控制器:页面控制器,
),
),
定位(
底部:0,
左:0,,
右:0,,
子:页面加载程序(动画:加载动画,计数:计数),
)
],
);
}
}
类PageLoader扩展了AnimatedWidget{
最终整数计数;
页面加载程序({Key Key,@required this.count,Animation})
:super(关键点:关键点,可收听:动画);
@凌驾
小部件构建(构建上下文){
最终动画=可收听;
返回行(
子项:List.generate(
计数
(索引)=>SmallLoadingBar(动画,索引),
));
}
}
类SmallLoadingBar扩展了无状态小部件{
最终整数指数;
最终动画值;
SmallLoadingBar(this.value,this.index);
@凌驾
小部件构建(构建上下文){
扩大回报(
子:容器(
边距:仅限边集(顶部:10,底部:10,左侧:5,右侧:5),
身高:5,,
宽度:double.infinity,
装饰:盒子装饰(颜色:Colors.white24),
子对象:线性表达式指示器(
背景颜色:颜色。透明,
valueColor:AlwaysStoppedAnimation(颜色.白色70),
value:value.value),
);
}
}
您可以简单地使用它:

最终列表图像=[
'https://i.imgur.com/F8PBP7P.jpg',
'https://i.imgur.com/DtWaRhg.jpg',
'https://i.imgur.com/GsRLPXM.jpg',
'https://i.imgur.com/BMnhHaH.jpg',
'https://i.imgur.com/qXvgwpw.jpg',
];
带加载指示器的页面视图(图像URL:图像)
这里最好的方法是什么?使用
InheritedWidget
或Stream检查LoadingIndicator容器中的当前页面索引

仅当当前 PageController(或PageView)的值与其第行中的索引相同

使用当前代码很容易做到这一点。您所要做的就是传递在动画侦听器中更新的索引。首先,可以稍微简化动画侦听器代码:

setState(() {
    index++;
    if (index == count) {
       index = 0;
    }
});
然后通过小部件层次结构将索引值传递给LinearProgressIndicator,您将在其中使用它:

// in PageViewWithLoadingIndicatorsState's build() method
child: PageLoader(animation: loadingBarAnimation, count: count, current: index),
然后,在SmallLoadingBar中,可以使用传递的值仅设置当前加载指示器的动画:

class SmallLoadingBar extends StatelessWidget {
  final int index;
  final Animation<double> value;
  final int current;

  SmallLoadingBar(this.value, this.index, this.current);

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Container(
          margin: EdgeInsets.only(top: 10, bottom: 10, left: 5, right: 5),
          height: 5,
          width: double.infinity,
          decoration: BoxDecoration(color: Colors.white24),
          child: LinearProgressIndicator(
              backgroundColor: Colors.transparent,
              valueColor: AlwaysStoppedAnimation<Color>(Colors.white70),
              value: _calculateState(index, current))),
    );
  }

  double _calculateState(int index, int current) {
    // this is the page at which we are so it needs to be animated
    if (index == current) {
      return value.value;
    } else if (index < current) {
      // this is behind the current indicator so was already animated
      return 1;
    } else {
      // this is after the current indicator so it wasn't yet animated
      return 0;
    }
  }
}
类SmallLoadingBar扩展了无状态小部件{
最终整数指数;
最终动画值;
最终int电流;
SmallLoadingBar(this.value、this.index、this.current);
@凌驾
小部件构建(构建上下文){
扩大回报(
子:容器(
边距:仅限边集(顶部:10,底部:10,左侧:5,右侧:5),
身高:5,,
宽度:double.infinity,
D