降Compose十八掌之『見龍在田』| Modifier

公眾號「稀有猿訴」 ?????? 原文鏈接 降Compose十八掌之『見龍在田』| Modifier

通過前面的文章我們學會了如何使用元素來構建和填充我們的UI頁面,但這只完成了一半,元素還需要裝飾,以及進行動畫和事件響應,這才能生成完整的UI。這就要用到Modifier,Jetpack Compose中的靈魂,它被用來裝飾和增強Composables,讓一個個平凡的元素變成鮮活的,好看的,可交互UI。我們來具體的看一下Modifier的使用方法。

對于Compose來說,每一個元素叫做Composable,它是一個函數,比如前面學過的布局(如Row)和小部件(如Text)等都是一個Composable,可以把它理解成為一個元素。

概念和基本使用方法

Modifier之于元素,猶如CSS之于HTML,但能做的更多,因為除了樣式裝飾以外,Modifier還能做很多事情,比如響應用戶輸入。

每一個Composable都可以接收一個Modifier參數,準確地說第一個參數都是Modifier,可以把一個Modifier對象作為第一個參數傳給元素;也可以用命名參數如modifier = Modifier.padding(8.dp)。Modifier支持鏈式調用,它的每個方法都會把當前對象返回:

@Composable
private fun Greeting(name: String) {Column(modifier = Modifier.padding(24.dp).fillMaxWidth()) {Text(text = "Hello,")Text(text = name)}
}

裝飾元素的樣式

重點來看一下如何用Modifier裝飾元素的樣式。需要注意的是Modifier是裝飾元素的共性樣式如尺寸,背景,邊框和位移等等,而像具體元素特性,如Text中的文本樣式,是無法用Modifier來修改的。

尺寸Size

尺寸對于一個UI元素來說是必要的,就是渲染之后的視覺上的寬度和高度。可以通過Modifier的下列函數來進行尺寸約束:

  • width/height - 指定固定的偏好寬度和偏好高度,參數傳入具體的數值如Modifier.width(320.dp).height(480.dp),就是指定某個元素的寬度是320dp,高度是480dp。偏好(preferred)的意思是可能會被其他約束條件覆蓋,而最終值可能會不一樣。
  • size - 同時指定寬度和高度為某一偏好的數值,只傳一個參數就是一個正方形,如Modifier.size(100.dp),等同于Modifier.width(100.dp).height(100.dp);傳兩個參數時分別指定寬和高,如Modifier.size(320.dp, 480.dp)等同于Modifier.width(320.dp).height(480.dp)。
  • wrapContentWidth/wrapContentHeight/wrapContentSize - 讓元素自己決定尺寸,無視最小尺寸限制(minimum_wdith/minimum_height),類似于XML中的wrap_content,這是比較嚴格的限制。
  • requiredWidth/requiredHeight - 指定寬度和高度必須為某一數值,不可以被其他限制約束覆蓋。帶有In的函數可以指定一個范圍。
  • requiredSize - 指定寬度和高度必須為某一數值,帶有In的函數可以指定范圍。
  • widthIn/heightIn/sizeIn - 帶有in的函數,可以指定一個范圍而非具體數值,比如Modifier.widthIn(10.dp, 100.dp),就是說限制此元素的寬度為10dp到100dp之間。
  • fillMaxWidth/fillMaxHeight - 不固定具體的數值,按比例填充最大可用空間,比例為1.0時填滿,類似于XML中的match_parent。
  • fillMaxSize - 按比例填充滿可用空間。
  • weight - 權重比例,僅在父布局是Row或者Column時,且尺寸與父布局約束一致時有效,比如在Row中,對width生效,在Column中對height生效。最終的占比是『權重比例 x 可用空間』,不指定weight則weight是0,比如一個Row中,有三個元素,其中兩個元素A和B指定了weight為1和2,另一個沒指定,那么A將占Row中剩余可用寬度的1/3,B將占2/3。與View中的LinearLayout中的權重是差不多的。

Modifier修飾尺寸的函數比較多,容易學雜了,需要梳理一下:size相當于快捷方式,可以同時約束寬和高;帶有In的函數可以為某個約束指定范圍。寬高是一種限制性約束,不同的函數的限制嚴格性是不一樣的,帶有required是最嚴格的限制約束,優先級最高,如有沖突,以它為準;wrapContentWidth/wrapContentHeight/wrapContentSize是較嚴格的限制,僅次于required;width/height/size是中等嚴格,較wrapContent再次之;weight再次之;fillMax則是最弱的限制。

間隔

間隔(padding)是在元素與其邊界之間添加的額外的空白空間,Modifier.padding不影響元素的尺寸,它是在測量之前就應用生效。

對于有XML經驗的同學來說,以往的間隔有兩個,一個是margin控制著元素邊界之外的間隔,padding控制著邊界與元素本身內容間隔。對于Modifier來說,只有一個函數,在不同的位置調用padding函數會有不同的效果,如果在尺寸之后調用padding,則是調整邊界與內容之間的間隔,如果是在尺寸之前調用,則是調整邊界與外部的間隔。另外,就是padding不可以傳負值。

@Composable
fun PaddingDemo(modifier: Modifier = Modifier.fillMaxSize()) {Box(modifier = Modifier.fillMaxSize().background(Color.LightGray)) {Text(text = "降龍十八掌",style = MaterialTheme.typography.headlineLarge,modifier = Modifier.padding(16.dp) // As margin: outside space beyond border.background(Color.Cyan).size(360.dp, 120.dp).padding(10.dp) // As padding: space between border and content)}
}

padding_demo.png

位移Offset

函數Modifier.offset用來給水平和垂直方向加一個位移,數值可正可負,注意僅是增加位移,并不會改變元素的尺寸。與View中的translateX和translateY是類似的。它有兩個函數,只有一個參數時是水平和垂直方向都加上相同的位移;兩個參數時是分別指定水平方向和垂直方向。

@Composable
fun ModifierDemo(modifier: Modifier = Modifier.fillMaxSize()) {var offset by remember { mutableStateOf(0) }Column(modifier = modifier.padding(8.dp).clickable { offset += 8 }) {Text(text = "降龍十八掌",style = MaterialTheme.typography.headlineLarge,color = MaterialTheme.colorScheme.primary,modifier = Modifier.offset(offset.dp, offset.dp).background(Color.Cyan).padding(16.dp))}
}

offset_demo.gif

因為offset并不改變元素的尺寸,僅是在原位置上進行偏移,所以多用于點擊效果,或者點擊動畫。

背景Background

使用Modifier.background函數來修改元素的背景顏色,唯一需要注意的是padding的影響,background是給尺寸所指定的區域加背景色,所以padding調用的位置會有影響。

邊框Border

用Modifier.bodrer函數可以指定邊框的樣式,如形狀,粗細,線條和顏色。需要注意的是它也是跟尺寸一樣的,受padding的影響:

@Composable
fun BorderWithShape(modifier: Modifier = Modifier.fillMaxSize()) {Box {Text(text = "降龍十八掌",style = MaterialTheme.typography.headlineLarge,modifier = Modifier.padding(10.dp).border(2.dp, SolidColor(Color.Green), RoundedCornerShape(20.dp)).padding(10.dp))}
}

border_demo.png

變幻

Modifier還能對元素進行一些變幻,如透明度(Alpha),旋轉(Rotate)和縮放(Scale)。通常用來實現一些非動畫的靜態特效。

Modifier.alpha指定透明度,0是透明,1是完全不透明,默認值是1.0。

Modifier.rotate實現旋轉,參數是一個角度,順時針旋轉為正值,逆時針旋轉為負值,默認值是0度。

Modifier.scale是以元素的幾何中心為中心點進行縮放負值會進行水平和垂直方向翻轉:

@Composable
fun TransformationDemo(modifier: Modifier = Modifier.fillMaxSize()) {Box(modifier = Modifier.fillMaxSize().background(Color.LightGray)) {Text(text = "降龍十八掌",style = MaterialTheme.typography.headlineLarge,color = MaterialTheme.colorScheme.primary,modifier = Modifier.padding(16.dp).alpha(0.618f).rotate(11.8f).scale(0.618f).background(Color.Cyan).size(360.dp, 120.dp).offset(10.dp, 10.dp))}
}

transformation_demo.png

事件監聽

Modifier.clickable函數用來指定點擊事件響應。此外,還可以用于指定元素是否可以點擊。

另外,還可以通過Modifier.scrollable來指定元素是否可以滑動。

最佳實踐

Modifier是非常強大的,也是非常復雜的,前面列出的都是最為常用的一些函數。接下再來學習一下使用Modifier時需要注意的事項。

順序很重要

Modifier有很多很多函數,修改著同一個對象實例,有些函數會相互影響,因此這些函數的調用順序就變得相當重要,特別是涉及尺寸強相關的裝飾特性時,如background和border,它們會受到padding以及變幻的影響。比如前面變幻小節的例子,可以試著修改函數的調用順序,就會發現結果會不一樣。在實例使用時,如果出現與預期不一致的結果時,就嘗試調整一下Modifiier函數的順序,看是否是順序 導致的。

留意上下文

在Compose中,有一些Modifier函數只能在特定的元素中使用,這就涉及了Compose上下文(Scope)。比如說像Modifier.align只能在BoxScope中使用,也就是說只能在Box的子元素中使用。對其他任何布局來說都是不能用的,所以在使用的時候也要注意元素所在的父布局。

盡可能的復用

每個元素在渲染的時候都需要一個Modifier對象,通常情況下都是通過Modifier的函數進行對象創建。但對于一些循環的場景,且Modifier對象沒啥變化 時,這時就應該復用對象,而非每次都創建。比如說動畫,以及像集合性布局的子布局,這時都應該在其父布局緩存Modifier對象,直接傳給子元素,而不是讓其每次都創建新對象:

val modifier = Modifier.padding(12.dp).background(Color.Gray)
@Composable
fun LoadingWheelAnimation() {val animatedState = animateFloatAsState(/*...*/)LoadingWheel(// 把Modifier對象緩存到上一級的父布局中,以免每幀動畫都創建一個Modifier對象modifier = reusableModifier,animatedState = animatedState)
}

對于集合性布局也最好是能復用Modifier對象:

val reusableItemModifier = Modifier.padding(bottom = 12.dp).size(216.dp).clip(CircleShape)@Composable
private fun AuthorList(authors: List<Author>) {LazyColumn {items(authors) {AsyncImage(// 提升到上一級中時進行緩存,而不是每次都創建modifier = reusableItemModifier,)}}
}

保持一致性

一致性對于代碼的可維護性和可擴展性是非常重要的,因為每個元素都需要Modifier對象,在Compose中到處都可以看到Modifier,在實際使用中保持一致性就非常重要。比如說Modifier要作為Composable的第一個參數,參數的命名應該是modifier,并且最好要有默認值,可以查閱Compose本身的代碼,可以發現其所有的元素都遵循此約定。另外,就是對于共性的裝飾要提升到父布局中進行統一設定,比如說根布局統一設定padding,而不是每個子布局進行分別設定,等等。

參考資料

  • Compose modifiers
  • 6. Jetpack Compose Modifiers
  • 6. Using Compose Modifiers

subscription

歡迎搜索并關注 公眾號「稀有猿訴」 獲取更多的優質文章!

保護原創,請勿轉載!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/43877.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/43877.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/43877.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2.5章節python中布爾類型

在Python中&#xff0c;布爾類型&#xff08;Boolean type&#xff09;用于表示真&#xff08;True&#xff09;或假&#xff08;False&#xff09;的值。這是編程中非常基礎且重要的一個概念&#xff0c;因為它允許程序進行條件判斷&#xff0c;從而根據條件執行不同的代碼塊。…

智慧校園行政辦公-紅頭文件功能概述

在智慧校園的行政辦公系統中&#xff0c;紅頭文件的管理功能是一項重要的組成部分&#xff0c;它極大地提升了文件處理的效率與規范性。該功能圍繞文件的創建、審批、歸檔等關鍵環節&#xff0c;進行了全面的數字化改造。 首先&#xff0c;系統內置了多種標準化的紅頭文件模板&…

一文實踐強化學習訓練游戲ai--doom槍戰游戲實踐

一文實踐強化學習訓練游戲ai–doom槍戰游戲實踐 上次文章寫道下載doom的環境并嘗試了簡單的操作&#xff0c;這次讓我們來進行對象化和訓練、驗證&#xff0c;如果你有基礎&#xff0c;可以直接閱讀本文&#xff0c;不然請你先閱讀Doom基礎知識&#xff0c;其中包含了下載、動作…

gsplat中的3D Gaussian Splatting as Markov Chain Monte Carlo的代碼解讀

總體 https://github.com/nerfstudio-project/gsplat simple_trainer_mcmc.py 2個關鍵點&#xff1a; 高斯狀態轉移&#xff08;每100iter調用&#xff09;高斯隨機過程&#xff08;每1iter調用&#xff09; relocate_gs 對 alive gs 進行采樣&#xff0c;被采樣的 alive…

打開ps提示dll文件丟失如何解決?教你幾種靠譜的方法

在日常使用電腦過程中&#xff0c;由于不當操作&#xff0c;dll文件丟失是一種常見現象。當dll文件丟失時&#xff0c;程序將無法正常運行&#xff0c;比如ps&#xff0c;pr等待軟件。此時&#xff0c;我們需要對其進行修復以恢復其功能&#xff0c;下面我們一起來了解一下出現…

【堆 (優先隊列) 掃描線】218. 天際線問題

本文涉及知識點 堆 &#xff08;優先隊列) 掃描線 LeetCode218. 天際線問題 城市的 天際線 是從遠處觀看該城市中所有建筑物形成的輪廓的外部輪廓。給你所有建筑物的位置和高度&#xff0c;請返回 由這些建筑物形成的 天際線 。 每個建筑物的幾何信息由數組 buildings 表示&…

景芯SoC訓練營DFT debug

景芯訓練營VIP學員在實踐課上遇到個DFT C1 violation&#xff0c;導致check_design_rule無法通過&#xff0c;具體報錯如下&#xff1a; 遇到這個問題第一反映一定是確認時鐘&#xff0c;于是小編讓學員去排查add_clock是否指定了時鐘&#xff0c;指定的時鐘位置是否正確。 景芯…

C語言文件操作-文件IO(系統調用)

文件IO (系統調用) 文件描述符open函數read函數write函數lseek函數close函數dup函數dup2函數 stat函數getpwuid函數getgrgid函數 實例 目錄操作 opendir函數readdir函數rewinddir函數closedir函數實例 文件IO (系統調用) 文件IO就是系統調用&#xff0c;用戶空間進入內核空間…

2024年信息系統項目管理師1批次上午客觀題參考答案及解析(3)

51、探索各種選項&#xff0c;權衡包括時間與成本、質量與成本、風險與進度、進度與質量等多種因素&#xff0c;在整個過程中&#xff0c;舍棄無效或次優的替代方案&#xff0c;這種不確定性應對方法是()。 A&#xff0e;集合設計 B&#xff0e;堅韌性 C&#xff0e;多種結果…

離線運行Llama3:本地部署終極指南_liama2 本地部署

4月18日&#xff0c;Meta在官方博客官宣了Llama3&#xff0c;標志著人工智能領域邁向了一個重要的飛躍。經過筆者的個人體驗&#xff0c;Llama3 8B效果已經超越GPT-3.5&#xff0c;最為重要的是&#xff0c;Llama3是開源的&#xff0c;我們可以自己部署&#xff01; 本文和大家…

衡量股票價值的尺度

勞倫女士說&#xff0c;“鄧普頓獵取便宜股的時候&#xff0c;總是運用證券分析師的‘一百種價值衡量尺度’中的好幾種。 原因之一呢&#xff0c;就是因為任何一種衡量方法都是萬能的&#xff0c;在不同的時期、不同的市場環境下&#xff0c;總會有它自己的局限性。就像有朋友…

大數據------JavaWeb------FilterListenerAJAXAxiosJSON

Filter Filter簡介 定義&#xff1a;Filter表示過濾器&#xff0c;是JavaWeb三大組件&#xff08;Servlet、Filter、Listener&#xff09;之一。 作用&#xff1a;它可把對資源&#xff08;Servlet、JSP、Html&#xff09;的請求攔截下來從而實現一些特殊功能 過濾器一般完成…

【QT中實現攝像頭播放、以及視頻錄制】

學習分享 1、效果圖2、camerathread.h3、camerathread.cpp4、mainwindow.h5、mainwindow.cpp6、main.cpp 1、效果圖 2、camerathread.h #ifndef CAMERATHREAD_H #define CAMERATHREAD_H#include <QObject> #include <QThread> #include <QDebug> #include &…

SAP顧問的核心競爭力是什么?

最近看到幾個業內大佬在討論這個話題&#xff0c;我也想談談我的看法。這位大佬的原話是“SAP顧問的核心技能不是配置軟件&#xff0c;而是對財務、供應鏈、銷售等運行流程的理解&#xff0c;解決的是企業流程和數據標準化的問題。” 我先不做評價&#xff0c;我先問幾個問題。…

選擇排序(C語言版)

選擇排序是一種簡單直觀的排序算法 算法實現 首先在未排序序列中找到最小&#xff08;大&#xff09;元素&#xff0c;存放到排序序列的起始位置。 再從剩余未排序元素中繼續尋找最小&#xff08;大&#xff09;元素&#xff0c;然后放到已排序序列的末尾。 重復第二步&…

【k8s安裝redis】k8s安裝單機版redis實現高性能高可用

文章目錄 簡介一.條件及環境說明&#xff1a;二.需求說明&#xff1a;三.實現原理及說明四.詳細步驟4.1.創建configmap 配置文件4.2.創建StatefulSet 配置4.3.創建service headless 配置 五.安裝說明 簡介 本文將根據在k8s環境中搭建【偽】單機模式的redis實例。由于共享存儲的…

020-GeoGebra中級篇-幾何對象之點與向量

本文概述了在GeoGebra中如何使用笛卡爾或極坐標系輸入點和向量。用戶可以通過指令欄輸入數字和角度&#xff0c;使用工具或指令創建點和向量。在笛卡爾坐標系中&#xff0c;示例如“P(1,0)”&#xff1b;在極坐標系中&#xff0c;示例如“P(1;0)”或“v(5;90)”。文章還介紹了點…

深入理解循環神經網絡(RNN)

深入理解循環神經網絡&#xff08;RNN&#xff09; 循環神經網絡&#xff08;Recurrent Neural Network, RNN&#xff09;是一類專門處理序列數據的神經網絡&#xff0c;廣泛應用于自然語言處理、時間序列預測、語音識別等領域。本文將詳細解釋RNN的基本結構、工作原理以及其優…

uniapp本地打包到Android Studio生成APK文件

&#xff08;1&#xff09;安裝 Android Studio 軟件&#xff1b; 下載地址&#xff1a;官方下載地址&#xff0c;英文環境 安裝&#xff1a;如下之外&#xff0c;其他一鍵 next &#xff08;2&#xff09;配置java環境&#xff1b; 下載&#xff1a;j…

基于SpringBoot構造超簡易QQ郵件服務發送 第二版

目錄 追加 郵箱附件 添加依賴 編碼 測試 第二版的更新點是追加了 郵箱附件功能 ( 后期追加定時任務 ) 基于SpringBoot構造超簡易QQ郵件服務發送(分離-圖解-新手) 第一版 追加 郵箱附件 添加依賴 <!-- 電子郵件 --><dependency><groupId>org.spri…