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