0%

【文章內容使用 Gemini 1.5 Pro 自動產生】

Hamilton Flare 設計挑戰

Flutter 社群持續帶給我們驚喜,我們經常看到許多新的計畫,幫助世界各地的開發者學習 Flutter 並樂在其中。VeryGoodVentures 剛宣布與 2Dimensions 合作,為 Hamilton App 舉辦首屆 Flare 設計挑戰。想了解更多資訊,請查看此比賽的 官方網站

Hamilton 是 首批使用 Flutter 建立的應用程式 之一。該應用程式在 3 個月內建成,下載量超過 100 萬次,並在 Apple App Store 和 Google Play 商店上獲得推薦。以下是我們製作的有關該應用程式的影片:

Flare 是一款全新的設計和動畫工具,允許使用者建立真實的互動式動畫資產,這些資產可以在其最終產品中實時運行。沒有什麼比將 Flare 的潛力應用到 Hamilton 應用程式上更好的方式了,方法是將其開放給設計師、開發者和 Hamilton 粉絲。

#HAMAPPFLARE

#HamAppFlare 挑戰是一個獨特的機會,讓您贏取獎品並在 Hamilton 應用程式(使用 Flutter 建立)中獲得展示,同時學習使用 Flare。

這是您使用 Flare 和 Flutter 以 Hamilton 應用程式為靈感創作驚人動畫的機會。思考動畫可以如何以有趣、引人入勝和實用的方式改善 Hamilton 應用程式,並透過 Flare 將它們變為現實。或者,您也可以用 Flare 創建一些令人驚嘆的內容來表達您對 Hamilton 的愛。

參加方法:

  1. 創建一個適合 Hamilton 的 Flare 動畫。
  2. 使用 #HamAppFlare 推文連結到您的作品。
  3. 2019 年 8 月 15 日晚上 11:59 EST 之前 將您的作品 提交到提交網站
  4. 獲獎者將由 Hamilton、Very Good Ventures 和 2Dimensions 選擇。

獲獎者將獲得:

  • 價值 250 美元的 Hamilton 商品包
  • 價值 250 美元的 Broadway.com 禮物卡
  • 1 年 Flare 訂閱(價值 250 美元)+ Flare T 恤
  • 應用程式內獲獎者公告
  • @HamiltonMusical 的社群媒體提及

立即參加挑戰

Hamilton Flare 挑戰於 2019 年 7 月 20 日開始,於 2019 年 8 月 15 日晚上 11:59 EST 結束。

Hamilton - 與 Flutter 和 Flare 一起崛起!

2017 年,百老匯熱門音樂劇 Hamilton 首個非 Google 品牌,推出了使用 Flutter 建立的製作應用程式。Hamilton 應用程式自推出以來,一直是 Flutter 的旗艦應用程式,在全球擁有超過 300 萬次下載。

雖然 Flutter 現在在開發者中已成為知名度極高的遊戲規則改變者,成為可移植 UI 框架,但 Hamilton 在 Flutter 的預覽版階段就早早採用了它。Hamilton 和 Very Good Ventures 一直致力於使用 Flutter 建立革命性的應用程式體驗…現在也包括 Flare。

詳細信息

提交指南

提交網站 上可以找到官方詳細信息和規則。以下任何信息僅供參考,並非「官方」信息。

  • 提交時間為 2019 年 7 月 20 日凌晨 12:00 EST 至 2019 年 8 月 15 日晚上 11:59 EST。
  • 提交作品 必須 包含 Flare 檔案。理想情況下,Flare 動畫也應在您提供的 Flutter 程式碼中使用。
  • 您的提交作品必須使用 GitHub 上的公共儲存庫的有效 URL 或 2Dimensions Flare 網站 提交。
  • 每個提交作品都必須附帶 MIT 許可證:https://opensource.org/licenses/MIT
  • 您的作品不得具有攻擊性或惡意 - 這是為了娛樂,並鼓勵設計師和開發者使用 Flare!

作品評審標準

Flare 作品將由 Hamilton、Very Good Ventures 和 Flare 團隊的成員根據以下標準進行評審:

  • 創意: 動畫及其使用的獨特性和新穎性。
  • 品牌一致性: 動畫與 Hamilton 品牌一致的程度,以及是否適合在應用程式中使用。
  • 驚豔: 動畫讓使用者露出笑容,並展示 Flare 強大功能的程度。

傳播訊息!

挑戰的官方標籤是 #HamAppFlare。請務必推文或發布您的作品,並提及 @HamiltonMusical@VGVentures@2Dimentions@FlutterDev

Hamilton 商品包包含哪些物品?

  • Hamilton 金星 T 恤 - 連結
  • Hamilton 棒球帽 - 連結
  • Hamilton 品脫杯 - 連結
  • Hamilton The Revolution 精裝本 - 連結
  • Hamilton 帆布沙灘包 - 連結
  • Hamilton 海灘毛巾 - 連結
  • Hamilton 紀念節目冊 - 連結
  • Hamilton 胸針 - 連結

需要靈感?

需要 Hamilton 應用程式為您在 Flare 中創作提供靈感?嘗試以下一些重點領域:

  • 輸入彩票動畫
  • 「您中獎了!」動畫
  • 彩票旅遊位置選擇器
  • trivia 星星爆發動畫
  • 今天螢幕內容動畫

基本上任何按鈕、內容或互動都是可以的!或者,您也可以使用 Hamilton 及其角色為靈感創作一些有趣的作品 - 可以看作是互動式粉絲藝術!


Hamilton Flare 設計挑戰 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

【文章內容使用 Gemini 1.5 Pro 自動產生】

Flutter 中的 Material RangeSlider

範圍滑桿是 Flutter 1.7 中釋出的高度自訂元件,用於選擇一組值。本文說明了範圍滑桿是什麼,為什麼您可能需要使用它,以及如何使用 Material 主題自訂 Flutter RangeSlider 的行為和外觀。

為什麼要使用範圍滑桿?

滑桿元件可以提供單一選取或多重選取,在離散或連續軌道上。與單一選取滑桿不同的是,單一選取滑桿預先確定最小值或最大值,並且可以在一個方向上調整選取,範圍滑桿具有兩個選取點,允許靈活調整最小值和最大值點。這種靈活性使其成為有用的元件,適用於使用者希望控制特定範圍的情況,例如指示價格點或時間長度。

結構和實作

RangeSlider 由 5 個部分組成:

  1. 一個軌道,拇指可以在上面滑動。
  2. 當 RangeSlider 為離散時,軌道上的刻度線。
  3. 2 個拇指(或旋鈕),表示範圍的最小值和最大值。
  4. 值指示器,在定義標籤且 showValueIndicator 與滑桿類型相符時,顯示拇指值的標籤。
  5. 當拇指被按下時,顯示在拇指上的覆蓋層。

我們需要 RangeSlider 具有豐富的動畫。這包括拇指位置的互動驅動動畫,以及覆蓋層和值指示器的內建動畫。在 Flutter 中,我們透過將 RangeSlider 元件設為 StatefulWidget 來做到這一點,它將動畫控制器作為狀態儲存。

實際的範圍滑桿值會儲存在父 Widget 中的狀態。透過在 RangeSlider 的 onChange() 回呼函數中呼叫 setState() 來更新值。換句話說,為了擁有互動式範圍滑桿,RangeSlider Widget 本身必須在 StatefulWidget 中建立。

RangeSlider 的 State 物件會構建 LeafRenderObjectWidget。所有內容都繪製在它的內部 RenderBox 中,它也處理觸控輸入。

處理觸控輸入

如果您好奇 RangeSlider 如何實作觸控輸入,請繼續閱讀!RangeSlider 的一個有趣之處在於,它是少數使用 GestureArenaTeam 的原生 Flutter Widget 之一。下一節將說明如何自訂觸控輸入。

如果您不感興趣,請跳過此節。

為了確保 RangeSlider 可以處理點擊和拖曳,同時在捲軸視圖、標籤列視圖和其他處理手勢的 Widget 中正常運作,會使用 GestureArenaTeam。GestureArenaTeam 允許透過「獲勝」來正確選擇一組手勢中的手勢。

首先,將拖曳辨識器加入到團隊中,然後加入點擊辨識器。沒有團隊隊長,因此一旦任何其他辨識器退出競技場,拖曳辨識器就會獲勝,因為它是第一個加入團隊的辨識器。另一方面,如果點擊可以直接獲勝,例如當滑桿在垂直捲軸列表中,使用者點擊然後立即鬆開時,則點擊辨識器會獲勝。

拖曳和點擊事件會解析為 3 種可能的互動之一:

  • 拖曳 onStart 或點擊 onTapDown → _startInteraction
  • 拖曳 onUpdate → _handleDragUpdate
  • 拖曳 onEnd 或 onCancel 以及點擊 onEnd 或 onCancel → _endInteraction

在互動開始時,必須確定的第一件事之一是哪個拇指應該被選取以進行移動。RangeSlider 透過使用可主題化函數來做到這一點,該函數會接收點擊值和拖曳位移等屬性,並返回拇指選擇:Thumb.start、Thumb.end 或 null(表示沒有選取)。

預設拇指選擇器首先嘗試在 _startInteraction 中找到最接近的拇指。如果選取了一個拇指,則拇指的位置會立即更新為點擊值。但是,如果點擊值位於拇指之間,但不在任何觸控目標中,則不會選取任何拇指。此外,如果拇指彼此足夠接近,並且點擊位於兩個觸控目標中,則不會選取任何拇指。在這種情況下,只有在存在非零移動(拖曳位移)時才會選取拇指。然後,對於負移動會選取左邊拇指,對於正移動會選取右邊拇指。這是唯一一種互動實際上在第一個 _handleDragUpdate 步驟中開始的情況。無論哪種情況,一個特殊的回呼函數 onChangeStart() 都會發出此互動的開始值。

當拇指分開較遠時,觸控內部軌道不會選取拇指:

當拇指更加靠近時,會使用拖曳位移來確定拇指選擇:

實作具有上述行為的預設拇指選擇器:

選取拇指後,所有未來的拖曳更新都用於確定拇指的新位置。覆蓋層動畫從選取的拇指開始,值指示器動畫從兩個拇指開始。當使用者拖曳選取的拇指時,範圍滑桿會發出一組帶有更新位置的新值,然後這些值會傳回範圍滑桿,以更新其對應的位置。

最後一步是 _endInteraction。一旦點擊或拖曳手勢抬起,在第一步中開始的覆蓋層和值指示器動畫就會反轉。一個特殊的回呼函數 onChangeEnd() 也會發出結束值。

自訂觸控輸入選取

在上一節中,您看到了 Material 的預設拇指選擇行為的程式碼。但是,如果您想要不同的東西呢?以下程式碼顯示了如何撰寫一個始終選取最接近拇指的拇指選擇器,無論觸控軌道的哪個部分。

實作始終找到最接近拇指的自訂拇指選擇器:

獲得此自訂拇指後,您可以在全域應用程式主題中設定它:

或者,可以使用 SliderTheme 在特定滑桿實例上設定它:

控制允許的拇指位置

在上面,您看到了如何使用 SliderThemeData 自訂拇指的選擇方式。本節將說明如何限制拇指可以拖曳或設定到的位置。有兩種方法可以控制拇指的允許位置。可以透過來完成,也可以透過空間來完成。透過值可能很有用,例如,如果您有一個價格選擇器。假設允許的價格可以在 0 美元和 100 美元之間,但您希望範圍至少相隔 20 美元。因此,[$30, $50] 的範圍是允許的,但 [$33, $34] 的範圍是不允許的。只需按照以下方式調整 onChanged 函數:

如果只需要限制拇指的出現,則可以使用 minThumbSeparation 屬性來限制分隔 2 個拇指的邏輯像素數。預設的頂部拇指會在其周圍繪製一個白色外框,以更好地區分拇指之間的對比。以下是一張比較預設值 8 與自訂值 24 的圖:

繪製形狀

除了處理觸控輸入之外,RenderBox 還負責繪製 RangeSlider。它會按照以下順序繪製 RangeSlider 的元件:

  1. 軌道
  2. 覆蓋層
  3. 刻度線(如果為離散)
  4. 值指示器(如果可見)
  5. 拇指

這對於繪製自訂形狀非常重要。所有形狀實作都透過 5 個獨立的抽象類別從 RenderBox.paint() 方法中抽象出來,這使得 RangeSlider 的繪製或渲染完全可自訂和可主題化,因為這些類別存在於 SliderThemeData 物件上。

在下一節中,我們將說明如何使用自訂形狀覆蓋預設形狀。

使用自訂形狀

就像單個 Slider 一樣,所有構成滑桿的形狀都可以針對 RangeSlider 自訂。查看 此片段 了解如何自訂 Material Slider 的範例。

這是透過將自訂抽象形狀類別的實作傳遞到 SliderThemeData 來完成的。這利用了 RangeSliderThumbShape 類別來提供自訂拇指,這些拇指根據它們所在的哪一側具有不同的外觀。

自訂範圍拇指形狀可以按以下方式實作:

然後,可以在 SliderThemeData 上設定自訂範圍拇指形狀:

結語

Material 範圍滑桿是社群要求的元件。它可以開箱即用,也可以自訂以符合您的應用程式需求。可以在全域層級的主題中,或在逐個實例的基礎上,變更行為和視覺外觀。

本文中包含的所有程式碼的完整程式碼,以及更多範例,可以在 github 上的 Material 範例庫github 上的 Material 函式庫 中找到。

特別感謝 Shams Zakhour、Liam Spradlin、Barbara Eldredge、Cortney Cassidy 和 Will Larche。


Flutter 中的 Material 範圍滑桿 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

【文章內容使用 Gemini 1.5 Pro 自動產生】

宣布 Flutter 1.7

今天,我們很高興 宣布 Flutter 1.7 正式推出,這是繼 Google I/O 上重大功能發佈後,一個較小的版本。Flutter 1.7 包含對 AndroidX 和更新的 Play Store 要求的支援、許多新的和增強的元件,以及對客戶報告問題的錯誤修復。

如果您已經在您的系統上安裝了 Flutter,並且您使用的是預設的穩定頻道,您可以透過命令列執行 flutter upgrade 來升級到 1.7 版。更新的版本也包含在 新的 Flutter 安裝 中。

新增應用程式的 AndroidX 支援

AndroidX 是一個由 Jetpack 團隊提供的新開源支援函式庫,它有助於 Android 應用程式在不犧牲向後相容性的情況下,使用最新的元件保持更新。由於 AndroidX 自身已經穩定,並且許多 Flutter 套件已更新以支援它,Flutter 支援 使用 AndroidX 建立新的 Flutter 專案,這減少了整合到 Android 生態系統其他部分所需的工作。

在建立 Flutter 專案時,您可以加入 --androidx 旗標,以確保產生的專案以新的支援函式庫為目標。有關將現有專案遷移到 AndroidX 的資訊,請參閱 flutter.dev 上的資訊。我們正在積極努力為混合使用 AndroidX/Android 支援函式庫的應用程式(例如在「新增至應用程式」情況下)提供 AndroidX/Jetifier 支援,並將在接下來的文章中分享更多有關此方面的資訊。

支援 Android 應用程式套件和 64 位元 Android 應用程式

從 2019 年 8 月 1 日起,使用原生程式碼且以 Android 9 Pie 為目標的 Android 應用程式在發佈到 Google Play 商店時,需要提供 64 位元版本,除了 32 位元版本。雖然 Flutter 長期以來一直支援產生 64 位元 Android 應用程式,但 1.7 版新增了對建立 Android 應用程式套件 的支援,這些套件可以從單次提交中以 64 位元和 32 位元為目標。請參閱更新的 關於發佈基於 Flutter 的 Android 應用程式的文件,以了解如何執行此操作,以及如何為 32 位元和 64 位元設備建立獨立的 APK 檔案。

新的 Widget 和框架增強

我們希望您的應用程式看起來很棒,並且感覺很自然,無論您以哪個平台為目標。因此,我們將繼續更新和增強 Android 和 iOS 上可用的 Widget。

此版本具備新的 RangeSlider 控制項,讓您可以在單個滑桿上選擇一系列值(例如,最小和最大溫度值):

新的、可主題化的 RangeSlider Widget 支援連續或離散樣式

更新的 SnackBar Widget 支援 Material 規格中更新的外觀,並且 新增了許多 範例 到文件

對於 Cupertino,用於建立像素完美的 iOS 應用程式的 Flutter 函式庫,我們進行了許多更新。特別是,我們改進了 CupertinoPicker 和 CupertinoDateTimePicker Widget 的保真度,並加入了對非英語語言的本地化支援。

我們還對 iOS 上的文字選取和編輯體驗 進行了重大改進,無論您使用的是 Material 還是 Cupertino 設計語言。此外,新的範例 展示了如何在 iOS 和 Android 之間進行更重大的平台適應,同時保留相同的程式碼庫。

文字渲染得到了重大升級,支援豐富的 排版功能,包括表格數字和舊式數字、斜線零和風格集,如 此演示 所示:

使用 Flutter,您現在可以使用 OpenType 字體功能支援新增複雜的排版

最後,我們加入了對 遊戲控制器 的支援。這會導致一些有趣的 Flutter 應用程式嗎?您告訴我們吧!

關注基本面

Flutter 1.7 代表著團隊為回應客戶報告問題所做出的大量努力,自我們上次穩定版本發佈以來,在兩個月的時間裡,已解決了 1,250 多個問題

隨著 Flutter 的快速成長,我們看到越來越多新的問題被報告,為了透明起見,當我們的專案規模較小時運作良好的錯誤處理過程現在效果不佳。因此,儘管我們在解決已分類問題方面取得了進展,但我們的公開問題數量在過去幾個月顯著增加。我們正在努力增加這方面的員工,這將有助於更快地解決新錯誤,解決和合併重複問題,並將支援請求重新導向到 StackOverflow

在最近的調查中,許多人表示希望看到我們繼續投資於文件和錯誤訊息。這项工作的一個关键部分是为我们的错误提供更好的结构,以便像 VS Code 和 Android Studio 这样的工具将来可以利用它。您可以查看 問題 34684 中的示例。

我們還解決了最常發生的崩潰錯誤,即當 Flutter 工具無法寫入 Flutter 目錄時產生的錯誤。如果使用者沒有寫入權限,Flutter 現在會在無法寫入的情況下優雅地失敗,並提供更明確的指示說明如何修復問題。

在文件方面,我們有一個不斷增加的範例列表,可以直接從 flutter create 工具中建立。從命令列,您可以執行以下命令:

1
flutter create --sample=material.AppBar.1 mysample

如果範例可以透過這種方式建立,您會在文件中看到一個「應用程式中的範例」標籤,例如 此 AppBar Widget 的範例

我們還將繼續將熱門的 每週 Widget 影片直接嵌入到文件,作為一種簡單的方法來了解 Flutter 工具箱中各種 Widget。

在幕後,您會看到為在 macOS 和 Windows 上啟用 Flutter 而建立基礎架構的許多底層工作,以及對重要概念的進一步支援,例如右鍵點擊和獨特的平台基礎架構,例如 MSBuild。但是,穩定頻道中尚未提供對非行動平台的支援。

最後,當您在 Mac 上建立 Flutter 應用程式時,我們現在支援 新的 Xcode 建立系統。這是在新的專案中預設啟用的,並且 很容易為現有專案啟用

不斷成長的 Flutter 社群

與往常一樣,看到 Flutter 的普及程度和使用率持續增長令人興奮,我們也慶祝大大小小的客戶使用 Flutter 的方式。自 I/O 以來,團隊一直忙於世界各地的各項活動:從中國的 GMTC 到紐約和墨西哥的聚會和演講;很高兴能与你们中的许多人见面,并了解你们正在构建的一些应用。

之前我們已經討論過 Reflectly:一家小型丹麥公司,他們為 iOS 和 Android 建立了一個美麗的正念應用程式。他們的應用程式剛被評選為美國 iPhone 應用程式商店的「每日應用程式」,這證明了 Flutter 應用程式完全有能力提供參考品質的體驗:

在柏林的 WeAreDevelopers 會議上,BMW 宣布了他們新的基於 Flutter 的應用程式,該應用程式目前正在開發中。以下是 BMW 連接公司 CTO Guy Duncan 的說法:

“透過結合 Dart 和 Flutter,我們拥有第一个真正的跨平台移动工具包;我们认为它是一个改变游戏规则的工具,可以确保数字接触点和物联网的功能一致性。
透過採用世界一流的工具、自動化和現代化的函數式程式設計模式,我们可以缩短功能周期时间,提高安全性和降低业务功能的交付成本。”

當然,除了應用程式之外,開源社群是使 Flutter 成为一個如此有趣的工作場所的原因,它擁有許多 資源Plugin活动聚会。我們對您如何使用 Flutter 以及能夠與大家分享樂趣感到驚嘆不已!

圖片出處:[@damian2048](https://twitter.com/damian2048)


宣布 Flutter 1.7 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

【文章內容使用 Gemini 1.5 Pro 自動產生】

很抱歉,您提供的輸入中似乎缺少內容,無法進行轉換。請確認您提供的輸入是否完整,並重新提交。

如果您能提供完整的輸入內容,我會盡力將它完整地轉換為 Markdown 格式。

【文章內容使用 Gemini 1.5 Pro 自動產生】

當我第一次意識到 Flutter 讓我可以完全控制螢幕上的所有内容,甚至精確到每個像素時,我立即想要超越大多數應用程式 UI 的固定和可預測的世界。我可以使用 [CustomPaint](https://api.flutter.dev/flutter/widgets/CustomPaint-class.html) 繪製的完全自訂 Widget 渴望擺脫典型的 ScrollView 或 Container。我希望能夠移動、放大和縮小,以及在 Flutter 創造的世界中導航。[Transform](https://api.flutter.dev/flutter/widgets/Transform-class.html) Widget 成為我在這個世界中導航的工具,而 [GestureDetector](https://api.flutter.dev/flutter/widgets/GestureDetector-class.html) 提供了控制項。

GestureDetector 提供了對大多數手勢的便捷存取,而 Transform 提供了修改子 Widget 被視角的能力。兩者都是簡單的獨立 Widget,遵循 Flutter 的組合模式。當我們將兩者結合在一起時,Widget 上的每個手勢都成為探索的方式。

變換簡介

儘管功能强大,但 Transform Widget 實際上只做的就是接收一個變換矩陣並將其應用於其子 Widget。這會導致子 Widget 相對於父 Widget 的平移、縮放、旋轉,甚至傾斜,所有這些都由一個簡單的 [Matrix4](https://api.flutter.dev/flutter/vector_math/Matrix4-class.html) 物件指定。

在進行變換時,矩陣非常方便使用,因為它們是可組合的。最初,儲存單獨的平移、縮放、旋轉和傾斜參數非常直观,但很容易在順序等方面造成歧义。

想象一下使用者連續執行一系列手勢。如果手勢只是一系列拖動,那麼我們可以輕鬆地將最終變換儲存為結果位置 Offset。但是,如果使用者拖動,然後在新的位置旋轉,並重複此操作幾次,我們如何跟踪最終狀態?一個 Offset 和一個弧度的倍數是不夠的,即使我們也包括一個焦點。我們必須跟踪使用者執行的操作的不断擴大的清單,並迭代整個過程才能獲得最終狀態。

一個變換矩陣可以與任意數量的其他變換矩陣無限次結合,結果始終是另一個相同大小的單一矩陣。GPU 在執行這種數學運算方面速度非常快,即使是大規模並行運算,例如針對螢幕上的每個像素。這使得它非常適合儲存類似 Transform 這樣的 Widget 的狀態,並且結果是一個非常簡單的 Widget 供 Flutter 開發人員使用。

偵測手勢

如果我們將一些使用者手勢與使用 GestureDetector 更新變換矩陣綁定在一起,那麼使用者就可以自由導航我們向他們顯示的場景。GestureDetector 提供了對拖動等手勢的便捷存取,我們可以使用它進行平移,捏合,用於縮放,甚至用於兩指旋轉。

GestureDetector 為各種手勢及其開始、更新和結束狀態提供了許多不同的回調。但是,如果您實作類似於圖中所示的演示(將幾個手勢結合在一起),那麼您只需要縮放回調。onScaleUpdate 回調提供了一個 focalPoint,水平和垂直縮放,以及旋轉,所有這些都在一個回調中。這允許您同時響應多個手勢,例如,如果使用者正在一個手勢中旋轉和縮放。請查看 [ScaleUpdateDetails](https://api.flutter.dev/flutter/gestures/ScaleUpdateDetails-class.html) 以了解 onScaleUpdate 回調中提供的所有內容。

在這些物理變換中,另一個經常實作的功能是慣性。在使用者完成手勢後,他們可能會期望變換繼續一段時間,然後才緩慢停止。Flutter 在所有這些手勢的結束回調中提供了「速度」參數,包括縮放。正如您可能從基於物理的移動中猜測到的那樣,如果使用者快速移動手指,則此值更大;如果使用者慢速移動手指,則此值更小。

您可以使用 Flutter 的另一個强大基礎設施 [Tween](https://api.flutter.dev/flutter/animation/Tween-class.html) 動畫來建立這種慣性效果。使用手勢結束時的速度和位置,以及一些基本的物理知識,您可以計算出一個最終位置和持續時間,並將其提供給 Tween,讓它處理其他所有事情。Flutter 甚至包括一個 [摩擦模擬類別](https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/physics/friction_simulation.dart) 來為您處理一些這些計算,並使事物感覺非常逼真。

結論

將 Transform 和 GestureDetector 結合起來,為我們提供了一個极其强大的工具。從移動棋盤(如螢幕截圖所示)到導航地圖,到提供互動式圖片檢視器等等,無數的功能都變得可能。

這裡顯示的應用程式目前可以在 [Flutter Gallery 應用程式](https://play.google.com/store/apps/details?id=io.flutter.demo.gallery&hl=en_US) 中作為演示使用。所有程式碼都是 Flutter 開源儲存庫的主要部分,可以在 [變換演示原始碼](https://github.com/flutter/flutter/blob/master/examples/flutter_gallery/lib/demo/transformations/transformations_demo.dart) 中找到。大多數變換邏輯都在 [GestureTransformable](https://github.com/flutter/flutter/blob/master/examples/flutter_gallery/lib/demo/transformations/transformations_demo_gesture_transformable.dart) 類別中,包括 [慣性動畫](https://github.com/flutter/flutter/blob/9d724d4c4483b585dfd4bfd719844802f8b38abe/examples/flutter_gallery/lib/demo/transformations/transformations_demo_gesture_transformable.dart#L503)。


Flutter 的 Transform 和 GestureDetector Widget 的强大功能 最初發佈在 Medium 上的 Flutter,人們在那裡透過突出顯示和回應這個故事來繼續討論。

【文章內容使用 Gemini 1.5 Pro 自動產生】

Flutter 文化與如何維護它

*[這篇文章是由 Emily Fortuna 和 Filip Hracek 共同撰寫。]

Flutter 的迷人之處和生產力的一個重要因素就是它的社群。我們非常希望這能持續下去,因此我們想分享我們對目前文化的觀察,以及如何維護它的想法。

開放的心胸

這裡有三個我們想到的「開放」的意思:開放的心胸易於使用以及開源。雖然開源的方面很棒(並且使我們的套件系統成為一個名副其實、充滿豐盛資源的熱帶雨林生物群落),但在文化方面,我們主要想到的是前兩個。看到 Flutter 社群歡迎新人並幫助他們學習,耐心地、透徹地回答問題,真是太好了。這有助於我們的社群成長,並對所有人感到親切,無論您的背景如何。我們喜歡看到 Flutter 開發者如何分享程式碼片段,以及他們願意深入除錯他人的問題。

當然,開放的心胸不僅適用於新人。通常,實作一個想法可能有多種方法,我們非常感謝 Flutter 社群在問題出現時能夠 溫和地 糾正問題,或者在適當的情況下允許使用不同的演算法實作方式。這再次證明了強大的力量。

一定程度 的標準化是好的。一個小型團隊可能應該有一個標準化的程式碼風格。但是,科技社群很容易對做事的「正確」方式過於熱衷。不同的團隊將會有不同的程式碼風格,這是可以的。不同的應用程式將會使用不同的狀態管理方式,這也是可以的。有些人會用 tab 而不是空格,這也是(顯然努力了 15 分鐘)可以的。

再次強調,科技社群很容易忽略將某些想法僵化是 自然 的,它們會獲得不可變的制度知識,並以狂熱的熱情捍衛它。

然而,在 Flutter 社群中,我們沒有看到任何這些。

以初學者的思維來面對問題,也就是以開放、溫柔、好奇、透徹和缺乏先入為主的觀念來面對問題,對每個人都有益。它不僅能鼓勵新人,還能促進 Flutter 老手的理解,他們可能只對某個領域有部分了解。而且,它能使其他人更容易接受您的想法。我們很高兴在 Stack Overflow 和各种 Slack 频道上经常看到这些积极的品质。另见 脆弱的力量

謙虛

我們看到 Flutter 開發者幫助新人而不會看不起他們。這非常有效。

在別人面前完美無瑕是人之常情。但是,如果做得過火,就會導致偽裝文化和不切實際的期望。這些事情如果放任不管,就會透過回饋迴路失控。它可以從小小的刻薄話語開始,接下來你就知道,你會看到普遍的冒名頂替症候群、不安全感、焦慮和殘酷。

我們希望我們透過各種 Flutter Boring Show 集數證明了我們犯了錯誤。(因為我們確實犯了錯誤!)Boring Show 的概念是展示開發過程,其中包含所有錯誤、死胡同和突觸延遲,而不作任何剪輯。

這是我們團隊在尋找潛在的 Flutter Google 開發者專家 (GDE) 時,我們尋找的核心品質之一。我們期望 Flutter GDE(那些地球上最了解 Flutter 的人)展現謙遜和同理心。我們不希望 Flutter 由一群聰明但愛管閒事的代表。值得慶幸的是,我們從未在任何潛在的 GDE 身上遇到過任何問題。謙遜的訊息總是能引起共鳴,甚至我們不必解釋我們的意思。這證明了我們社群的力量。

幸運的是,我們在 Flutter 工程團隊中也看到了這一點。舉一個例子,Ian - Flutter 的創始人之一,以及 HTML 規範的前任編輯(除其他外) - 是一位我們認識的最謙虛的工程師之一。你看,他對 Sliver 的運作不確定。這讓我們更加尊重他,而不是更少。

尊重其他技術

很容易對一項技術產生依戀,以至於所有其他技術看起來都像個壞主意。尤其是當它們是競爭技術時。

Flutter 不需要炒作或狂熱。使用 Flutter 有很多很好的理由,例如想要利用 Dart 快速撰寫反應式 UI,擁有快速且對應性高的應用程式,可在 iOS 和 Android(以及網頁和桌面)上運行,以及擁有豐富且易於使用的套件生態系統。

但是,有些人也有不適合使用 Flutter 的用例,作為 Flutter 愛好者,您可以做的最好的事情之一就是說服这些人 不要 使用 Flutter。您將為他們節省很多痛苦和失望。而且那個人會因為您對技術領域的廣泛了解,能够提供公正的建議,而 尊重您。

不幸的是,Filip 已經看到 Flutter 社群對其他技術的一些嘲諷。但是,這並非普遍現象,社群中的其他人也反對這種行為。這讓我們感到樂觀。

為什麼要維護它?

這種社群文化是 Flutter 的一大優勢。讓我們坦誠地說:任何技術的開發者體驗都是技術本身及其周圍社群的總和。如果一個社群只由狂熱者、混蛋或狂人組成,那麼無論技術有多麼優越,我們都不會加入它。

健康的社群是成長的社群。社群在成長的同時也變得更加孤立,其中可能有隱藏的代價。是的,一些 新人正在加入,但是您可以想像如果社群更加歡迎,會有多少 額外 的人會加入嗎?我們想維護將 我們 帶來這個社群的這些品質,並繼續為那些在我們之後加入的人打開它。

如何維護它?

沒有從上而下維護這些價值觀的方式。Flutter 是一個開放的社群。它的價值觀將透過其成員日常的決策來維護。一些小事情,例如您如何歡迎新成員,您如何分享您的知識,您如何誠實地談論您的最新錯誤,您如何友善地談論競爭框架。所有這些都是 Flutter 社群

透過專注於 開放性謙虛尊重生態系統中的其他人,我們將繼續為所有人培養出色的開發者體驗。我們希望,透過識別和命名我們在社群中所見的內容,這篇文章將有助於維護它。畢竟,在沒有意識到我們擁有了某項東西的情況下,很難維護它。

我們的意思不是

  • 我們的意思不是我們不應該展示最佳實務和優秀的程式碼。你在自己的領域中可以出類拔萃,而不會看不起別人。
  • 我們的意思不是我們不應該有任何標準和「主要做事方式」。你可以有標準,而不必貶低其他方式。
  • 我們的意思不是我們不應該熱情。你可以熱情,同時仍然知道 Flutter 何時以及為什麼不適合某項工作。
  • 我們的意思不是我們不應該對 Flutter 感到興奮。你可以感到興奮,同時仍然清楚知道 Flutter 何時以及為什麼不是一项好的工具。

隨著 Flutter 繼續受到歡迎,我們正處於社群歷史上的重要時刻,而 是其中至關重要的部分!讓我們以正確的方式成長,繼續為所有人培養出色的體驗。在網路上與其他人互動時,請記住讓 開放性謙虛尊重其他生態系統 的品質指導您的回應。Flutter 有一個 行為準則,就像我們在那裡提到的,如果您遇到任何讓您在 Flutter 社群中感到不受歡迎的事情,請聯繫團隊中的某個人,例如我們其中一位。如果您是新手,歡迎!我們很高兴您能加入我们!


Flutter 文化與如何維護它 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

http://creativecommons.org/licenses/by/4.0/

【文章內容使用 Gemini 1.5 Pro 自動產生】

一週前,在 Google I/O 2019 上,Android 團隊 宣布在 Android Q 中支援深色主題,這是一種由使用者切換的系統範圍的深色 UI 模式。這就引發了一個問題:Flutter 何時會支援這個很棒的新 Android 功能?嗯,您可能會驚訝地發現,Flutter 在 2 月份就加入了對深色主題的支援!以下是如何使用它。

首先,讓我們從一個典型的 MaterialApp 開始,它為其餘 UI 建立主題。以下是如何在深色主題之前,典型的應用程式定義其主題。

在 Flutter 中,我們為 MaterialApp 引入了一個 darkTheme 屬性,它允許您指定一個獨立的第二主題,僅在 Android 的深色主題功能中使用。讓我們為 MaterialAppdarkTheme 引入一個 Brightness.dark 設定的主題。

完成了!現在,當您在系統抽屜中切換深色主題時,您的 Flutter 應用程式將會從普通的 theme 自動切換到您的 darkTheme

由於 Flutter 使用程式碼來製作 UI,因此更新您的應用程式以支援新功能只需要在您的 Widget 樹中新增一個新屬性即可。沒有 XML 樣式需要更新,沒有 CSS 需要更新,只是一個普通的 Dart 參數。

在 Flutter 中,沒有理由害怕黑暗。


在 Flutter 中使用 Android 深色主題 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

【文章內容使用 Gemini 1.5 Pro 自動產生】

Flutter 應用程式的效能測試

Flutter 框架在預設情況下非常快速,但這是否意味著您不必考慮效能呢?不。絕對有可能撰寫出速度緩慢的 Flutter 應用程式。另一方面,也有可能充分利用框架,讓您的應用程式不僅速度快,而且高效,消耗更少的 CPU 時間和電池。

這就是我們想要的:一個在某些有意義的指標上比較您的應用程式的兩個版本時具有統計顯著性的結果。請繼續閱讀以了解如何獲得此結果。

Flutter 效能優化的概略準則如下:

  • 更新狀態時,目標盡可能少的 Widget。
  • 僅在必須時更新狀態。
  • 將計算密集型任務放在建構方法之外,理想情況下是在主隔離區之外。

事實上,對於許多有關效能优化的問題,答案是「視情況而定」。對 特定 Widget 進行的 特定 優化是否值得付出努力和維護成本?特定 情況下的 特定 方法是否有意義?

這些問題唯一有用的答案來自測試和測量。量化每個選擇對效能的影響,並根據這些資料做出決定。

好消息是,Flutter 提供了出色的效能分析工具,例如 Dart DevTools(目前處於預覽發行階段),其中包含 Flutter Inspector,或者您可以直接從 Android Studio(安裝 Flutter 外掛後)使用 Flutter Inspector。您有 Flutter Driver 用於測試您的應用程式,以及用於儲存效能資訊的 Profile 模式。

壞消息是現代智慧型手機非常「聰明」。

治理器的問題

iOS 和 Android 治理器使量化 Flutter 應用程式的效能變得特別困難。這些系統級別的守護程序會根據負載調整 CPU 和 GPU 單位的速度。當然,這大多是好事,因為它確保在消耗盡可能少的電池的情況下提供流暢的效能。

缺點是,您可以透過讓應用程式 更多 地工作來使其顯著 更快

在下方,您可以看到如何將具有無意義 print 語句的迴圈加入到應用程式中,使治理器切換到更高檔,從而使應用程式更快,其效能也更可預測。

治理器的問題:預設情況是,您無法信任您的數字。在這個箱型圖中,我們在 x 軸上有單獨的執行(以它們開始的精確時間標記),以及 y 軸上的建構時間。如您所見,當我們加入一些完全不必要的 `print` 語句時,它會使建構時間下降,而不是上升。

在此實驗中,較差的程式碼導致更快的建構時間(上方)、更快的柵格化時間和更高的畫面更新率。當客觀上較差的程式碼導致更好的效能指標時,您便無法依賴這些指標來提供指導。

這只是一個例子,說明行動應用程式的效能基準測試為何會不合常理且困難。

在下方,我分享了一些我在處理 Flutter 的 Google I/O 應用程式 Developer Quest 時收集的技巧。

基本建議

  • 在 DEBUG 模式下不要測量效能。僅在 profile 模式下測量效能。
  • 在真實設備上測量,而不是在 iOS 模擬器或 Android 模擬器中。軟體模擬器非常適合開發,但它們與真實設備的效能特性有很大差異。Flutter 不允許您在模擬設備上以 profile 模式執行,因為這沒有任何意義。您以這種方式收集的資料不適用於現實世界的效能。
  • 理想情況下,使用相同的物理設備。將其作為您的專用效能測試設備,不要用於其他任何用途。
  • 了解 Flutter 的 效能分析工具

CPU/GPU 治理器

如上所述,現代作業系統會根據負載和其他一些啟發式算法更改其處置的每個 CPU 和 GPU 的頻率。(例如,觸碰螢幕通常會使 Android 手機切換到更高檔。)

在 Android 上,您可以關閉這些治理器。我們稱此過程為「比例鎖定」。

  • 建立一個比例鎖定效能測試設備的腳本。您可以使用 Skia 的做法 作為靈感。您也可以查看 Unix CPU API
  • 除非您執行的基準測試作業規模龐大,例如 Skia,否則您可能想要更輕量級且不那麼通用的工具。查看 Developer Quest 的 shell 腳本 以獲取一些提示。例如,以下摘錄將 CPU 設為使用者空間治理器(唯一不會自行更改 CPU 頻率的治理器)。
1
2
3
4
5
6
7
#!/usr/bin/env bash

GOV="userspace"
echo "Setting CPU governor to: ${GOV}"
adb shell "echo ${GOV} > /sys/devices/system/cpu/cpu${CPU_NO}/cpufreq/scaling_governor"
ACTUAL_GOV=`adb shell "cat /sys/devices/system/cpu/cpu${CPU_NO}/cpufreq/scaling_governor"`
echo "- result: ${ACTUAL_GOV}"
  • 您的目標在此不是模擬現實世界的效能(沒有使用者會比例鎖定其設備),而是讓不同執行之間的效能指標具有可比性。
  • 最終,您需要進行實驗,並將 shell 腳本調整為您將使用的設備。這項工作很繁瑣,但直到您完成這項工作之前,您的效能資料都會欺騙您。
Developer Quest 的早期版本在桌面上由 Flutter Driver 測試。

Flutter Driver

Flutter Driver 讓您可以自動測試您的應用程式。請閱讀 flutter.dev 的 效能分析 部分,以獲取有關如何在分析應用程式時使用它的具體做法。

  • 在效能測試時,不要手動測試您的應用 Programm。始終使用 Flutter Driver 以確保您比較的是同樣的事物。
  • 撰寫 Flutter Driver 程式碼,讓它測試您真正想要測量的內容。如果您追求的是一般的應用程式效能,請嘗試瀏覽應用程式的各個部分,並執行使用者會執行的操作。
  • 如果您的應用程式包含機率因素(隨機、網路事件等),請將其模擬出來。這些瀏覽過程應盡可能彼此相似。
  • 如果需要,請使用 TimelinestartSync()finishSync() 方法來新增自訂時間軸事件。例如,當您感興趣的是特定函數的效能時,此方法非常有用。將 startSync() 放在其開頭,將 finishSync() 放在其結束位置。
  • 儲存摘要(writeSummaryToFile)和更重要的是原始時間軸(writeTimelineToFile)。
  • 對於應用程式的每個版本,請執行多次測試。對於 Developer Quest,我將其收斂到 100 次執行。(當您測量雜訊較大的事物時,例如第 99 個百分位數,您可能需要更多次執行。)對於基於 POSIX 的系統,這只意味著執行類似以下內容:for i in {1..100}; do flutter drive --target=test_driver/perf.dart --profile; done
使用 Chrome 的時間軸工具檢查 Flutter 的 profile 輸出。

時間軸

時間軸是 profile 執行結果的原始輸出。Flutter 將此資訊轉儲到一個 JSON 檔案中,可以將其載入到 chrome://tracing 中。

  • 了解如何在 Chrome 的追蹤時間軸中打開完整時間軸。您只需要在 Chrome 瀏覽器中打開 chrome://tracing,點選「載入」,然後選擇 JSON 檔案。您可以在 這個簡短的教學課程 中了解更多資訊。(Flutter 也提供了 時間軸工具,目前處於技術預覽階段。我沒有使用它,因為 Developer Quest 專案在 Flutter 的時間軸工具準備就緒之前就已經開始了。)
  • 使用 WSAD 鍵在 chrome://tracing 中移動時間軸,並使用 1234 切換操作模式。
  • 首次設定效能測試時,請考慮使用完整的 Android 系統追蹤來執行 Flutter Driver。這為您提供了更多關於設備中實際發生的事情的洞察力,包括 CPU 比例資訊。但是,請不要在完全開啟系統追蹤的情況下測量您的應用程式,因為它會使一切都變得更慢且更不可預測。
  • 如何使用 Flutter Driver 執行完整的 Android 系統追蹤?首先,使用 /path/to/your/android/sdk/platform-tools/systrace/systrace.py --atrace-categories=gfx,input,view,webview,wm,am,sm,audio,video,camera,hal,app,res,dalvik,rs,bionic,power,pm,ss,database,network,adb,pdx,sched,irq,freq,idle,disk,load,workq,memreclaim,regulators,binder_driver,binder_lock 開始 Android 系統追蹤。然後,使用 flutter run test_driver/perf.dart --profile --trace-systrace 啟動應用程式。最後,使用 flutter drive --driver=test_driver/perf_test.dart --use-existing-app=http://127.0.0.1:NNNNN/(其中 NNNNN 是 flutter run 上面的埠號)啟動 Flutter Driver。

指標

查看盡可能多的指標總比少好,但我發現有些指標比其他指標更有用。

  • 建構時間和柵格化時間(TimelineSummary 預設提供的指標)僅適用於實際上不包含太多 UI 建構以外的內容的非常嚴格的效能測試。
  • 不要將 TimelineSummary.frameCount 作為計算畫面更新率 (FPS) 的方法。Flutter 的 profile 工具不會提供實際的畫面更新率資訊。TimelineSummary 提供 countFrames() 方法,但它只計算已完成的畫面建構次數。一個經過良好優化的應用程式會限制不必要的重新建構,其畫面更新率將低於頻繁重新建構的未優化應用程式。
  • 我個人透過測量執行 Dart 程式碼所花費的總 CPU 時間來獲得最有用的資料。這計算了在建構方法中以及在建構方法之外執行的程式碼。假設您在比例鎖定的設備上執行 profile 測試,則總 CPU 時間是應用程式將消耗多少電池電量的良好近似值。
  • 找出執行 Dart 程式碼所花費的總 CPU 時間最簡單的方法是測量時間軸中 MessageLoop:FlushTasks 事件的範圍。對於 Developer Quest,我撰寫了一個 Dart 工具 來提取這些事件
  • 若要偵測卡頓(即跳過的畫面),請尋找極端值。例如,對於 Developer Quest 的特定案例和我們用於測試的設備,查看第 95 個百分位數的建構時間很有幫助。(即使比較具有截然不同的效率水準的程式碼,第 90 個百分位數的建構時間也過於相似,而第 99 個百分位數的數字往往會出現雜訊。您的情況可能有所不同。)
  • 如上所述,請對應用程式的每個版本執行多次測試(可能 100 次)。然後,使用具有誤差範圍的平均值或百分位數資料。更好的是,使用箱型圖。

結果

設定完畢後,您便能夠自信地比較提交和實驗。在下方,您可以看到針對常見困境的答案:「這個優化是否值得維護開銷?」

我認為在 特定 案例中,答案是肯定的。只需增加幾行程式碼,我們應用程式的每次自動瀏覽平均可以節省 12% 的 CPU 時間。

但是,這是本文的主要訊息 - 另一項優化的測量結果可能會顯示出截然不同的情況。試圖過度外推效能測量結果是引人入勝的,但錯誤的做法。

換句話說:「視情況而定」。我們應該接受這句話。


Flutter 應用程式的效能測試 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。

http://creativecommons.org/licenses/by/4.0/

【文章內容使用 Gemini 1.5 Pro 自動產生】

Flutter:為行動、網頁和桌面打造美麗的應用程式

今年在 I/O ‘19 中,我們發佈了有關 Flutter 的無數消息,如果您沒有全職追蹤所有消息,您可能會錯過其中一些。因此,這篇文章將彙集所有重大消息,以及來自新聞報導的重點。

在 Google I/O '19 開發者大會主題演講中,Adam Seligman 宣布 Flutter for Web 技術預覽版。

TL;DR

Flutter 從行動設備擴展到支援網頁和桌面:相同的程式碼庫,同樣關注於高生產力下快速、美麗的體驗。

新聞和公告

來自 Flutter 和 Dart 團隊的文章

來自合作團隊的文章

Flutter 和 Dart 主題演講和會議錄影

示範和 Codelabs

紐約時報 KENKEN 遊戲,顯示在 Chrome、macOS、行動 Safari、iPhone 和 Android 上運行。

新聞報導重點

  • “Flutter 已經取得了長足的進步,迅速成為跨 iOS 和 Android 的多平台編碼最佳框架之一。[…] 坦白說,對 Flutter 的積極反應讓人感到震驚。” (XDA 開發者)
  • “Google 的 Flutter UI 工具包專注於跨平台開發,可能只有兩年的歷史,但它已迅速成為許多開發人員的首選框架。” (TechCrunch)
  • “Google 正在解決應用程式開發人員面臨的最大障礙之一,這不僅讓開發人員的工作變得更輕鬆,而且讓他們的應用程式和服務在我們最常用的幾乎所有平台上都更易於使用,包括 Android、iOS、Windows 10、macOS、Chrome OS 和 Web 瀏覽器。” (BusinessInsider)
  • “顯然,Google 正在努力讓 Flutter 成為建立各種應用程式的最佳方式。無論您的應用程式是針對 Android、iOS、Chrome OS、Windows、Web、IoT 還是所有這些,都不再重要了,這真是太驚人了。” (9to5Google)
  • “這些更新今天宣布時收穫了許多歡呼聲,……意味著 Flutter 實際上成為了多平台 UI 框架。” (SiliconAngle)

請參閱 VentureBeatZDNetThurrott 等其他媒體報導。


Google I/O 上 Flutter 新聞彙總 最初發佈在 Flutter 上的 Medium,人們在那裡透過突出顯示和回應這個故事來繼續討論。