PageView类似看小说或抖音的页面
scrollDirection: Axis.vertical,
PageView(
children: [
包裹的页面
]
)
example无限加载:
class PageViewFullPage extends StatefulWidget {
const PageViewFullPage({super.key});
@override
State<PageViewFullPage> createState() => _PageViewFullPageState();
}
class _PageViewFullPageState extends State<PageViewFullPage> {
List<Widget> list = [];
@override
void initState() {
super.initState();
for (var i = 0; i < 10; i++) {
list.add(Center(
child: Text(
"第${i + 1}屏",
style: const TextStyle(fontSize: 60),
),
));
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
scrollDirection: Axis.vertical,
children: list,
onPageChanged: (index) {
print(index);
if (index + 2 == list.length) {
setState(() {
for (var i = 0; i < 10; i++) {
list.add(Center(
child: Text(
"第${i + 1}屏",
style: const TextStyle(fontSize: 60),
),
));
}
});
}
},
),
);
}
}
细节:PageView尽量外层包裹一下,不然可能会出现控制不了高度
定位技巧:能占满行
left: 0,
right: 0,
bottom: 2,
PageController 实现轮播
这里有用到定时器:Timer
dispose 用于释放资源,以便在Widget被删除之前,可以清除它们。
cancel用于取消异步操作。它通常与Future和Stream一起使用,以便在不需要结果时,可以停止异步操作。
1、图片数据文件
class PageViewSwiper extends StatefulWidget {
const PageViewSwiper({super.key});
@override
State<PageViewSwiper> createState() => _PageViewSwiperState();
}
class _PageViewSwiperState extends State<PageViewSwiper> {
List<String> list = [];
@override
void initState() {
super.initState();
list = const [
"https://www.itying.com/images/flutter/1.png",
"https://www.itying.com/images/flutter/2.png",
"https://www.itying.com/images/flutter/3.png",
];
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("pageview-Swiper"),
),
body: ListView(children: [Swiper(list: list,)]),
);
}
}
2、轮播文件
class Swiper extends StatefulWidget {
final double width;
final double height;
final List<String> list;
const Swiper(
{super.key,
this.height = 200,
this.width = double.infinity,
required this.list});
@override
State<Swiper> createState() => _SwiperState();
}
class _SwiperState extends State<Swiper> {
int _currentIndex = 0;
List<Widget> pageList = [];
late PageController _pageController;
late Timer timer;
@override
void initState() {
super.initState();
for (var i = 0; i < widget.list.length; i++) {
pageList.add(ImagePage(
width: widget.width, height: widget.height, src: widget.list[i]));
}
_pageController = PageController(initialPage: 0);
timer = Timer.periodic(const Duration(seconds: 3), (t) {
_pageController.animateToPage((_currentIndex + 1) % pageList.length,
duration: const Duration(microseconds: 1000), curve: Curves.linear);
});
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
SizedBox(
height: widget.height,
child: PageView.builder(
controller: _pageController,
onPageChanged: (index) {
setState(() {
_currentIndex = index % pageList.length;
});
},
itemCount: 1000,
itemBuilder: (context, index) {
return pageList[index % pageList.length];
}),
),
Positioned(
left: -5,
right: 0,
bottom: 2,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(pageList.length, (index) {
return Container(
margin: const EdgeInsets.all(5),
height: 10,
width: 10,
decoration: BoxDecoration(
color: _currentIndex == index ? Colors.blue : Colors.grey,
borderRadius: BorderRadius.circular(5)),
);
}).toList(),
))
],
);
}
@override
void dispose() {
super.dispose();
timer.cancel();
_pageController.dispose();
}
}
class ImagePage extends StatelessWidget {
final double width;
final double height;
final String src;
const ImagePage(
{super.key,
this.width = double.infinity,
this.height = 200,
required this.src});
@override
Widget build(BuildContext context) {
return Container(
width: width,
height: height,
child: Image.network(
src,
fit: BoxFit.cover,
),
);
}
}
-
AutomaticKeepAliveClientMixin 缓存
类 with AutomaticKeepAliveClientMixin 一下
example:
class MyContainer extends StatefulWidget {
final int num;
const MyContainer({super.key, required this.num});
@override
State<MyContainer> createState() => _MyContainerState();
}
class _MyContainerState extends State<MyContainer>
with AutomaticKeepAliveClientMixin {
@override
Widget build(BuildContext context) {
print(widget.num);
return Center(
child: Text(
"第${widget.num}屏",
style: Theme.of(context).textTheme.headlineLarge,
),
);
}
@override
bool get wantKeepAlive => true;
}