实现一个轮播
在PC端实现轮播一般都是直接使用JavaScript库进行实现.但在Flutter上想要实现一个轮播,可能只有自己写一下了.
轮播的特点:
1. 可以自动播放;
2. 图片可以左右滑动(使用Flutter自带的PageView初始只能向右滑动,不能向左);
3. 可以定义自动播放的间隔时间.
大概就这么几个特点,可以实现个简单的例子.
功能部分
目前仅实现简单功能:
1. 可以自定义网络图片或本地图片(可以混用本地图片和网络图片),
2. 自定义图片切换时间,
3. 自定义是否开启自动轮播.
上述几条可以满足一个简单轮播的需要,如果需要更多功能.可以在此基础上增加.
源码
完整代码: Gitee仓库
/// 轮播组件
///
/// 目前仅实现简单功能:
/// 1. 可以自定义网络图片或本地图片(可以混用本地图片和网络图片),
/// 2. 自定义图片切换时间,
/// 3. 自定义是否开启自动轮播.
///
/// 调用示例:
///
/// ```dart
/// static const List _images = [
/// 'assets/images/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
/// 'assets/images/19aa98b1fcb2781c4fba33d850549jpeg.jpeg',
/// 'https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg',
/// 'https://fuss10.elemecdn.com/9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg',
/// 'https://fuss10.elemecdn.com/d/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg',
/// 'https://fuss10.elemecdn.com/3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg',
/// 'https://fuss10.elemecdn.com/2/11/6535bcfb26e4c79b48ddde44f4b6fjpeg.jpeg',
/// 'https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
/// 'https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg',
/// 'https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg'
/// ];
///
/// ......
///
/// SizedBox(
// width: double.infinity,
// height: 200,
// child: Carousel(
// _images,
// autoPlayer: false,
// ),
// ),
///
/// ```
///
///
///
///
class Carousel extends StatefulWidget {
Carousel(
this.imagesList, {
Key key,
this.autoPlayer = true,
this.seconds = 5,
}) : assert(imagesList.isNotEmpty),
assert(seconds > 2),
super(key: key);
final int _maxPage = 2000000000;
/// 轮播切换间隔秒数.
final int seconds;
/// 是否自动播放
final bool autoPlayer;
final List imagesList;
@override
_CarouselState createState() => new _CarouselState();
}
class _CarouselState extends State {
PageController _pageController;
Timer _timer;
var _currIndex = 0;
@override
void initState() {
super.initState();
if (widget.autoPlayer) {
startTimeout();
}
_pageController = new PageController(initialPage: widget._maxPage);
}
@override
void dispose() {
super.dispose();
_pageController.dispose();
if (_timer != null) {
_timer.cancel();
}
}
void startTimeout() {
var timeout = Duration(seconds: widget.seconds);
Timer.periodic(timeout, (Timer timer) {
var tempIndex = _currIndex + 1;
if (tempIndex >= widget.imagesList.length) {
tempIndex = 0;
}
setState(() {
_timer = timer;
_currIndex = tempIndex;
});
});
}
List getBottomIcon() {
var forLength = widget.imagesList.length;
var res = List();
for (var i = 0; i < forLength; i++) {
if (_currIndex == i) {
res.add(GestureDetector(
/// 选中时的图标,可以更换为图片.
child: Icon(Icons.brightness_1),
onTap: () {
setState(() {
_currIndex = i;
});
},
));
} else {
res.add(GestureDetector(
/// 未选中时的图标,可以更换为图片.
child: Icon(Icons.panorama_fish_eye),
onTap: () {
setState(() {
_currIndex = i;
});
},
));
}
}
return res;
}
@override
Widget build(BuildContext context) {
var width = MediaQuery.of(context).size.width;
return Scaffold(
body: PageView.builder(
controller: _pageController,
onPageChanged: (int index) {
var renderIndex = index - widget._maxPage;
renderIndex = renderIndex % widget.imagesList.length;
if (renderIndex < 0) {
renderIndex += widget.imagesList.length;
}
setState(() {
_currIndex = renderIndex;
});
},
itemBuilder: (BuildContext context, int index) {
var renderIndex = _currIndex - widget._maxPage;
renderIndex = renderIndex % widget.imagesList.length;
if (renderIndex < 0) {
renderIndex += widget.imagesList.length;
}
return Container(
child: Stack(children: [
Center(
child: widget.imagesList[_currIndex].startsWith("https://") ||
widget.imagesList[_currIndex].startsWith("http://")
? CachedNetworkImage(
imageUrl: widget.imagesList[_currIndex],
fit: BoxFit.fill,
width: width,
height: double.infinity,
placeholder: (context, url) =>
CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
)
: FadeInImage(
image: AssetImage(widget.imagesList[_currIndex]),
placeholder: AssetImage("assets/images/loading.gif"),
fit: BoxFit.fill,
width: width,
height: double.infinity,
),
),
Positioned(
left: 2.0,
right: 2.0,
bottom: 10.0,
child: Container(
/// padding: EdgeInsets.all(5.0),
child: widget.imagesList.length > 10
? SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: getBottomIcon(),
),
)
: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: getBottomIcon(),
)))
]));
}),
);
}
}