gpt4 book ai didi

flutter - Flutter:如何以编程方式周期性地滚动(从流中)?

转载 作者:行者123 更新时间:2023-12-03 04:46:51 25 4
gpt4 key购买 nike

我有拍打小部件。它是带有 child +“中间光标”的SingleChildScrollView:

我可以左右滚动此列表-光标始终位于中间。
现在,我需要以一秒钟的频率,以编程方式滚动相对于光标的“子级”。

我尝试添加计时器和线程并在我的小部件中对其进行处理。另外,我在小部件中添加了SteamBuilder,但在一帧中出现错误。

我的错误框:

enter image description here

我的正常构架:

enter image description here

一帧后发生此错误。任何解决此问题的想法-您将不胜感激。

这是我的完整代码:

    void main() => //runApp(MyApp());
runApp(StartApp());

class StartApp extends StatefulWidget {
@override
_StartAppState createState() => _StartAppState();
}

class _StartAppState extends State<StartApp> {
StreamController<double> _currentPositionController;
double position = 0;
Timer _progressTimer;

void positionUpdate(Timer timer) {
position += 0.550;
_currentPositionController.add(position);
}

@override
void initState() {
super.initState();
_progressTimer = Timer.periodic(
Duration(milliseconds: 350), positionUpdate);
_currentPositionController = StreamController<double>.broadcast();
}

@override
void dispose() {
_progressTimer?.cancel();
_currentPositionController?.close();
super.dispose();
}

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: TmpPage(currentPosition:_currentPositionController.stream ),
),
);
}
}

这是我的小部件(TmpPage):
import 'package:flutter/material.dart';
import 'dart:ui';

class TmpPage extends StatefulWidget {
final Stream<double> currentPosition;

const TmpPage({Key key, this.currentPosition}) : super(key: key);
@override
_TmpPageState createState() => _TmpPageState();
}

class _TmpPageState extends State<TmpPage> with WidgetsBindingObserver {

double before = 0;
double halfWidth;
double leftPosition;
ScrollController _controller;

@override
void initState() {

WidgetsBinding.instance.addObserver(this);
halfWidth =0;
_controller = ScrollController();
_controller.addListener(_scrollListener);
super.initState();
}

@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
_controller.removeListener(_scrollListener);
_controller.dispose();
super.dispose();
}

double width = 0.0;
double height = 0.0;

@override void didChangeMetrics() {
setState(() {
width = window.physicalSize.width;
height = window.physicalSize.height;
halfWidth = window.physicalSize.width / 2;
//halfWidth = (MediaQuery.of(context).size.width) / 2;
leftPosition = halfWidth;
});
}

@override
Widget build(BuildContext context) {
return _getBody(context);
}

Widget _getBody(context) {
if(halfWidth ==0)
halfWidth = (MediaQuery.of(context).size.width) / 2;
if (before == 0)
leftPosition = halfWidth;
return StreamBuilder<double>(
stream: widget.currentPosition,
builder: (context, snapshot) {
if(snapshot.data !=null && _controller.hasClients){
_controller.jumpTo(snapshot.data);
}
return NotificationListener<ScrollNotification>(
onNotification: (scrollNotification) {
if (scrollNotification is ScrollUpdateNotification) {
var m = scrollNotification.metrics;
before = m.extentBefore;
setState(() {
leftPosition = before;
});
return false;
}
return false;
},
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SingleChildScrollView(
controller: _controller,
scrollDirection: Axis.horizontal,
child: Row(
children: <Widget>[
SizedBox(
width: halfWidth,
),
Stack(
children: <Widget>[
Row(
children: List.generate(
30,
(i) => Padding(
padding: const EdgeInsets.all(2.0),
child: new Container(
height: 42.0,
width: 42.0,
color: _getColor(i),
),
)).toList(),
),
Positioned(
left: leftPosition,
top: 0,
bottom: 0,
child: Container(
color: Colors.red,
width: 2,
),
),
],
),
SizedBox(
width: halfWidth,
),
],
)),
],
),
);
}
);
}

Color _getColor(int i) {
if(i<10)
return Colors.blueGrey;
if(i<20)
return Colors.orange;
if(i<30)
return Colors.lightBlueAccent;
else
return Colors.green;

}


void _scrollListener() {
if (_controller.offset >= _controller.position.maxScrollExtent &&
!_controller.position.outOfRange) {
print('end');
_controller.jumpTo(_controller.offset - 1);
}
if (_controller.offset <= _controller.position.minScrollExtent &&
!_controller.position.outOfRange) {
print('start');
_controller.jumpTo(_controller.offset + 1);
}
}
}

最佳答案

您不能像setState一样从build方法内部触发构建。因此,您可以使用以下命令包装对setState的所有调用:

WidgetsBinding.instance.addPostFrameCallback((_) {
// Your code here
});

为了在构建方法完成之后在框架的结尾处调用代码。

关于flutter - Flutter:如何以编程方式周期性地滚动(从流中)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62138465/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com