亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

flutter仿微信底部圖標(biāo)漸變功能的實現(xiàn)代碼

 更新時間:2020年04月15日 14:55:46   作者:今天你摸魚了嗎  
這篇文章主要介紹了flutter仿微信底部圖標(biāo)漸變功能,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

先給大家展示下效果圖,感覺不錯請參考實例代碼。

實現(xiàn)思路

在flutter中,如果想實現(xiàn)上面的頁面切換效果,必然會想到pageView。pageView的controller可以監(jiān)聽到pageView的滾動事件,也可以獲取pageView滾動的位置,所以我們在滾動事件中根據(jù)位置去改變對應(yīng)的圖標(biāo)顏色就可以實現(xiàn)了。

改變圖標(biāo)顏色

圖標(biāo)是從微信中提取出來的,都是webp格式的圖片。要改變圖片顏色可以使用ImageIcon這個組件。

ImageIcon會把一張圖片變成單色圖片,所以只要圖片沒有多色的要求,就可以用這個組件。

既然能改變顏色了,我們也需要知道pageView滾動的時候究竟要改什么顏色。從一個頁面滾動到另一個頁面的過程中,顏色都是線性漸變的,要獲取這個過程中的顏色可以使用flutter的Color類提供的lerp方法,作用是獲取兩種顏色之間的線性差值

里面有3個參數(shù),a和b都是顏色,t是夾在0到1之間的,當(dāng)t為0時返回a,當(dāng)t為1時返回b

也就是在滾動事件中,計算出 t ,根據(jù) t 改變圖標(biāo)顏色就可以實現(xiàn)上面的效果了。

pageController.addListener(() {
   int currentPage = pageController.page.toInt();
   //當(dāng)前頁面的page是double類型的, 把它減去當(dāng)前頁面的int類型就可以得出當(dāng)前頁面到下一個頁面的偏移量了
   double t = pageController.page - currentPage;
   //根據(jù)上一次的頁面位置獲得方向
   if (lastPage <= pageController.page) {
    //向右滑動時currentPage是當(dāng)前頁
    //從當(dāng)前頁過渡到下一頁
    streamController.sink.add(StreamModel(
      timeline: t, index: currentPage, gotoIndex: currentPage + 1));
   } else {
    //向左滑動時currentPage是上一頁
    //從當(dāng)前頁過渡到上一頁
    streamController.sink.add(StreamModel(
      timeline: t, index: currentPage + 1, gotoIndex: currentPage));
   }
   lastPage = pageController.page;
  });

上面代碼中currentPage的值舉個例子:當(dāng)前page是1,要滑動到2,那么它的值是1.11...1.21...這樣一直到2,所以在這個過程中currentPage是當(dāng)前頁。如果當(dāng)前page是4,要滑動到3的時候,它的值是3.99...3.81...這樣一直到3,在這個過程中currentPage就是上一頁了。

t 的計算就更簡單了,1.11-1=0.11,3.99-3=0.99  .....

管理圖標(biāo)顏色

因為我是用了自帶的底部導(dǎo)航BottomNavigationBar,在pageController的滾動事件中改變圖標(biāo)顏色太麻煩了,所以用了Stream來管理圖標(biāo)的狀態(tài)。使用Stream創(chuàng)建一個多訂閱的管道,讓所有圖標(biāo)都訂閱它,然后在滑動事件中把需要的數(shù)據(jù)都發(fā)送給所有圖標(biāo)。

需要的數(shù)據(jù):

class StreamModel {
 const StreamModel({this.timeline, this.index, this.gotoIndex});
 
 final double timeline;
 final int index;
 final int gotoIndex;
}

圖標(biāo)組件

構(gòu)造方法設(shè)置一個index,方便判斷圖標(biāo)是哪個。

使用StreamBuilder包住要改變顏色的組件,并且綁定從構(gòu)造函數(shù)設(shè)置的StreamController。

在StreamBuilder中根據(jù)pageView滾動事件傳進來的參數(shù)控制圖標(biāo)顏色。

class BottomNavIcon extends StatelessWidget {
  final StreamController<StreamModel> streamController;
  final int index;
  final String img;
   final String title;
   final double fontSize;
   Color _color;
   Color _activeColor;
   final bool isActive;
  BottomNavIcon(this.title, this.img, this.index,
   {@required this.streamController,
   this.isActive = false,
   this.fontSize = 18.0,
   Color color = Colors.grey,
   Color activeColor = Colors.blue}) {
  _color = isActive ? activeColor : color;
  _activeColor = isActive ? color : activeColor;
  }
  @override
  Widget build(BuildContext context) {
  return StreamBuilder(
    stream: streamController.stream,
    builder: (BuildContext context, AsyncSnapshot snapshot) {
     final StreamModel data = snapshot.data;
     double t = 0.0;
     if (data != null) {
      //開始的index
      if (data.index == index) {
       t = data.index > data.gotoIndex
         ? data.timeline
         : 1.0 - data.timeline;
       print("this${data.index}:${t}");
      }
      //結(jié)束的index
      if (data.gotoIndex == index) {
       t = data.index > data.gotoIndex
         ? 1.0 - data.timeline //開始的index大于結(jié)束的index方向向左
         : data.timeline; //小于方向向右
       //過渡到的圖標(biāo)顏色的插值超過0.6時, 個人感覺當(dāng)前顏色和結(jié)束的哪個顏色相差太多,
       //所以超過0.6時恢復(fù)默認(rèn)顏色
       t = t >= 0.6 ? 1 : t;
       print("goto${data.gotoIndex}:${t}");
      }
     }
     if (t > 0.0 && t < 1.0) {
      //color.lerp 獲取兩種顏色之間的線性插值
      return Column(
       children: <Widget>[
        ImageIcon(AssetImage(this.img),
          color: Color.lerp(_color, _activeColor, t)),
        Text(title,
          style: TextStyle(
            fontSize: fontSize,
            color: Color.lerp(_color, _activeColor, t))),
       ],
      );
     }
     return Column(
      children: <Widget>[
       ImageIcon(AssetImage(this.img),
         color:
           Color.fromRGBO(_color.red, _color.green, _color.blue, 1)),
       Text(title,
         style: TextStyle(
           fontSize: fontSize,
          color: Color.fromRGBO(
             _color.red, _color.green, _color.blue, 1))),
      ],
     );
    });
   }
  }

圖標(biāo)的顏色都是當(dāng)前的(index == data.index)漸漸變淺,要滾動到(index==data.gotoIndex)的圖標(biāo)顏色漸深

創(chuàng)建多訂閱的管道(Stream)

final StreamController<StreamModel> streamController =
  StreamController.broadcast();
加載圖標(biāo)
for (int i = 0; i < pages.length; i++) {
   TabBarModel model = pages[i];
   bars.add(
    BottomNavigationBarItem(
     icon: BottomNavIcon(
      model.title,
      'assets/images/tabbar_' + model.icon + '_c.webp',
      i,
      streamController: streamController,
     ),
     activeIcon: BottomNavIcon(
      model.title,
      'assets/images/tabbar_' + model.icon + '_s.webp',
      i,
      streamController: streamController,
      isActive: true,
     ),
     title: Center(),
    ),
   );
  }

上面代碼的title為Center的原因是已經(jīng)在圖標(biāo)組件中創(chuàng)建了一個顯示標(biāo)題的組件,方便一起設(shè)置顏色。這里就不需要了,但是它的title不允許為null,所以隨便給它一個高寬都是0的組件

結(jié)語

其實這個效果和微信的不是一模一樣,微信的應(yīng)該是選中圖標(biāo)疊加到默認(rèn)圖標(biāo)上面。默認(rèn)圖標(biāo)顏色線性漸變,選中圖標(biāo)透明度漸變。flutter實現(xiàn)這個用自帶的BottomNavigationBar估計不行,可能需要自定義一個底部導(dǎo)航。

第一次寫技術(shù)文章,感覺有點亂,所以貼下完整的代碼地址:

gist: gist.github.com/327100395/9 …
dartPad: dartpad.dev/9dee2497a99…(圖片讀的是本地的,在dartPad中路徑錯誤,所以圖片不顯示)

相關(guān)文章

  • Studio 編譯報錯:compileSdkVersion ''android-24'' requires JDK 1.8 or later to compile.的解決辦法

    Studio 編譯報錯:compileSdkVersion ''android-24'' requires JDK 1.

    今天小編就為大家分享一篇關(guān)于Studio編譯報錯:compileSdkVersion 'android-24' requires JDK 1.8 or later to compile.的解決辦法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-10-10
  • Android取消EditText自動獲取焦點默認(rèn)行為

    Android取消EditText自動獲取焦點默認(rèn)行為

    在項目中,一進入一個頁面, EditText默認(rèn)就會自動獲取焦點,很是郁悶,Android 如何讓EditText不自動獲取焦點?于是搜集整理一番,曬出來和大家分享,希望對你們有所幫助
    2012-12-12
  • Android實現(xiàn)閃屏及注冊和登錄界面之間的切換效果

    Android實現(xiàn)閃屏及注冊和登錄界面之間的切換效果

    這篇文章主要介紹了Android實現(xiàn)閃屏及注冊和登錄界面之間的切換效果,實現(xiàn)思路是先分別實現(xiàn)閃屏、注冊界面、登錄界面的活動,再用Intent將相關(guān)的活動連接起來,實現(xiàn)不同活動之間的跳轉(zhuǎn),對android 實現(xiàn)閃屏和界面切換感興趣的朋友一起看看吧
    2016-11-11
  • Android Service詳解及示例代碼

    Android Service詳解及示例代碼

    本文主要介紹Android Service,在Android應(yīng)用開發(fā)過程中,Service 會經(jīng)常用到,這里對Service 的概念,生命周期等做了詳細(xì)介紹,并附示例代碼,有需要的朋友可以參考下
    2016-08-08
  • Android入門之BroadCast模擬實現(xiàn)異地登錄事件發(fā)生后的主動退出

    Android入門之BroadCast模擬實現(xiàn)異地登錄事件發(fā)生后的主動退出

    隨著對BroadCast的越來越深入,我們今天要實現(xiàn)一個稍微復(fù)雜一點的BroadCast。即只允許一個設(shè)備登錄一個帳號時,APP會彈一個對話框如:您的賬號在別處登錄,請重新登陸!感興趣的可以了解一下
    2022-12-12
  • Android第三方微信支付教程

    Android第三方微信支付教程

    這篇文章主要為大家詳細(xì)介紹了Android第三方微信支付教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-08-08
  • Android編程實現(xiàn)自定義Tab選項卡功能示例

    Android編程實現(xiàn)自定義Tab選項卡功能示例

    這篇文章主要介紹了Android編程實現(xiàn)自定義Tab選項卡功能,結(jié)合完整實例形式分析了Android自定義tab選項卡的遍歷、設(shè)置及屬性操作相關(guān)技巧,需要的朋友可以參考下
    2017-02-02
  • Android自定義View中attrs.xml的實例詳解

    Android自定義View中attrs.xml的實例詳解

    這篇文章主要介紹了Android自定義View中attrs.xml的實例詳解的相關(guān)資料,在自定義View首先對attrs.xml進行布局的實現(xiàn)及屬性的應(yīng)用,需要的朋友可以參考下
    2017-07-07
  • 安卓(android)仿電商app商品詳情頁按鈕浮動效果

    安卓(android)仿電商app商品詳情頁按鈕浮動效果

    很多電商類app的商品詳情頁(其他app也有類似效果,比如qq音樂)都有這么一個效果:當(dāng)用戶向上滑動頁面內(nèi)容超過一定距離后,中間的標(biāo)題欄會卡在頂部,往下拉回到固定高度后又會消失。那么如何實現(xiàn)這個效果呢?跟著小編一起來學(xué)習(xí)學(xué)習(xí)。
    2016-08-08
  • Android實現(xiàn)在列表List中顯示半透明小窗體效果的控件用法詳解

    Android實現(xiàn)在列表List中顯示半透明小窗體效果的控件用法詳解

    這篇文章主要介紹了Android實現(xiàn)在列表List中顯示半透明小窗體效果的控件用法,結(jié)合實例形式分析了Android半透明提示框的實現(xiàn)與設(shè)置技巧,需要的朋友可以參考下
    2016-06-06

最新評論