Android?Flutter實(shí)現(xiàn)創(chuàng)意時(shí)鐘的示例代碼
時(shí)鐘這個(gè)東西很奇妙,總能當(dāng)做創(chuàng)意實(shí)現(xiàn)的入口,比如這個(gè)大神用compose實(shí)現(xiàn)了一個(gè)小創(chuàng)意時(shí)鐘
看下效果

習(xí)慣把Compose這種組合聲明的開(kāi)發(fā)方式叫熱插拔,節(jié)省了大量代碼,簡(jiǎn)化了開(kāi)發(fā),尤其Modifier這個(gè)神奇的東西,熟悉了解決一切樣式的問(wèn)題。
看了下他的源碼,很簡(jiǎn)單,百十行左右,不多說(shuō),用Flutter仿一份?;蛘吣阌X(jué)得簡(jiǎn)單直接看GitHub歡迎批評(píng)指正
本案例使用的環(huán)境是:
Flutter (Channel stable, 2.2.3, on macOS 11.0.1 20B29 darwin-arm, locale zh-Hans-CN)
• Flutter version 2.2.3 at /Users/moon/Documents/sdk/flutter
• Framework revision f4abaa0735 (2 months ago), 2021-07-01 12:46:11 -0700
• Engine revision 241c87ad80
• Dart version 2.13.4
• Pub download mirror https://pub.flutter-io.cn
• Flutter download mirror https://storage.flutter-io.cn
1.構(gòu)建一個(gè)代表時(shí)間的小格子
一個(gè)最普通的Container 里包含一個(gè)text
_Number() {
return Container(
width: 40,
height: 40,
child: Text(
"5",
style: TextStyle(color: Colors.white, fontSize: 16),
),
);
}通過(guò)看上邊的gif圖就能設(shè)計(jì)出來(lái),小格子是有狀態(tài)的,是當(dāng)前的時(shí)間點(diǎn)數(shù)字的話背景色改變,同時(shí)也可以讓這個(gè)數(shù)字的字體變大一點(diǎn),區(qū)別于其他數(shù)字,而且他會(huì)在所在的列里位于屏幕的中部。 所以先簡(jiǎn)單封裝下這個(gè)小格子。
_Number(int number, bool isActive) {
var backgroundColor;
var numberSize;
if (isActive) {
backgroundColor = Colors.black;
numberSize = 18.0;
} else {
backgroundColor = Colors.deepPurpleAccent;
numberSize = 16.0;
}
return Container(
alignment: Alignment.center,
width: _normalSize,
height: _normalSize,
child: Text(
"$number",
style: TextStyle(color: Colors.white, fontSize: numberSize),
),
);2.構(gòu)建一列小格子
既然是幾列數(shù)字條構(gòu)成的一個(gè)時(shí)鐘,所以想下大概是繪制出一條就可以了,其他的幾個(gè)傳不同的數(shù)字和狀態(tài)就可以, Compose里用column,F(xiàn)lutter里同樣有這個(gè)東西,當(dāng)然用listview 或其他的容器都可以。
child: Column(
children: [
_Number(1 , false,),
_Number(2 , false,),
_Number(3 , false,),
_Number(4 , false,),
_Number(5 , true,),
],
))
為了美觀可以切個(gè)圓角,這點(diǎn)compose的modifier就體現(xiàn)出了優(yōu)勢(shì), 可以直接clip column,但Flutter卻沒(méi)那么強(qiáng)大,只能根據(jù)位置對(duì)每個(gè)小格子單獨(dú)處理了。
if (number == 0) {
borderRadius = BorderRadius.only(
topLeft: Radius.circular(15), topRight: Radius.circular(15));
} else if (number == (totalSize - 1)) {
borderRadius = BorderRadius.only(
bottomLeft: Radius.circular(15), bottomRight: Radius.circular(15));
} else {
borderRadius = BorderRadius.all(Radius.zero);
}decoration: BoxDecoration( color: backgroundColor, borderRadius: borderRadius, ),
或許還有其簡(jiǎn)單方式設(shè)置邊角,請(qǐng)朋友提示。

3.構(gòu)建多列小格子
同理搞出六列格子,代表雙位的時(shí)分秒,可以用row 包裹六個(gè) column ,設(shè)置外層container的子widget都居中,接受當(dāng)前時(shí)間作為狀態(tài),突出顯示就可以了。 比如現(xiàn)在是21:49:15

這樣就畫(huà)出了一個(gè)單獨(dú)的靜態(tài)時(shí)間刻度。
4.關(guān)于Align
這個(gè)圖好像不太對(duì),一種亂糟糟的感覺(jué),需要能一眼看出當(dāng)前時(shí)間才行,即把所有時(shí)間對(duì)齊在一條線上。
這方面Compose 發(fā)揮了優(yōu)勢(shì), modifier的 offset 可以輕松實(shí)現(xiàn)位移。
val mid = (range.last - range.first) / 2f val offset = 40.dp * (mid - current) Modifier .offset(y = offset)
flutter 里貌似沒(méi)這么方便了,怎么實(shí)現(xiàn)呢,我使用了Align組件,簡(jiǎn)單說(shuō)明下, 以下摘自官方。
Align 組件可以調(diào)整子組件的位置,并且可以根據(jù)子組件的寬高來(lái)確定自身的的寬高,定義如下:
Align({
Key key,
this.alignment = Alignment.center,
this.widthFactor,
this.heightFactor,
Widget child,
})alignment: 需要一個(gè)AlignmentGeometry類型的值,表示子組件在父組件中的起始位置。AlignmentGeometry是一個(gè)抽象類,它有兩個(gè)常用的子類:Alignment和FractionalOffset。widthFactor和heightFactor是用于確定Align組件本身寬高的屬性;它們是兩個(gè)縮放因子,會(huì)分別乘以子元素的寬、高,最終的結(jié)果就是Align組件的寬高。如果值為null,則組件的寬高將會(huì)占用盡可能多的空間。
舉例如下
Container(
height: 120.0,
width: 120.0,
color: Colors.blue[50],
child: Align(
alignment: Alignment.topRight,
child: FlutterLogo(
size: 60,
),
),
)
我顯式指定了Container的寬、高都為120。如果我不顯式指定寬高,而通過(guò)同時(shí)指定widthFactor和heightFactor 為2也是可以達(dá)到同樣的效果:
Align(
widthFactor: 2,
heightFactor: 2,
alignment: Alignment.topRight,
child: FlutterLogo(
size: 60,
),
),5.對(duì)齊時(shí)間線
分析,Align實(shí)際上就是把原高度擴(kuò)大為之前的 heightFactor 倍數(shù),而它的子widget仍然處于Align的頂部,而當(dāng)前時(shí)間點(diǎn)位于column頂部的距離是已知的,所以要讓當(dāng)前時(shí)間點(diǎn)的數(shù)字定位于 Align的中間 ,需要補(bǔ)齊(或截掉)當(dāng)前時(shí)間點(diǎn)的格子下邊的空間。 為了示意明確,我給總體背景和 Align 背景都加了顏色。

第一列: 小時(shí)首位,只有三個(gè)格子, 當(dāng)前是2, 2位于第三個(gè),所以需要給下邊補(bǔ)齊兩個(gè)格子, 第二列:小時(shí)的末位,共有10個(gè)格子,當(dāng)前數(shù)字也是2 ,也位于第三個(gè),為了讓上下相等,需要截掉4以下的數(shù)字,讓2位于中間位置。
以此類推。
這下就可以發(fā)現(xiàn)規(guī)律了。 高度的系數(shù)因子為 :
(current * 2 + 1)/numbers.length
numbers.length 是列的長(zhǎng)度。 因此, 每列的函數(shù)可以寫(xiě)為
_columnNumber(List<int> numbers, int current) {
List<Widget> list = [];
numbers.forEach((e) {
list.add(_Number(e, e == current, numbers.length));
});
return Container(
color: Colors.white,
child: Align(
alignment: Alignment.topCenter,
widthFactor: 1,
heightFactor: (current *2 + 1)/numbers.length,
child: Container(
height: numbers.length * _normalSize,
margin: EdgeInsets.only(left: 5, right: 5),
child: Column(
children: list,
)),
),
);
}
至此一個(gè)靜態(tài)時(shí)間鐘就繪制完成。
6.動(dòng)起來(lái)
獲取當(dāng)前時(shí)間,開(kāi)啟計(jì)時(shí)器,每秒刷新一次就可以實(shí)現(xiàn)動(dòng)態(tài)效果了 這個(gè)比較簡(jiǎn)單,不再?gòu)?fù)述了。

總結(jié)下: Compose 和 Flutter、SwiftUI都是聲明式UI,良好的設(shè)計(jì)已經(jīng)確定了是發(fā)展趨勢(shì), 同時(shí)上手簡(jiǎn)單,更能把精力專注在業(yè)務(wù)上。
以上就是Android Flutter實(shí)現(xiàn)創(chuàng)意時(shí)鐘的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Android Flutter時(shí)鐘的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
android實(shí)現(xiàn)banner輪播圖無(wú)限輪播效果
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)banner輪播圖無(wú)限輪播效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
Android 模仿iPhone列表數(shù)據(jù)View刷新動(dòng)畫(huà)詳解
本文主要介紹Android 模仿iPhone列表數(shù)據(jù)view 刷新動(dòng)畫(huà)的資料,這里整理詳細(xì)的資料,并附示例代碼及實(shí)現(xiàn)效果圖,有興趣的小伙伴可以參考下2016-09-09
Android編程實(shí)現(xiàn)音量按鈕添加監(jiān)聽(tīng)事件的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)音量按鈕添加監(jiān)聽(tīng)事件的方法,結(jié)合實(shí)例形式分析了Android事件監(jiān)聽(tīng)實(shí)現(xiàn)音量控制的相關(guān)操作技巧,需要的朋友可以參考下2017-06-06
Android自定義星星可滑動(dòng)評(píng)分控件
這篇文章主要介紹了Android自定義星星可滑動(dòng)評(píng)分控件,通過(guò)線性布局結(jié)合ImageView實(shí)現(xiàn)評(píng)分控件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
android中圖片加載到內(nèi)存的實(shí)例代碼
這篇文章主要介紹了android中圖片加載到內(nèi)存的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
Android Jetpack 狠活Lifecycles與LiveData使用詳解
這篇文章主要為大家介紹了Android Jetpack 狠活Lifecycles與LiveData使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
Android懸浮對(duì)話框(即點(diǎn)即關(guān)對(duì)話框)實(shí)現(xiàn)代碼
本文給大家介紹android懸浮對(duì)話框和即點(diǎn)即關(guān)閉對(duì)話框,本文介紹非常詳細(xì),具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧2016-03-03
Android中AlertDialog四種對(duì)話框的最科學(xué)編寫(xiě)用法(實(shí)例代碼)
這篇文章主要介紹了Android中AlertDialog四種對(duì)話框的最科學(xué)編寫(xiě)用法,本文通過(guò)代碼講解的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-11-11

