上一节,我们制作了轮播图,在这里来对这个轮播图进行一点点优化。
在浏览应用时,很多应用都会有在页面滚动时,出现轮播图慢慢消失,导航不断清晰的效果,那么这里就来制作这样的效果。
首先我们要将首页的Column,改写成ListView,让首页滚动起来。
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: Center(
child: ListView( //这里原来是Column,现在改写成listview
children: <Widget>[
Container(
height: 160,
child: Swiper( //这里是我们的轮播图
itemCount: _imageUrls.length, //轮播图数量
autoplay: true, //自动播放
itemBuilder: (BuildContext context,int index){ //在这个里面编写展示的每个内容
return Image.network( //通过远程链接获取图片
_imageUrls[index], //获取图片url
fit: BoxFit.fill, //展示方式
);
},
pagination: SwiperPagination(), //添加轮播下方的小点
),
)
],
),
)
);
}
现在还是无法滚动,因为高度不够。我们还需要在listview中添加一个填充高度的容器。
child: ListView(
children: <Widget>[
Container(
height: 160,
child: Swiper( //这里是我们的轮播图
itemCount: _imageUrls.length, //轮播图数量
autoplay: true, //自动播放
itemBuilder: (BuildContext context,int index){ //在这个里面编写展示的每个内容
return Image.network( //通过远程链接获取图片
_imageUrls[index], //获取图片url
fit: BoxFit.fill, //展示方式:充满父容器
);
},
pagination: SwiperPagination(), //添加轮播下方的小点
),
),
Container(
height: 800,
child: ListTile(
title: Text('哈哈'),
),
)
],
),
如果你是刘海屏,你会发现轮播图并没有紧贴顶部,我们希望我们的轮播图可以紧贴顶部。这里就需要用到一个MediaQuery.removePadding。那么我们就用MediaQuery.removePadding来替代Center组件
MediaQuery.removePadding( //移除默认的padding,可以移除iphone刘海屏的距离,不会直接移除需要removeTop: true配合
removeTop: true, //移除顶部距离
context: context,
child: NotificationListener( //监听组件,可以监听列表组件的滚动
// ignore: missing_return
onNotification: (scrollNotification){ //监听列表滚动
if(scrollNotification is ScrollUpdateNotification && scrollNotification.depth == 0){ //触发第0个组件,也就是listview
//列表滚动时调用
_onScroll(scrollNotification.metrics.pixels); //传入的参数为滚动距离
}
},
child: ListView(
children: <Widget>[
Container(
height: 160,
child: Swiper( //这里是我们的轮播图
itemCount: _imageUrls.length, //轮播图数量
autoplay: true, //自动播放
itemBuilder: (BuildContext context,int index){ //在这个里面编写展示的每个内容
return Image.network( //通过远程链接获取图片
_imageUrls[index], //获取图片url
fit: BoxFit.fill, //展示方式:充满父容器
);
},
pagination: SwiperPagination(), //添加轮播下方的小点
),
),
Container(
height: 800,
child: ListTile(
title: Text('哈哈'),
),
)
],
),
)
),
MediaQuery.removePadding并不能直接去除默认顶部距离,而是要通过removeTop: true来实现。同时我们也引用了一个监听组件NotificationListener,用来监听屏幕的滚动。
现在我们来创建滚动触发的方法:
const APPBAR_SCROLL_OFFSET = 100 ; //当滚动到100时变量
double appBarAlpha = 0; //透明值
//listview滚动调用的函数
_onScroll(offset){
double alpha = offset/APPBAR_SCROLL_OFFSET;
if(alpha < 0){
alpha = 0;
}else if(alpha> 1){
alpha = 1;
}
setState(() {
appBarAlpha = alpha;
});
}
这里的offset就是我们滚动页面时传来实时高度。APPBAR_SCROLL_OFFSET我们设置了一个变量,也就是在滚动到100位置之前导航会从透明到半透明,如果超过100的位置就会透明消失。变为不透明。
现在我们正式来添加导航,这里我为了大家看起来直观方便,直接把全部代码放出:
import 'package:flutter/material.dart';
import 'package:flutter_swiper/flutter_swiper.dart';
const APPBAR_SCROLL_OFFSET = 100 ; //当滚动到100时变量
class HomePage extends StatefulWidget{
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage>{
//轮播图的图片地址
List _imageUrls=[
'http://tcode.net/images/blogupload/timg201908190221.jpeg',
'http://tcode.net/images/blogupload/20190501images.jpeg',
'http://tcode.net/images/blogupload/symfony-ubuntu-apachepng-450x191.png'
];
double appBarAlpha = 0; //透明值
//listview滚动调用的函数
_onScroll(offset){
double alpha = offset/APPBAR_SCROLL_OFFSET;
if(alpha < 0){
alpha = 0;
}else if(alpha> 1){
alpha = 1;
}
setState(() {
appBarAlpha = alpha;
});
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: Stack(
children: <Widget>[
MediaQuery.removePadding( //移除默认的padding,可以移除iphone刘海屏的距离,不会直接移除需要removeTop: true配合
removeTop: true, //移除顶部距离
context: context,
child: NotificationListener( //监听组件,可以监听列表组件的滚动
// ignore: missing_return
onNotification: (scrollNotification){ //监听列表滚动
if(scrollNotification is ScrollUpdateNotification && scrollNotification.depth == 0){ //触发第零个组件,也就是listview
//列表滚动时调用
_onScroll(scrollNotification.metrics.pixels); //传入的参数为滚动距离
}
},
child: ListView(
children: <Widget>[
Container(
height: 160,
child: Swiper( //这里是我们的轮播图
itemCount: _imageUrls.length, //轮播图数量
autoplay: true, //自动播放
itemBuilder: (BuildContext context,int index){ //在这个里面编写展示的每个内容
return Image.network( //通过远程链接获取图片
_imageUrls[index], //获取图片url
fit: BoxFit.fill, //展示方式:充满父容器
);
},
pagination: SwiperPagination(), //添加轮播下方的小点
),
),
Container(
height: 800,
child: ListTile(
title: Text('哈哈'),
),
)
],
),
)
),
Opacity( //设置一个透明的appbar ,自定义导航
opacity: appBarAlpha,
child: Container(
height: 80,
decoration: BoxDecoration(color: Colors.white),
child: Center(
child: Padding(
padding: EdgeInsets.only(top: 20),
child: Text('首页'),
),
),
),
)
],
)
);
}
}
效果如下(静态图):