簡介:大家好,我是楓哥,🌟一線互聯網的IT民工、📝資深面試官、🌹Java跳蚤網課堂創始人,擁有多年一線研發經驗,曾就職過科大訊飛、美團網、平安等公司,在上海有自己小伙伴組建的副業團隊,目前業余時間專注Java技術分享,春招/秋招/社招/跳槽,一對一學習輔助,專案接活開發,
🎉🎉掃碼左側二維碼,加入群聊,一起學習,一起進步!
🌟 歡迎關注 🌟 收藏 🌹留言 🌹
🍊🍊:文末送福利
摸魚是不可能摸魚的,這輩子都不會摸魚,
我看了下郭佬分享了一篇微博:微博國際版https://share.api.weibo.cn/share/269008779.html

頓時這個念頭劃過了我的腦海:好東西,但是我用的是 MacBook,不能用這個應用,但是貌似我可以自己寫一個?
準備作業
年輕最需要的就是行動力,想到就干,盡管我此刻正在理順 DevFest 的講稿,但絲毫不妨礙我用 10 分鐘寫一個 App,于是我打出了一套組合拳:
flutter config --enable-macos-desktop
flutter create --platforms=macos touch_fish_on_macos
一個支持 macOS 的 Flutter 專案就創建好了,(此時大約過去了 1 分鐘)
開始敲代碼
找到資源
我們首先需要一張高清無碼的 圖片,這里你可以在網上進行搜尋,有一點需要注意的是,使用 LOGO 要注意使用場景帶來的著作權問題,找到圖片后,丟到 assets/apple-logo.png,并在 pubspec.yaml 中加上資源參考:
flutter:
use-material-design: true
+ assets:
+ - assets/apple-logo.png
思考布局
我們來觀察一下 macOS 的啟影片面,有幾個要點:

- LOGO 在螢屏中間,固定大小約為 100dp;
- LOGO 與進度條間隔約 100 dp;
- 進度條高度約 5dp,寬度約 200dp,圓角幾乎完全覆寫高度,值部分為白色,背景部分為填充色+淺灰色邊框,
(別問我為什么這些東西能觀察出來,問就是天天教 UI 改 UI,)
確認了大概的布局模式,接下來我們開始搭布局,(此時大約過去了 2 分鐘)
實作布局
首先將 LOGO 居中、著色、設定寬度為 100,上下間隔 100:
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Spacer(),
Padding(
padding: const EdgeInsets.symmetric(vertical: 100),
child: Image.asset(
'assets/apple-logo.png',
color: CupertinoColors.white, // 使用 Cupertino 系列的白色著色
width: 100,
),
),
const Spacer(),
],
),
);
然后在下方放一個相對靠上的進度條:
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Spacer(),
Padding(
padding: const EdgeInsets.symmetric(vertical: 100),
child: Image.asset(
'assets/apple-logo.png',
color: CupertinoColors.white, // 使用 Cupertino 系列的白色
width: 100,
),
),
Expanded(
child: Container(
width: 200,
alignment: Alignment.topCenter, // 相對靠上中部對齊
child: DecoratedBox(
border: Border.all(color: CupertinoColors.systemGrey), // 設定邊框
borderRadius: BorderRadius.circular(10), // 這里的值比高大就行
),
child: ClipRRect(
borderRadius: BorderRadius.circular(10), // 需要進行圓角裁剪
child: LinearProgressIndicator(
value: 0.3, // 當前的進度值
backgroundColor: CupertinoColors.lightBackgroundGray.withOpacity(.3),
color: CupertinoColors.white,
minHeight: 5, // 設定進度條的高度
),
),
),
),
],
),
);
到這里你可以直接 run,一個靜態的界面已經做好了,(此時大約過去了 4 分鐘)
打開 App,你已經可以放在一旁掛機了,老板走到你的身邊,可能會跟你閑聊更新的內容,但是,更新界面不會動,能稱之為更新界面? 當老板一而再再而三地從你身邊經過,發現還是這個進度的時候,也許就已經把你的工資劃掉了,或者第二天你因為進辦公室在椅子上坐下而被辭退,
那么下一步我們就要思考如何讓它動起來,
思考影片
來看看啟動影片大概是怎么樣的:

- 開始是沒有進度條的;
- 進度潭訓逐級移動、速度不一定相等,
基于以上兩個條件,我設計了一種影片處理方式:
- 構造分段的時長 (
Duration),可以自由組合由多個時長; - 影片通過時長的數量決定每個時長最終的進度;
- 每段時長控制起始值到結束值的間隔,
只有三個條件,簡單到起飛,開動!(此時大約過去了 5 分鐘)
實作影片
開局一個 AnimationController:
class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
/// 巧用 late 初始化,節省代碼量
late final AnimationController _controller = AnimationController(vsync: this);
/// 啟動后等待的時長
Duration get _waitingDuration => const Duration(seconds: 5);
/// 分段的影片時長
List<Duration> get _periodDurations {
return <Duration>[
const Duration(seconds: 5),
const Duration(seconds: 10),
const Duration(seconds: 4),
];
}
/// 當前進行到哪一個分段
final ValueNotifier<int> _currentPeriod = ValueNotifier<int>(1);
接下來實作影片方法,采用了遞回呼叫的方式,減少呼叫鏈的控制:
@override
void initState() {
super.initState();
// 等待對應秒數后,開始進度條影片
Future.delayed(_waitingDuration).then((_) => _callAnimation());
}
Future<void> _callAnimation() async {
// 取當前分段
final Duration _currentDuration = _periodDurations[currentPeriod];
// 準備下一分段
currentPeriod++;
// 如果到了最后一個分段,取空
final Duration? _nextDuration = currentPeriod < _periodDurations.length ? _periodDurations.last : null;
// 計算當前分段影片的結束值
final double target = currentPeriod / _periodDurations.length;
// 執行影片
await _controller.animateTo(target, duration: _currentDuration);
// 如果下一分段為空,即執行到了最后一個分段,重設當前分段,影片結束
if (_nextDuration == null) {
currentPeriod = 0;
return;
}
// 否則呼叫下一分段的影片
await _callAnimation();
}
以上短短幾行代碼,就完美的實作了進度條的影片操作,(此時大約過去了 8 分鐘)
最后一步,將影片、分段二者與進度條系結,在沒進入分段前不展示進度條,在影片開始后展示對應的進度:
ValueListenableBuilder<int>(
valueListenable: _currentPeriod,
builder: (_, int period, __) {
// 分段為0時,不展示
if (period == 0) {
return const SizedBox.shrink();
}
return DecoratedBox(
decoration: BoxDecoration(
border: Border.all(color: CupertinoColors.systemGrey),
borderRadius: BorderRadius.circular(10),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: AnimatedBuilder( // 使用 AnimatedBuilder,在影片進行時觸發更新
animation: _controller,
builder: (_, __) => LinearProgressIndicator(
value: _controller.value, // 將 controller 的值系結給進度
backgroundColor: CupertinoColors.lightBackgroundGray.withOpacity(.3),
color: CupertinoColors.white,
minHeight: 5,
),
),
),
);
},
)
大功告成,總共用時 10 分鐘,讓我們跑起來看看效果,(下圖 22.1 M)

打包發布
發布正式版的 macOS 應用較為復雜,但我們可以打包給自己使用,只需要一行命令即可:flutter build macos,
成功后,產物將會輸出在 build/macos/Build/Products/Release/touch_fish_on_macos.app,雙擊即可使用
結語
可能大多數人都沒有想到,撰寫一個 Flutter 應用,跑在 macOS 上,能有這么簡單,當然,看似短暫的 10 分鐘并沒有包括安裝環境、搜索素材、提交到 git 的時間,但在這個時間范圍內,完成相關的事情也是綽綽有余,
🌹 🌹感謝大家,堅持看完,既然選擇了這條路,那就一起加油,一起學習!如果需要學習資源,實戰面試資料,專案資源,關注公眾號:IT楓斗者,🌟根據關鍵字領取對應的資料福利🌟!咨詢解決問題,公眾號私聊楓哥,備注來意,
🍊回復:java全套學習資源
🍊回復:面試資料
🍊回復:楓哥簡歷
🍊回復:程式員表白神器
(從此告別程式員單身狗!)
🍊回復:程式員兼職網站
🍊回復:楓哥666
( 獲取66套專案實戰資料,大廠面試視頻)
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/390663.html
標籤:其他
