最終效果
項(xiàng)目地址
演示代碼地址
image
實(shí)現(xiàn)方法
使用PageView
組件
NotificationListener
可以監(jiān)聽PageView
的改變革骨,比如滑動(dòng)的距離拧篮,頁面索引等蠢壹,目前只使用的了索引区匠。里面的一些方法挺有用的负蠕。
NotificationListener(
onNotification: (ScrollNotification scrollInfo) {
// print(scrollInfo.metrics.pixels);
// print(scrollInfo.metrics.viewportDimension);
// print(_controller.page);
this.setState(() {
this.activeIndex = _controller.page.round();
});
return true;
},
child: PageView(
controller: _controller,
children: pictrueList
.map((PictrueData data) => FadeInImage.assetNetwork(
placeholder: "lib/assets/loading_img.gif",
image: data.url,
fit: BoxFit.cover,
alignment: Alignment.center,
))
.toList()),
),
AnimatedContainer
使用AnimatedContainer
組件保證切換以后會(huì)有流程的過渡效果,表現(xiàn)的會(huì)平滑一些蛙埂。
完整代碼
AnimatedContainer(
duration: Duration(milliseconds: 300),
height: pictrueData.height * deviceWidth / pictrueData.width,
curve: Curves.ease,
child: Stack(
children: <Widget>[
NotificationListener(
onNotification: (ScrollNotification scrollInfo) {
// print(scrollInfo.metrics.pixels);
// print(scrollInfo.metrics.viewportDimension);
// print(_controller.page);
this.setState(() {
this.activeIndex = _controller.page.round();
});
return true;
},
child: PageView(
controller: _controller,
children: pictrueList
.map((PictrueData data) => FadeInImage.assetNetwork(
placeholder: "lib/assets/loading_img.gif",
image: data.url,
fit: BoxFit.cover,
alignment: Alignment.center,
))
.toList()),
),
Positioned(
bottom: 10.0,
right: 10.0,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 5.0, vertical: 3.0),
decoration: BoxDecoration(
color: Color.fromRGBO(0, 0, 0, 0.5),
borderRadius: BorderRadius.circular(20.0)),
child: Text(
'${activeIndex + 1}/${pictrueList.length}',
style: TextStyle(
color: const Color(0xffffffff), fontSize: 10.0),
),
),
)
],
),
)
重點(diǎn)
首先,返回?cái)?shù)據(jù)需要包含圖片的寬高信息遮糖,就像這樣:
List<PictrueData> pictrueList = [
PictrueData(
width: 1920.0,
height: 1152.0,
url:
"http://admin.soscoon.com/uploadImages/24294a8960f7cec4a5bb77276b8d1804eddc0023.jpg"),
PictrueData(
width: 550.0,
height: 810.00,
url:
"http://admin.soscoon.com/uploadImages/72041ef01b9c8dd543511968d8659817c0086145.jpeg"),
PictrueData(
width: 1600.0,
height: 900.00,
url:
"http://admin.soscoon.com/uploadImages/c236aa0af948e5d8812d23bd9eb1878682f247d8.jpg"),
PictrueData(
width: 1900.0,
height: 1200.00,
url:
"http://admin.soscoon.com/uploadImages/41b2b4490204912f345b80be4fa88d7f5c9487a7.jpg"),
PictrueData(
width: 1920.0,
height: 1000.00,
url:
"http://admin.soscoon.com/uploadImages/52a138c4dfcfbaab74daec69f128a2dd6dbf558f.jpg"),
];
如果返回的只有圖片信息沒有寬高數(shù)據(jù)可以使用以下方法去獲得圖片的信息,這樣也可以得到圖片的寬高信息绣的,不太建議,還是直接叫后端給欲账,我們也方便處理屡江,要是后端說他們給不了就拿上磚頭去叫他們加,就想偷懶赛不。
class MyHomePage extends StatelessWidget {
Widget build(BuildContext context) {
Image image = new Image.network(
'https://timgsa.baidu.com/timg?image&quality=80&size=b10000_10000&sec=1564812422&di=a113f4b98d25442643ad9236f01ecbf5&src=http://hbimg.b0.upaiyun.com/0338cbe93580d5e6b0e89f25531541d455f66fda4a6a5-eVWQaf_fw658');
Completer<ui.Image> completer = new Completer<ui.Image>();
image.image.resolve(new ImageConfiguration()).addListener(
ImageStreamListener(
(ImageInfo info, bool _) => completer.complete(info.image)));
return new Scaffold(
appBar: new AppBar(
title: new Text("Image Dimensions Example"),
),
body: new ListView(
children: [
new FutureBuilder<ui.Image>(
future: completer.future,
builder: (BuildContext context, AsyncSnapshot<ui.Image> snapshot) {
if (snapshot.hasData) {
return new Text(
'${snapshot.data.width}x${snapshot.data.height}',
style: Theme.of(context).textTheme.display3,
);
} else {
return new Text('Loading...');
}
},
),
image,
],
),
);
}
}
自適應(yīng)輪播圖的高度我們需要原始圖片的寬高比惩嘉,或者知道原始圖的寬高。顯示的時(shí)候按照原始的寬高比進(jìn)行等比例縮放踢故。
_controller.page
獲取到的是一個(gè)浮點(diǎn)數(shù)文黎,類似1.0325441
,使用round
四舍五入出現(xiàn)的效果就是我們拖到一半或以上就可以得到下一個(gè)activeIndex
惹苗,activeIndex
是一個(gè)整數(shù)。
_controller.page
flutter: 0.01314531968164951
flutter: 0.026430343836238882
flutter: 0.03609217958503115
flutter: 0.048169474271021494
flutter: 0.0517926626768186
flutter: 0.0590390394884128
flutter: 0.06386995736280894
flutter: 0.9918596275657323
flutter: 0.9928677347556618
flutter: 0.9948281247819616
flutter: 0.9955746971008173
flutter: 0.9966901944924708
flutter: 0.9971838269533462
flutter: 0.9978950491069947
flutter: 0.9981962948156735
flutter: 0.998685063281176
flutter: 1.0
// 當(dāng)前展示的banner圖數(shù)據(jù)
PictrueData pictrueData = pictrueList[activeIndex];
// 等比縮放算出現(xiàn)在的高度
height: pictrueData.height * deviceWidth / pictrueData.width,
我們動(dòng)態(tài)獲取了圖片的寬度以后放入AnimatedContainer
就可以有過渡效果耸峭,真機(jī)和模擬器測試都很流暢桩蓉,可以已60幀渲染。