From 406dea96949b4ce1debb73b81c7487ac30974e9a Mon Sep 17 00:00:00 2001 From: Kun Chen Date: Tue, 19 Oct 2021 17:32:22 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=E8=A7=86=E9=A2=91=E9=A1=B5?= =?UTF-8?q?=E7=BC=96=E5=86=99=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- douban_app/lib/assets/font/CusIcons.dart | 6 + douban_app/lib/components/top_tabs/index.dart | 1 + douban_app/lib/main.dart | 1 + douban_app/lib/views/book/index.dart | 28 +- .../book/tab_pages/movie/top_banner.dart | 87 +-- douban_app/pubspec.yaml | 4 + douban_app/resource/fonts/demo.css | 539 ++++++++++++++++++ douban_app/resource/fonts/demo_index.html | 207 +++++++ douban_app/resource/fonts/iconfont.css | 17 + douban_app/resource/fonts/iconfont.js | 1 + douban_app/resource/fonts/iconfont.json | 16 + douban_app/resource/fonts/iconfont.ttf | Bin 0 -> 3276 bytes 12 files changed, 859 insertions(+), 48 deletions(-) create mode 100644 douban_app/lib/assets/font/CusIcons.dart create mode 100644 douban_app/resource/fonts/demo.css create mode 100644 douban_app/resource/fonts/demo_index.html create mode 100644 douban_app/resource/fonts/iconfont.css create mode 100644 douban_app/resource/fonts/iconfont.js create mode 100644 douban_app/resource/fonts/iconfont.json create mode 100644 douban_app/resource/fonts/iconfont.ttf diff --git a/douban_app/lib/assets/font/CusIcons.dart b/douban_app/lib/assets/font/CusIcons.dart new file mode 100644 index 0000000..a8fad98 --- /dev/null +++ b/douban_app/lib/assets/font/CusIcons.dart @@ -0,0 +1,6 @@ +import 'package:flutter/cupertino.dart'; + +class CusIcons { + static const IconData movie = + const IconData(0xe6bb, fontFamily: "cusIcon", matchTextDirection: true); +} diff --git a/douban_app/lib/components/top_tabs/index.dart b/douban_app/lib/components/top_tabs/index.dart index e69de29..8b13789 100644 --- a/douban_app/lib/components/top_tabs/index.dart +++ b/douban_app/lib/components/top_tabs/index.dart @@ -0,0 +1 @@ + diff --git a/douban_app/lib/main.dart b/douban_app/lib/main.dart index b4feb58..761762f 100644 --- a/douban_app/lib/main.dart +++ b/douban_app/lib/main.dart @@ -41,6 +41,7 @@ class _MyStackPageState extends State { return Scaffold( bottomNavigationBar: BottomNavigationBar( + backgroundColor: Colors.white, currentIndex: _currentIndex, selectedItemColor: Colors.green, selectedFontSize: 14, diff --git a/douban_app/lib/views/book/index.dart b/douban_app/lib/views/book/index.dart index b3f1ae5..05d79e6 100644 --- a/douban_app/lib/views/book/index.dart +++ b/douban_app/lib/views/book/index.dart @@ -1,5 +1,6 @@ import 'package:douban_app/components/top_search/index.dart'; import 'package:douban_app/views/book/tab_pages/movie/index.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:douban_app/views/book/tab_pages/tv.dart'; import 'package:flutter/material.dart'; @@ -10,7 +11,7 @@ class Book extends StatefulWidget { class _BookState extends State with SingleTickerProviderStateMixin { TabController _tabController; - List tabs = ["电影", "电视", "读书", "小说", "音乐", "同城"]; + List tabs = ["电影", "电视", "读书", "原创小说", "音乐", "同城"]; List tabsViews = [ TabMovie(), TabTV(), @@ -19,7 +20,7 @@ class _BookState extends State with SingleTickerProviderStateMixin { TabMovie(), TabTV() ]; - + int curItem = 0; @override void initState() { super.initState(); @@ -34,20 +35,33 @@ class _BookState extends State with SingleTickerProviderStateMixin { backgroundColor: Colors.white, title: TopSearch(), bottom: TabBar( + isScrollable: true, controller: this._tabController, - indicatorColor: Color.fromARGB(255, 25, 25, 25), - indicatorWeight: 2, + // indicatorColor: Color.fromARGB(255, 25, 25, 25), + // indicatorWeight: 2, indicatorSize: TabBarIndicatorSize.label, + indicator: UnderlineTabIndicator( + borderSide: BorderSide(color: Colors.red, width: 2)), + labelColor: Color.fromARGB(255, 25, 25, 25), + unselectedLabelColor: Color.fromARGB(255, 129, 129, 129), + onTap: (index) { + setState(() => curItem = index); + }, tabs: this .tabs .map((item) => Tab( - text: item, + child: Text( + item, + style: TextStyle(fontSize: 12.5.sp), + ), )) .toList(), ), ), - body: TabBarView( - controller: this._tabController, children: this.tabsViews)); + body: Container( + color: Colors.white, + child: TabBarView( + controller: this._tabController, children: this.tabsViews))); } @override diff --git a/douban_app/lib/views/book/tab_pages/movie/top_banner.dart b/douban_app/lib/views/book/tab_pages/movie/top_banner.dart index eadd405..2ddf3e6 100644 --- a/douban_app/lib/views/book/tab_pages/movie/top_banner.dart +++ b/douban_app/lib/views/book/tab_pages/movie/top_banner.dart @@ -1,58 +1,63 @@ -import 'dart:convert'; - import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; class BannerItem { - String icon = ""; - String title = ""; - BannerItem({this.icon = null, this.title = "默认"}); - - Map toMap() { - return { - 'icon': icon, - 'title': title, - }; - } - - factory BannerItem.fromMap(Map map) { - return BannerItem( - icon: map['icon'], - title: map['title'], - ); - } - - String toJson() => json.encode(toMap()); - - factory BannerItem.fromJson(String source) => - BannerItem.fromMap(json.decode(source)); - - @override - String toString() => 'BannerItem(icon: $icon, title: $title)'; + String title; + IconData icon; + BannerItem({ + this.title = "默认", + this.icon = Icons.check_box_outline_blank, + }); } -List _getBanner(List> itemList) { +List _getBanner(List itemList) { return itemList - .map((item) => BannerItem.fromMap(item)) .map((item) => DecoratedBox( - decoration: BoxDecoration(color: Colors.red), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all( + color: Color.fromRGBO(223, 223, 223, 1), + width: 1.w, + ), + borderRadius: BorderRadius.all(Radius.circular(12.r))), + child: InkWell( + onTap: () => { + //TODO: 点击跳转事件 + print("tap") + }, child: Container( - width: 360.w, - padding: EdgeInsets.symmetric(horizontal: 0.0, vertical: 8.0), - child: Text(item.title), + padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.w), + child: Column( + children: [ + Icon( + item.icon, + color: Colors.black54, + ), + Text( + item.title, + style: TextStyle( + fontSize: 10.sp, + color: Colors.black54, + ), + ) + ], + ), ), - )) + ))) .toList(); } Widget TopBanner() { - var children = _getBanner([ - {"title": "你好鸭"}, - ]); + var children = _getBanner( + [ + BannerItem(icon: Icons.search, title: '找电影'), + BannerItem(icon: Icons.bar_chart, title: '豆瓣榜单'), + BannerItem(icon: Icons.schedule, title: '即将上映'), + BannerItem(icon: Icons.video_library, title: '豆瓣片单') + ], + ); return Container( - color: Colors.blue, - padding: EdgeInsets.symmetric(horizontal: 0.0, vertical: 6.0), - child: - Row(mainAxisAlignment: MainAxisAlignment.center, children: children)); + padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 24.w), + child: Wrap(alignment: WrapAlignment.spaceBetween, children: children)); } diff --git a/douban_app/pubspec.yaml b/douban_app/pubspec.yaml index 37213db..5d648b5 100644 --- a/douban_app/pubspec.yaml +++ b/douban_app/pubspec.yaml @@ -48,6 +48,10 @@ flutter: # included with your application, so that you can use the icons in # the material Icons class. uses-material-design: true + fonts: + - family: cusIcon + fonts: + - asset: resource/fonts/iconfont.ttf # To add assets to your application, add an assets section, like this: # assets: diff --git a/douban_app/resource/fonts/demo.css b/douban_app/resource/fonts/demo.css new file mode 100644 index 0000000..a67054a --- /dev/null +++ b/douban_app/resource/fonts/demo.css @@ -0,0 +1,539 @@ +/* Logo 字体 */ +@font-face { + font-family: "iconfont logo"; + src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834'); + src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'), + url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg'); +} + +.logo { + font-family: "iconfont logo"; + font-size: 160px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* tabs */ +.nav-tabs { + position: relative; +} + +.nav-tabs .nav-more { + position: absolute; + right: 0; + bottom: 0; + height: 42px; + line-height: 42px; + color: #666; +} + +#tabs { + border-bottom: 1px solid #eee; +} + +#tabs li { + cursor: pointer; + width: 100px; + height: 40px; + line-height: 40px; + text-align: center; + font-size: 16px; + border-bottom: 2px solid transparent; + position: relative; + z-index: 1; + margin-bottom: -1px; + color: #666; +} + + +#tabs .active { + border-bottom-color: #f00; + color: #222; +} + +.tab-container .content { + display: none; +} + +/* 页面布局 */ +.main { + padding: 30px 100px; + width: 960px; + margin: 0 auto; +} + +.main .logo { + color: #333; + text-align: left; + margin-bottom: 30px; + line-height: 1; + height: 110px; + margin-top: -50px; + overflow: hidden; + *zoom: 1; +} + +.main .logo a { + font-size: 160px; + color: #333; +} + +.helps { + margin-top: 40px; +} + +.helps pre { + padding: 20px; + margin: 10px 0; + border: solid 1px #e7e1cd; + background-color: #fffdef; + overflow: auto; +} + +.icon_lists { + width: 100% !important; + overflow: hidden; + *zoom: 1; +} + +.icon_lists li { + width: 100px; + margin-bottom: 10px; + margin-right: 20px; + text-align: center; + list-style: none !important; + cursor: default; +} + +.icon_lists li .code-name { + line-height: 1.2; +} + +.icon_lists .icon { + display: block; + height: 100px; + line-height: 100px; + font-size: 42px; + margin: 10px auto; + color: #333; + -webkit-transition: font-size 0.25s linear, width 0.25s linear; + -moz-transition: font-size 0.25s linear, width 0.25s linear; + transition: font-size 0.25s linear, width 0.25s linear; +} + +.icon_lists .icon:hover { + font-size: 100px; +} + +.icon_lists .svg-icon { + /* 通过设置 font-size 来改变图标大小 */ + width: 1em; + /* 图标和文字相邻时,垂直对齐 */ + vertical-align: -0.15em; + /* 通过设置 color 来改变 SVG 的颜色/fill */ + fill: currentColor; + /* path 和 stroke 溢出 viewBox 部分在 IE 下会显示 + normalize.css 中也包含这行 */ + overflow: hidden; +} + +.icon_lists li .name, +.icon_lists li .code-name { + color: #666; +} + +/* markdown 样式 */ +.markdown { + color: #666; + font-size: 14px; + line-height: 1.8; +} + +.highlight { + line-height: 1.5; +} + +.markdown img { + vertical-align: middle; + max-width: 100%; +} + +.markdown h1 { + color: #404040; + font-weight: 500; + line-height: 40px; + margin-bottom: 24px; +} + +.markdown h2, +.markdown h3, +.markdown h4, +.markdown h5, +.markdown h6 { + color: #404040; + margin: 1.6em 0 0.6em 0; + font-weight: 500; + clear: both; +} + +.markdown h1 { + font-size: 28px; +} + +.markdown h2 { + font-size: 22px; +} + +.markdown h3 { + font-size: 16px; +} + +.markdown h4 { + font-size: 14px; +} + +.markdown h5 { + font-size: 12px; +} + +.markdown h6 { + font-size: 12px; +} + +.markdown hr { + height: 1px; + border: 0; + background: #e9e9e9; + margin: 16px 0; + clear: both; +} + +.markdown p { + margin: 1em 0; +} + +.markdown>p, +.markdown>blockquote, +.markdown>.highlight, +.markdown>ol, +.markdown>ul { + width: 80%; +} + +.markdown ul>li { + list-style: circle; +} + +.markdown>ul li, +.markdown blockquote ul>li { + margin-left: 20px; + padding-left: 4px; +} + +.markdown>ul li p, +.markdown>ol li p { + margin: 0.6em 0; +} + +.markdown ol>li { + list-style: decimal; +} + +.markdown>ol li, +.markdown blockquote ol>li { + margin-left: 20px; + padding-left: 4px; +} + +.markdown code { + margin: 0 3px; + padding: 0 5px; + background: #eee; + border-radius: 3px; +} + +.markdown strong, +.markdown b { + font-weight: 600; +} + +.markdown>table { + border-collapse: collapse; + border-spacing: 0px; + empty-cells: show; + border: 1px solid #e9e9e9; + width: 95%; + margin-bottom: 24px; +} + +.markdown>table th { + white-space: nowrap; + color: #333; + font-weight: 600; +} + +.markdown>table th, +.markdown>table td { + border: 1px solid #e9e9e9; + padding: 8px 16px; + text-align: left; +} + +.markdown>table th { + background: #F7F7F7; +} + +.markdown blockquote { + font-size: 90%; + color: #999; + border-left: 4px solid #e9e9e9; + padding-left: 0.8em; + margin: 1em 0; +} + +.markdown blockquote p { + margin: 0; +} + +.markdown .anchor { + opacity: 0; + transition: opacity 0.3s ease; + margin-left: 8px; +} + +.markdown .waiting { + color: #ccc; +} + +.markdown h1:hover .anchor, +.markdown h2:hover .anchor, +.markdown h3:hover .anchor, +.markdown h4:hover .anchor, +.markdown h5:hover .anchor, +.markdown h6:hover .anchor { + opacity: 1; + display: inline-block; +} + +.markdown>br, +.markdown>p>br { + clear: both; +} + + +.hljs { + display: block; + background: white; + padding: 0.5em; + color: #333333; + overflow-x: auto; +} + +.hljs-comment, +.hljs-meta { + color: #969896; +} + +.hljs-string, +.hljs-variable, +.hljs-template-variable, +.hljs-strong, +.hljs-emphasis, +.hljs-quote { + color: #df5000; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-type { + color: #a71d5d; +} + +.hljs-literal, +.hljs-symbol, +.hljs-bullet, +.hljs-attribute { + color: #0086b3; +} + +.hljs-section, +.hljs-name { + color: #63a35c; +} + +.hljs-tag { + color: #333333; +} + +.hljs-title, +.hljs-attr, +.hljs-selector-id, +.hljs-selector-class, +.hljs-selector-attr, +.hljs-selector-pseudo { + color: #795da3; +} + +.hljs-addition { + color: #55a532; + background-color: #eaffea; +} + +.hljs-deletion { + color: #bd2c00; + background-color: #ffecec; +} + +.hljs-link { + text-decoration: underline; +} + +/* 代码高亮 */ +/* PrismJS 1.15.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */ +/** + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ +code[class*="language-"], +pre[class*="language-"] { + color: black; + background: none; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +pre[class*="language-"]::-moz-selection, +pre[class*="language-"] ::-moz-selection, +code[class*="language-"]::-moz-selection, +code[class*="language-"] ::-moz-selection { + text-shadow: none; + background: #b3d4fc; +} + +pre[class*="language-"]::selection, +pre[class*="language-"] ::selection, +code[class*="language-"]::selection, +code[class*="language-"] ::selection { + text-shadow: none; + background: #b3d4fc; +} + +@media print { + + code[class*="language-"], + pre[class*="language-"] { + text-shadow: none; + } +} + +/* Code blocks */ +pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; +} + +:not(pre)>code[class*="language-"], +pre[class*="language-"] { + background: #f5f2f0; +} + +/* Inline code */ +:not(pre)>code[class*="language-"] { + padding: .1em; + border-radius: .3em; + white-space: normal; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: slategray; +} + +.token.punctuation { + color: #999; +} + +.namespace { + opacity: .7; +} + +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.constant, +.token.symbol, +.token.deleted { + color: #905; +} + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.builtin, +.token.inserted { + color: #690; +} + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #9a6e3a; + background: hsla(0, 0%, 100%, .5); +} + +.token.atrule, +.token.attr-value, +.token.keyword { + color: #07a; +} + +.token.function, +.token.class-name { + color: #DD4A68; +} + +.token.regex, +.token.important, +.token.variable { + color: #e90; +} + +.token.important, +.token.bold { + font-weight: bold; +} + +.token.italic { + font-style: italic; +} + +.token.entity { + cursor: help; +} diff --git a/douban_app/resource/fonts/demo_index.html b/douban_app/resource/fonts/demo_index.html new file mode 100644 index 0000000..4e278ec --- /dev/null +++ b/douban_app/resource/fonts/demo_index.html @@ -0,0 +1,207 @@ + + + + + iconfont Demo + + + + + + + + + + + + + +
+

+ + +

+ +
+
+
    + +
  • + +
    movie
    +
    
    +
  • + +
+
+

Unicode 引用

+
+ +

Unicode 是字体在网页端最原始的应用方式,特点是:

+
    +
  • 支持按字体的方式去动态调整图标大小,颜色等等。
  • +
  • 默认情况下不支持多色,直接添加多色图标会自动去色。
  • +
+
+

注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)

+
+

Unicode 使用步骤如下:

+

第一步:拷贝项目下面生成的 @font-face

+
@font-face {
+  font-family: 'iconfont';
+  src: url('iconfont.ttf?t=1634624545312') format('truetype');
+}
+
+

第二步:定义使用 iconfont 的样式

+
.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+

第三步:挑选相应图标并获取字体编码,应用于页面

+
+<span class="iconfont">&#x33;</span>
+
+
+

"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

+
+
+
+
+
    + +
  • + +
    + movie +
    +
    .icon-movie +
    +
  • + +
+
+

font-class 引用

+
+ +

font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。

+

与 Unicode 使用方式相比,具有如下特点:

+
    +
  • 相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。
  • +
  • 因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。
  • +
+

使用步骤如下:

+

第一步:引入项目下面生成的 fontclass 代码:

+
<link rel="stylesheet" href="./iconfont.css">
+
+

第二步:挑选相应图标并获取类名,应用于页面:

+
<span class="iconfont icon-xxx"></span>
+
+
+

" + iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。

+
+
+
+
+
    + +
  • + +
    movie
    +
    #icon-movie
    +
  • + +
+
+

Symbol 引用

+
+ +

这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇文章 + 这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:

+
    +
  • 支持多色图标了,不再受单色限制。
  • +
  • 通过一些技巧,支持像字体那样,通过 font-size, color 来调整样式。
  • +
  • 兼容性较差,支持 IE9+,及现代浏览器。
  • +
  • 浏览器渲染 SVG 的性能一般,还不如 png。
  • +
+

使用步骤如下:

+

第一步:引入项目下面生成的 symbol 代码:

+
<script src="./iconfont.js"></script>
+
+

第二步:加入通用 CSS 代码(引入一次就行):

+
<style>
+.icon {
+  width: 1em;
+  height: 1em;
+  vertical-align: -0.15em;
+  fill: currentColor;
+  overflow: hidden;
+}
+</style>
+
+

第三步:挑选相应图标并获取类名,应用于页面:

+
<svg class="icon" aria-hidden="true">
+  <use xlink:href="#icon-xxx"></use>
+</svg>
+
+
+
+ +
+
+ + + diff --git a/douban_app/resource/fonts/iconfont.css b/douban_app/resource/fonts/iconfont.css new file mode 100644 index 0000000..ac89660 --- /dev/null +++ b/douban_app/resource/fonts/iconfont.css @@ -0,0 +1,17 @@ +@font-face { + font-family: "iconfont"; /* Project id */ + src: url('iconfont.ttf?t=1634624545312') format('truetype'); +} + +.iconfont { + font-family: "iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-movie:before { + content: "\e6bb"; +} + diff --git a/douban_app/resource/fonts/iconfont.js b/douban_app/resource/fonts/iconfont.js new file mode 100644 index 0000000..8e4cb74 --- /dev/null +++ b/douban_app/resource/fonts/iconfont.js @@ -0,0 +1 @@ +!function(c){var h,v,t,e,n,l='',i=(i=document.getElementsByTagName("script"))[i.length-1].getAttribute("data-injectcss"),z=function(c,h){h.parentNode.insertBefore(c,h)};if(i&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(c){console&&console.log(c)}}function o(){n||(n=!0,t())}function a(){try{e.documentElement.doScroll("left")}catch(c){return void setTimeout(a,50)}o()}h=function(){var c,h;(h=document.createElement("div")).innerHTML=l,l=null,(c=h.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",h=c,(c=document.body).firstChild?z(h,c.firstChild):c.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(h,0):(v=function(){document.removeEventListener("DOMContentLoaded",v,!1),h()},document.addEventListener("DOMContentLoaded",v,!1)):document.attachEvent&&(t=h,e=c.document,n=!1,a(),e.onreadystatechange=function(){"complete"==e.readyState&&(e.onreadystatechange=null,o())})}(window); \ No newline at end of file diff --git a/douban_app/resource/fonts/iconfont.json b/douban_app/resource/fonts/iconfont.json new file mode 100644 index 0000000..9b608f9 --- /dev/null +++ b/douban_app/resource/fonts/iconfont.json @@ -0,0 +1,16 @@ +{ + "id": "", + "name": "", + "font_family": "iconfont", + "css_prefix_text": "icon-", + "description": "", + "glyphs": [ + { + "icon_id": "19813080", + "name": "movie", + "font_class": "movie", + "unicode": "e6bb", + "unicode_decimal": 59067 + } + ] +} diff --git a/douban_app/resource/fonts/iconfont.ttf b/douban_app/resource/fonts/iconfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..923485dc3abfd66b4e87664f16fa46ac1be5d37e GIT binary patch literal 3276 zcmd^BZETxY6+Y+Q_bYbny#9#I+BJ1-Vq4otQroeuENja8HKwVnwk}k(taTm7N#!pk zZr4r%GEG9jNXw5&Fa$^lq=~P=BtBITt@ts1z*K}#C17g>QYSH(gj57fiOX|ezfQAk z)h6vH*Y7>|InO=k+;i`_k}ok4d1;v>jqiW-vHN4sj66xiMX-k+esnA|^}CNe1O4;R zkC*GE)@y(L$)BL#KyOuRXXjS0JbRi*)`*N>&sR#bL;LH~u)T(!p9f*SDxU`aIr<0Z z>+LfZ0DS)rVbz-DlAKk#BaM3LOp6bQZ({xfAY+YEy<&f3>IX!g9FeHDnoI59FF(;D z>i-Jn#|XL0<(tcNR8v6+Qtf7A6AlCRyFX z!gW`Xg!mHO@92v4;74@R(Yq^oXqx--x-kP%R;T*OM`) zW*H2V;j)@W`~}jn@Mpzuz@6`o{5oYAo`Q4<_8r>6xxKS=@%n}97o77T`DaqQQ90ad zLM`Z~gf&ocqI|sA|;UT_@M|qNW@`HSUKgN&qNpA3y{7L>CpW`p{*ZAA~0{@a<;>-L; z{tLg(H^iM{k9bggT$DvqEQwExFCwwwaCC^HkxXGH7xKB(D5sKf)6b?6nlQ{jBpQik zGlhI1kW39GCbG#?G7&coGddW6HgTIioE=OI-lnI9pu#;d?m)S1^N7=;r&>W!8;` zv{Zckea73I&*u0tuJ(=WbN6ySVh)B!5(;L*1vQaD7P3nWhK;UOCd~06?bQqLvFaCs(B?YJ?3>y$9nR5pqd;5KCP6NOxUn)B~q=g0AH$K~tVP2>7y3wZ_= zFh|q{NhO>TAth8O8A6mm3MnBmB#e@q%Eq|@(TSX@`8HM;f#HkYM7n;tlqsk~>D0L+ z$1fi{x{^w#Q!7W0T|R!~Tq^yt9oX~O;m7szk&o^hh!*`*yZ1h@clY$9S$s?5|GY&l zPIp#(q1o1{lR;0=-+9g#3i-I|4{pS<&U1liG{9BJ&SyM+zlW<{pU-^pW@)-FqLU9_x=7SCa) zTd-Nvy4wP~}xni6Z5RAH|waX1>driu!| zF~8@Usw%|VQ_;Xx#Y6CRpZBV&GepPMHC0KOO^cMOsAZ+kY#N`itOEE{kM9+*_%_R) z#qB*h2d!TTX$!mWl6Bd(pSPa3@U6XRTbgFuTn%jv2DgTGc>I0%P6(}65X?$l>Y9#P z0_id!b!M?3H(2zlddo){$<9BeZc5Fc4yXHB7A@4aZ}lH2p13lwmdBQbS+I)f`AFbJ z^QTd7|BuWUf`j7w<6HWJnq_H4O{gajT997t{;vUt(4GG{NDEpQ3o>b|izWEDi#6c8 zT&&~enQ^fJ{yrCb=x*BUVlN`L)T>16!#YWN+Qm#Zeappy{PZ&yOYkqbSOdP|Vx1!N znu`taYcBTC4EtQ{r6iYkFIGzJ%53b!+1Nt4*_dlK+P(3SO7&E&wAfR7<4k37X`$JO z?HC>JQTr>6%3?3f(&=iZ-JXlhEjH`1eTY}7)ta%^V)JCB+#a28w_B5AV`?46kCvNt z+D(g8p%S$rXDLP}=q%&{m8nS$nsa3PZTcgyuF@$yA4>3lH|rT#FVYh1RLmIdpiw+$ zH+$`eRl~8|oXrxQ#%dYl*hWS%^hHFf1MPG3t00paa0~@hb0-m}4C_%mag?L iTi;L5e$?4#T|Ica&AoK4c54v0-jeis^YlUm?Ee7f;n;Nm literal 0 HcmV?d00001 -- Gitee From 42658eda70d38e80858a36211a61cf7640e0aab6 Mon Sep 17 00:00:00 2001 From: Kun Chen Date: Wed, 20 Oct 2021 18:33:24 +0800 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=9C=86?= =?UTF-8?q?=E8=A7=92=E4=B8=8B=E5=88=92=E7=BA=BF=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../round_cap_underline_tab_indicator.dart | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 douban_app/lib/components/round_cap_underline_tab_indicator.dart diff --git a/douban_app/lib/components/round_cap_underline_tab_indicator.dart b/douban_app/lib/components/round_cap_underline_tab_indicator.dart new file mode 100644 index 0000000..98046e8 --- /dev/null +++ b/douban_app/lib/components/round_cap_underline_tab_indicator.dart @@ -0,0 +1,98 @@ +import 'package:flutter/material.dart'; + +/// Used with [TabBar.indicator] to draw a horizontal line below the +/// selected tab. +/// +/// The selected tab underline is inset from the tab's boundary by [insets]. +/// The [borderSide] defines the line's color and weight. +/// +/// The [TabBar.indicatorSize] property can be used to define the indicator's +/// bounds in terms of its (centered) widget with [TabBarIndicatorSize.label], +/// or the entire tab with [TabBarIndicatorSize.tab]. +class RoundCapUnderlineTabIndicator extends Decoration { + /// Create an underline style selected tab indicator. + /// + /// The [borderSide] and [insets] arguments must not be null. + const RoundCapUnderlineTabIndicator({ + this.borderSide = const BorderSide(width: 2.0, color: Colors.white), + this.insets = EdgeInsets.zero, + }) : assert(borderSide != null), + assert(insets != null); + + /// The color and weight of the horizontal line drawn below the selected tab. + final BorderSide borderSide; + + /// Locates the selected tab's underline relative to the tab's boundary. + /// + /// The [TabBar.indicatorSize] property can be used to define the tab + /// indicator's bounds in terms of its (centered) tab widget with + /// [TabBarIndicatorSize.label], or the entire tab with + /// [TabBarIndicatorSize.tab]. + final EdgeInsetsGeometry insets; + + @override + Decoration lerpFrom(Decoration a, double t) { + if (a is RoundCapUnderlineTabIndicator) { + return RoundCapUnderlineTabIndicator( + borderSide: BorderSide.lerp(a.borderSide, borderSide, t), + insets: EdgeInsetsGeometry.lerp(a.insets, insets, t), + ); + } + return super.lerpFrom(a, t); + } + + @override + Decoration lerpTo(Decoration b, double t) { + if (b is RoundCapUnderlineTabIndicator) { + return RoundCapUnderlineTabIndicator( + borderSide: BorderSide.lerp(borderSide, b.borderSide, t), + insets: EdgeInsetsGeometry.lerp(insets, b.insets, t), + ); + } + return super.lerpTo(b, t); + } + + @override + BoxPainter createBoxPainter([VoidCallback onChanged]) { + return _UnderlinePainter(this, onChanged); + } + + Rect _indicatorRectFor(Rect rect, TextDirection textDirection) { + assert(rect != null); + assert(textDirection != null); + final Rect indicator = insets.resolve(textDirection).deflateRect(rect); + return Rect.fromLTWH( + indicator.left, + indicator.bottom - borderSide.width, + indicator.width, + borderSide.width, + ); + } + + @override + Path getClipPath(Rect rect, TextDirection textDirection) { + return Path()..addRect(_indicatorRectFor(rect, textDirection)); + } +} + +class _UnderlinePainter extends BoxPainter { + _UnderlinePainter(this.decoration, VoidCallback onChanged) + : assert(decoration != null), + super(onChanged); + + final RoundCapUnderlineTabIndicator decoration; + + @override + void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) { + assert(configuration != null); + assert(configuration.size != null); + final Rect rect = offset & configuration.size; + final TextDirection textDirection = configuration.textDirection; + final Rect indicator = decoration + ._indicatorRectFor(rect, textDirection) + .deflate(decoration.borderSide.width / 2.0); + final Paint paint = decoration.borderSide.toPaint() + ..strokeCap = StrokeCap.round; + canvas.drawLine(indicator.bottomLeft, indicator.bottomRight, paint); + } +} -- Gitee From 5b7b222c987911130eb58df423d3f43102fa11d7 Mon Sep 17 00:00:00 2001 From: Kun Chen Date: Thu, 21 Oct 2021 10:14:31 +0800 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20=E5=88=9B=E5=BB=BAmodel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../read_model.dart} | 42 +++++++++---------- douban_app/pubspec.yaml | 9 +--- 2 files changed, 23 insertions(+), 28 deletions(-) rename douban_app/lib/models/{book_av_model.dart => book_av/read_model.dart} (87%) diff --git a/douban_app/lib/models/book_av_model.dart b/douban_app/lib/models/book_av/read_model.dart similarity index 87% rename from douban_app/lib/models/book_av_model.dart rename to douban_app/lib/models/book_av/read_model.dart index 0d345bf..9dcf37f 100644 --- a/douban_app/lib/models/book_av_model.dart +++ b/douban_app/lib/models/book_av/read_model.dart @@ -14,23 +14,24 @@ /// actors : ["张国荣","张丰毅","巩俐","葛优","英达","蒋雯丽","吴大维","吕齐","雷汉","尹治","马明威","费振翔","智一桐","李春","赵海龙","李丹","童弟","沈慧芬","黄斐","徐杰","黄磊","冯远征","杨立新","方征","周璞","隋永清"] /// is_watched : false -class Book_av_model { - Book_av_model({ - List rating, - int rank, - String coverUrl, - bool isPlayable, - String id, - List types, - List regions, - String title, - String url, - String releaseDate, - int actorCount, - int voteCount, - String score, - List actors, - bool isWatched,}){ +class ReadModel { + ReadModel({ + List rating, + int rank, + String coverUrl, + bool isPlayable, + String id, + List types, + List regions, + String title, + String url, + String releaseDate, + int actorCount, + int voteCount, + String score, + List actors, + bool isWatched, + }) { _rating = rating; _rank = rank; _coverUrl = coverUrl; @@ -46,9 +47,9 @@ class Book_av_model { _score = score; _actors = actors; _isWatched = isWatched; -} + } - Book_av_model.fromJson(dynamic json) { + ReadModel.fromJson(dynamic json) { _rating = json['rating'] != null ? json['rating'].cast() : []; _rank = json['rank']; _coverUrl = json['cover_url']; @@ -116,5 +117,4 @@ class Book_av_model { map['is_watched'] = _isWatched; return map; } - -} \ No newline at end of file +} diff --git a/douban_app/pubspec.yaml b/douban_app/pubspec.yaml index 0b7237a..482f2c9 100644 --- a/douban_app/pubspec.yaml +++ b/douban_app/pubspec.yaml @@ -48,17 +48,12 @@ flutter: # included with your application, so that you can use the icons in # the material Icons class. uses-material-design: true - fonts: - - family: cusIcon - fonts: - - asset: resource/fonts/iconfont.ttf - # To add assets to your application, add an assets section, like this: -# assets: + # assets: # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg fonts: - - family: myIcon #指定一个字体名 + - family: myIcon #指定一个字体名 fonts: - asset: lib/assets/fonts/iconfont.ttf -- Gitee