Flutter100行輕鬆實現自定義P站和油管的Logo及自由切換Logo功能
- 2019 年 11 月 21 日
- 筆記
版權聲明:本文為博主原創文章,未經博主允許不得轉載。 https://www.jianshu.com/p/004b7a56bb51
轉載請標明出處: https://www.jianshu.com/p/004b7a56bb51 本文出自 AWeiLoveAndroid的博客
本文首發在公眾號Flutter那些事,未經允許,嚴禁轉載。
本文配套代碼已經傳到了github,歡迎朋友們給個star
,感謝大家,希望能在幫助大家的同時,麻煩大家給個打賞買口水喝,謝謝大家。
開源倉庫地址: https://github.com/AweiLoveAndroid/Flutter-learning/
Flutter系列博文鏈接 ↓:
工具安裝:
Flutter基礎篇:
- 谷歌Flutter1.0正式版發佈
- Flutter基礎篇(1)– 跨平台開發框架和工具集錦
- Flutter基礎篇(2)– 老司機用一篇博客帶你快速熟悉Dart語法
- Flutter基礎篇(3)– Flutter基礎全面詳解
- Flutter基礎篇(4)– Flutter填坑全面總結
- Flutter基礎篇(5)– Flutter代碼模板,解放雙手,提高開發效率必備
- Flutter基礎篇(6)– 水平和垂直布局詳解
- Flutter基礎篇(7)– Flutter更新錯誤全面解決方案(圖文+視頻講解)
- Flutter基礎篇(8)– Flutter for Web詳細介紹
- Flutter基礎篇(9)– 手把手教你用Flutter實現Web頁面編寫
- Flutter1.9升級體驗總結(Flutter Web 1.9最新版本填坑指南)
- Flutter實現Adobe全家桶Logo列表功能
- Flutter100行輕鬆實現自定義P站和油管的Logo及自由切換Logo功能
Flutter進階篇:
- Flutter進階篇(1)– 手把手帶你快速上手調試Flutter項目
- Flutter進階篇(2)– Flutter路由詳解
- Flutter進階篇(3)– Flutter 的手勢(GestureDetector)分析詳解
- Flutter進階篇(4)– Flutter的Future異步詳解
- Flutter進階篇(5)– 使用Flutter創建插件詳解並發佈到Pub庫
- Flutter進階篇(6)– PageStorageKey、PageStorageBucket和PageStorage使用詳解
- Flutter進階篇(7)– Flutter路由輕量級框架FRouter
Dart語法系列博文鏈接 ↓:
Dart語法基礎篇:
- Flutter基礎篇(2)– 老司機用一篇博客帶你快速熟悉Dart語法(這是Dart語法系列的第一篇)
- Dart的語法詳解系列篇(二)– 類與函數
- Dart的語法詳解系列篇(三)– mixin入門
- Dart的語法詳解系列篇(四)– 泛型、異步、庫等有關詳解
- Dart2.6正式版發佈,支持編譯為native可執行文件
Dart語法進階篇:
本文首發在公眾號Flutter那些事,未經允許,嚴禁轉載。
本文配套代碼已經傳到了github,歡迎朋友們給個star
,感謝大家,希望能在幫助大家的同時,麻煩大家給個打賞買口水喝,謝謝大家。
開源倉庫地: https://github.com/AweiLoveAndroid/Flutter-learning/
上次跟大家分享了Flutter實現Adobe全家桶Logo列表功能 ,主要通過一個簡單的案例,帶領大家了解如何在需求開發不斷變更的時候,學會封裝和具有架構核心思想。今天給大家帶來的是Flutter僅用100行代碼輕鬆實現自定義P站和油管的Logo以及自由切換Logo的功能。通過這篇文章,你可以學到兩個知識點:自定義你喜歡的Logo風格;學會通過一個組件控制另一個組件的功能。下面詳細介紹我的實現思路和步驟。
本文內容圖文並茂,希望大家可以認真看完。為了避免大家犯困,我這裡特意準備了本文配套的兩個視頻,下面這個是騰訊視頻的播放鏈接:
騰訊視頻鏈接:Flutter100行輕鬆實現自定義P站和油管的Logo及自由切換Logo功能
如果你喜歡去B站觀看本文配套的視頻講解,請點擊Bilibili鏈接:
B站鏈接: Flutter100行輕鬆實現自定義P站和油管的Logo及自由切換Logo功能
第一部分:自定義Logo
你可以根據自己的心情定義你自己的Logo樣式,我這裡以「YouTube」和「PornHub」的Logo為模板,你可以隨意更改你的設置,然後達到自定義Logo的目的。下面詳細講解一下如何實現這兩個Logo模板的。

image
1.首先這裡是一個Contanner
組件,給它設置背景,邊框,文字內容,以及對應的前景和背景顏色。
示例代碼如下所示:
@override Widget build(BuildContext context) { return Container( margin: EdgeInsets.all(30), width: widget.bgWidth, height: widget.bgHeight, color: widget.bgColor, child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Padding( padding: EdgeInsets.only(left: 0, top: 0, right: 5, bottom: 0), child: Text( widget.leftText, style: TextStyle( fontSize: widget.leftTextSize, color: widget.leftTextColor, fontWeight: FontWeight.bold, ), ), ), Container( decoration: BoxDecoration( color: widget.rightBgColor, border: Border.all( color: widget.rightBgColor, width: 8.0, ), borderRadius: BorderRadius.circular( widget.rightBgBorderRadius, ), ), padding: EdgeInsets.all(5), child: Text( widget.rightText, style: TextStyle( fontSize: widget.leftTextSize, color: widget.rightTextColor, fontWeight: FontWeight.bold, ),// TextStyle ),// Text ),// Container ],// Row children ),// Row );// Container }
2.傳入所需的變量類型
這裏面需要傳入的變量有很多,包括以下這些:
// 全局背景顏色 Color bgColor; // 全局內容寬度 double bgWidth; // 全局內容高度 double bgHeight; // 左側文字內容 String leftText; // 左側文字大小 double leftTextSize; // 左側文字顏色 Color leftTextColor; // 右側背景顏色 Color rightBgColor; // 右側邊框圓角大小 double rightBgBorderRadius; // 右側文字內容 String rightText; // 右側文字顏色 Color rightTextColor;
3.構造函數裏面傳入這些變量,並對每一個變量做一個初始化
代碼如下所示:
Contents( {Key key, this.bgColor = Colors.black, this.bgWidth = 300, this.bgHeight = 300, this.leftText = 'Porn', this.leftTextSize = 30, this.leftTextColor = Colors.white, this.rightBgColor = const Color.fromARGB(255, 254, 155, 0), this.rightBgBorderRadius = 5, this.rightText = 'Hub', this.rightTextColor = Colors.black}) : super(key: key);
4.接下來我們可以使用這個類
下面這個就是PornHub
風格的樣式:
Scaffold( appBar: AppBar( title: Text('Flutter創建自定義Logo'), ), body: Contents( bgColor: Colors.black, bgWidth: 300, bgHeight: 300, leftText: 'Porn', leftTextSize: 60, leftTextColor: Colors.white, rightBgColor: Color.fromARGB(255, 254, 155, 0), rightBgBorderRadius: 5, rightText: 'Hub', rightTextColor: Colors.black, ), );
如果我們只使用:body: Contents(),
,啥屬性都不填寫,默認就是PornHub
風格,我們看一下運行效果如下圖所示:

效果圖
母胎單身的我不知道你們在笑什麼。

image
5.你也可以自定義其它的樣式
比如以下幾個示例:
body:ListView( children: <Widget>[ Contents( bgWidth: 150, bgHeight: 150, leftText: '${String.fromCharCodes(Runes('u{1f525}'))}Tokyo', rightText: 'Hot', ), Contents( bgWidth: 150, bgHeight: 150, leftText: 'Git', rightText: 'Hub', ), Contents( bgWidth: 150, bgHeight: 150, leftText: 'Flutter', rightText: 'dev', ), Contents( bgWidth: 150, bgHeight: 150, leftText: '韋哥的', rightText: '博客', ), Contents( bgWidth: 150, bgHeight: 150, leftText: 'Developer', rightText: 'Group', ), ], ),
上例中有一個String.fromCharCodes(Runes('u{1f525}'))
這個用法是一個比較特殊的用法,詳細介紹可以查看Flutter基礎篇(2)– 老司機用一篇博客帶你快速熟悉Dart語法,這裏面的第四條:數據類型
,裏面有詳細的介紹,這裡就不再講解了。我們看看效果圖如下圖所示:

image
我的天啊,這個「PornHub
」風格的Logo太有魔性了,我笑出了豬叫。

image
6.同理可以自定義YouTube風格的Logo
只需要更改傳入的參數類型,即可實現YouTube
的Logo風格了,示例如下:
Contents( bgColor: Color.fromARGB(255, 238, 28, 27), bgWidth: 150, bgHeight: 150, leftText: 'You', leftTextSize: 40, leftTextColor: Colors.white, rightBgColor: Colors.white, rightBgBorderRadius: 10, rightText: 'Tube', rightTextColor: Color.fromARGB(255, 238, 28, 27), ),
效果如下圖所示:

image
同理把上述ListView的內容,對應的改成YouTube
風格的相關配置,即可輕鬆實現YouTube
風格的Logo樣式了
效果如下圖所示:

image
7.除此之外你還可以自定義各種類型的Logo風格
這類橫向的都是文字類型Logo很難收集,我花了很長時間才找到的,所以就照葫蘆畫瓢做了這些Logo,截圖如下所示:

Flutter創造更多自定義Logo
【注意】: 這裡的Logo都是百度到的,然後自己試着用上述代碼模板仿製出來了,僅作為學習使用,嚴禁商用,這部分的代碼就不提供了,希望大家理解。

image
第二部分:自由切換Logo功能(這個很牛逼了)
1.封裝InheritedWidget類
封裝一個類繼承自InheritedWidget
類,把我們要操作的內容傳入即可。
【Tips:】為什麼要用InheritedWidget
類,因為直接操作是沒反應的,而使用它可以讓不同層級(樹形結構)的組件之間相互交操作,所以很牛逼啊,不用不行。

image
下面看看代碼是怎麼寫的:
class MyInheritedWidget extends InheritedWidget { final String texts; final Function onTap; final Widget showWidgetContents; final bool isChange; const MyInheritedWidget( {Key key, this.texts, this.onTap, this.showWidgetContents, this.isChange, child}) : super(key: key, child: child); @override bool updateShouldNotify(MyInheritedWidget oldWidget) { return oldWidget.showWidgetContents != showWidgetContents || oldWidget.isChange != isChange || oldWidget.texts != texts; } static MyInheritedWidget of(BuildContext context) { return context.inheritFromWidgetOfExactType(MyInheritedWidget); } }
2.修改body的具體內容頁面
ListView的內容修改如下,替換成使用 MyInheritedWidget
操作我們的組件:
body: ListView( children: <Widget>[ MyInheritedWidget.of(context).showWidgetContents, RaisedButton( onPressed: () { MyInheritedWidget.of(context).onTap(); }, child:Text( '${MyInheritedWidget.of(context).texts.toString()}' ), ), ], ),
3.在主頁面裏面修改邏輯交互的操作內容
把我們的操作對象逐個存入給MyInheritedWidget
,然後包裹住我們的具體頁面內容MyHomePage
。
@override Widget build(BuildContext context) { return new MyInheritedWidget( texts: texts, onTap: changeWidget, showWidgetContents: showWidgetContents, isChange: isChange, child: new MyHomePage(), ); }
4.當我們點擊按鈕時,changeWidget()
函數會被調用,按鈕文字和Logo都會跟隨更改。
changeWidget() { setState(() { if (isChange == true) { showWidgetContents = new Contents().pornhub; texts = '切換至 YouTube Logo'; isChange = !isChange; } else { showWidgetContents = Contents().youtube; // showWidgetContents = Contents().suning; texts = '切換至 PornHub Logo'; isChange = !isChange; } }); return showWidgetContents; }
(大家心想:博主真是太厲害了,不多說了,趕緊拿個筆記下來!哈哈哈。。。)

image
默認文字是「切換至PornHub Logo」,默認Logo是「YouTube」。當我點擊按鈕的時候,文字變成「切換至YouTube Logo」,Logo變成「PornHub 」,當我再次點擊,就會還原層默認的樣式。
最後讓我們看看效果圖,如下所示:

image