Flutter實現(xiàn)馬蜂窩小紅書自適應(yīng)高度輪播圖

最終效果

項目地址

演示代碼地址

image

實現(xiàn)方法

使用PageView組件

NotificationListener可以監(jiān)聽PageView的改變,比如滑動的距離,頁面索引等,目前只使用的了索引。里面的一些方法挺有用的。

              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組件保證切換以后會有流程的過渡效果,表現(xiàn)的會平滑一些。

完整代碼

        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),
                  ),
                ),
              )
            ],
          ),
        )

重點

首先,返回數(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)輪播圖的高度我們需要原始圖片的寬高比,或者知道原始圖的寬高。顯示的時候按照原始的寬高比進行等比例縮放。

_controller.page獲取到的是一個浮點數(shù),類似1.0325441,使用round四舍五入出現(xiàn)的效果就是我們拖到一半或以上就可以得到下一個activeIndex,activeIndex是一個整數(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,

我們動態(tài)獲取了圖片的寬度以后放入AnimatedContainer就可以有過渡效果,真機和模擬器測試都很流暢,可以已60幀渲染。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,621評論 1 32
  • 渾渾噩噩的8天馬上就要結(jié)束了,感覺就熬熬夜睡睡懶覺見見閨蜜,日子就這樣悄悄溜走了,明天一早要開始新的旅程。年輕人...
    蘿蘭閱讀 253評論 0 0
  • 下午跑去看書,挑了本余華的《活著》。 好沒出息,淚點太低,好幾次眼淚盈眶,差點要大哭出來。 生命里難得的溫情將被一...
    一生追夢的人閱讀 481評論 4 5
  • 書名:終身成長 作者: [美] 卡羅爾·德韋克 副標(biāo)題:重新定義成功的思維模式 原作名:MINDSET: THE ...
    無00閱讀 603評論 0 6

友情鏈接更多精彩內(nèi)容