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基礎篇:

Flutter進階篇:

Dart語法系列博文鏈接 ↓:

Dart語法基礎篇:

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樣式,我這裡以「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

只需要更改傳入的參數類型,即可實現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