Android Compose 入門,深入底層源碼分析

来源:https://www.cnblogs.com/laomuji666/p/18126525
-Advertisement-
Play Games

Android Compose 入門,深入底層源碼分析 我是跟著AS官網學習的,但是官方的教程寫的不是很詳細.官網鏈接 首先創建一個Compose項目,目錄結構是這樣: ui -> theme -> -> Color.kt -> -> Theme.kt -> -> Type.kt MainActiv ...


Android Compose 入門,深入底層源碼分析

我是跟著AS官網學習的,但是官方的教程寫的不是很詳細.官網鏈接
首先創建一個Compose項目,目錄結構是這樣:
ui
-> theme
-> -> Color.kt
-> -> Theme.kt
-> -> Type.kt
MainActivity.kt
通過閱讀源碼,發現實際上還少了一個Shapes.kt,我手動添加了.

Type.kt

/**  
 * 存放組件的Style  
 * Typography全部是文字的屬性
 * 點開Typography的代碼,結構很簡單.
 * 存了一些TextStyle,提供以下功能:
 * 主構造函數: 使用一些預設參數初始化各個TextStyle
 * copy: 複製一份
 * equals: 比較每一個TextStyle
 * hashCode: 計算hash,把每個TextStyle都計算進去.
 * fromToken: internal修飾,為Typography類增加拓展函數,根據傳進來的enum,確認獲取哪個TextStyle.
 * 在class外部還有一個對象:
 * LocalTypography: internal修飾,被MaterialTheme作為預設參數使用
 */  
val Typography = Typography(  
    bodyLarge = TextStyle(  
        fontFamily = FontFamily.Default,  
        fontWeight = FontWeight.Normal,  
        fontSize = 16.sp,  
        lineHeight = 24.sp,  
        letterSpacing = 0.5.sp  
    )
)

Color.kt

/**  
 * 存放顏色值
 * darkColorScheme和lightColorScheme都屬於ColorScheme  
 * 點開ColorScheme的代碼,結構很簡單.
 * 存了一些Color,提供以下功能:
 * 主構造函數: 顏色委托給mutableStateOf,使顏色值的變化可以被Compose觀察.
 * copy: 複製一份
 * 剩下的是一些函數:
 * lightColorScheme: 提供預設的白天模式顏色
 * darkColorScheme: 提供預設的夜間模式顏色
 * ColorScheme.contentColorFor: 為ColorScheme類增加拓展函數,根據背景色使用對應的前景色,如果顏色不匹配,返回透明色.
 * contentColorFor: 提供一個函數,import這個函數來使用,如果顏色不匹配,返回黑色.
 * applyTonalElevation: internal修飾,為ColorScheme類增加拓展函數,返回新背景色,傳入的背景色加上高度.
 * surfaceColorAtElevation: 為ColorScheme類增加拓展函數,計算不同高度的surface錶面色調.
 * updateColorSchemeFrom: internal修飾,為ColorScheme類增加拓展函數,更新顏色,成本很高,但顏色委托給了mutableStateOf,忽略不變化的顏色值,提高運行效率.
 * fromToken: internal修飾,為ColorScheme類增加拓展函數,根據傳進來的enum,確認獲取哪個Color.
 * toColor: internal修飾,為ColorSchemeKeyTokens類增加拓展函數,將enum轉換為對應的顏色,調用fromToken.
 * 在class外部還有兩個對象:
 * LocalColorScheme: internal修飾,被MaterialTheme作為預設參數使用,預設使用lightColorScheme.
 * DisabledAlpha: internal修飾,禁用狀態的前景色.比如禁用按鈕的文字顏色.
 */  
val Purple80 = Color(0xFFD0BCFF)  
val PurpleGrey80 = Color(0xFFCCC2DC)  
val Pink80 = Color(0xFFEFB8C8)  

val Purple40 = Color(0xFF6650a4)  
val PurpleGrey40 = Color(0xFF625b71)  
val Pink40 = Color(0xFF7D5260)  

//深色模式  
val DarkColorScheme = darkColorScheme(  
    primary = Purple80,  
    secondary = PurpleGrey80,  
    tertiary = Pink80  
)  
  
//淺色模式  
val LightColorScheme = lightColorScheme(  
    primary = Purple40,  
    secondary = PurpleGrey40,  
    tertiary = Pink40,  
)

Shapes.kt

/**  
 * 預設創建的項目里沒有創建Shapes  
 * 這裡也簡單介紹一下  
 * 點開Shapes代碼,結構很簡單.  
 * 存放了一些形狀,提供以下功能:  
 * 主構造函數: 存放一些CornerBasedShape  
 * CornerBasedShape基於角的形狀,子類有: AbsoluteCutCornerShape,AbsoluteRoundedCornerShape,CutCornerShape,RoundedCornerShape.  
 * https://developer.android.com/reference/kotlin/androidx/compose/foundation/shape/CornerBasedShape * copy: 複製一份  
 * equals: 比較每個shape  
 * hashCode: 計算hash,把每個shape都計算進去.  
 * 類外部:  
 * ShapeDefaults: 提供CornerBasedShape的預設參數  
 * top,bottom,start,end: internal修飾,幫助組件獲取Shape.  
 * fromToken: internal修飾,根據傳入的enum,返回對應的Shape.  
 * toShape: internal修飾,為ShapeKeyTokens增加擴展函數,把enum轉為Shape,調用fromToken.  
 * LocalShapes: internal修飾,被MaterialTheme作為預設參數使用,預設使用ShapeDefaults.  
 */val shapes = Shapes(  
    extraSmall = ShapeDefaults.ExtraSmall  
)

Theme.kt

/**  
 * 構建一個Theme用來使用  
 * 如果不用自己構建的theme,會使用預設的theme.  
 * Theme很簡單,分為兩部分.  
 * 由Compose托管的:  
 * 使用colorScheme,shapes,typography,content創建一個MaterialTheme.  
 * content使用這個MaterialTheme,並且這個MaterialTheme會遞歸傳遞給content內的@Composable修飾的函數.  
 * 非Compose托管的:  
 * 一些不屬於View的,屬於window的.如狀態欄顏色,導航欄是否顯示等.  
 * 然後是MaterialTheme的源碼
 * MaterialTheme是一個@Composable修飾的函數,按照順序拆解:
 * rememberedColorScheme,用來更新顏色.調用updateColorSchemeFrom.使用remember讓currentComposer緩存colorScheme.copy()返回的對象,下次重組時繼續使用該值,涉及的內容太多,這裡不再深入.
 * rippleIndication,波紋動畫,預設使用透明色,也就是沒有波紋動畫.
 * selectionColors,文字選中顏色,預設使用:rememberedColorScheme.primary
 * CompositionLocalProvider,一個@Composable修飾的函數,使用上面的參數構建一個ProvidedValue對象,調用currentComposer.startProviders保存這些對象,然後調用content繪製,繪製時會使用這些ProvidedValue對象,然後調用currentComposer.endProviders()終止記錄.
 */  
/**  
 * @param darkTheme 是否是深色模式  
 * @param dynamicColor 動態顏色 安卓12(api31) 新增,會基於系統壁紙的顏色使用對應的顏色,https://developer.android.com/develop/ui/views/theming/dynamic-colors  
 * @param content Composable代碼塊,使用colorScheme作為主題色  
 */  
@Composable  
fun Study1Theme(  
    darkTheme: Boolean = isSystemInDarkTheme(),  
    dynamicColor: Boolean = true,  
    content: @Composable () -> Unit  
) {  
    //Material Design 需要的顏色  
    val colorScheme = when {  
        //使用動態顏色,跟隨壁紙,只有大於api31才能使用  
        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {  
            val context = LocalContext.current  
            if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)  
        }  
  
        darkTheme -> DarkColorScheme  
        else -> LightColorScheme  
    }  
  
    //獲取View,@Composable的組合函數實際上是一個View  
    val view = LocalView.current  
    //不是編輯模式的情況下,設置一些參數  
    if (!view.isInEditMode) {  
        //window不是Compose管理的對象,需要用SideEffect來共用Compose狀態,SideEffect保證每次重組後都會執行  
        SideEffect {  
            //設置status bar 顏色  
            val window = (view.context as Activity).window  
            window.statusBarColor = colorScheme.primary.toArgb()  
            WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme  
        }  
    }  
  
    //顏色,字體,代碼塊構建一個MaterialTheme對象,代碼塊的MaterialTheme對象會使用這個構建的對象  
    MaterialTheme(  
        colorScheme = colorScheme,  
        typography = typography,  
        shapes = shapes,  
        content = content  
    )  
}

MainActivity.kt

這個沒什麼好說的,官方的教程說的很明白了.這裡簡單貼一下代碼.

class MainActivity : ComponentActivity() {  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  
        //setContent是Kotlin的擴展函數,使用Compose創建視窗  
        setContent {  
            //Study1Theme在theme/Theme.kt里,生成MaterialTheme給整個代碼塊用  
            Study1Theme(dynamicColor = false) {  
                //使用一個@Composable函數來作為界面的入口  
                MyApp(Modifier.fillMaxSize())  
            }  
        }    }  
  
    //界面入口,用來複用函數  
    @Composable  
    fun MyApp(modifier: Modifier = Modifier){  
        //Surface,一般顯示組件的顏色,如卡片,表格,菜單的背景色  
        Surface(  
            //Modifier.fillMaxSize() 鋪滿父組件  
            modifier = modifier,  
            //使用Study1Theme里創建的MaterialTheme的colorScheme  
            //colorScheme現在有深色淺色兩種模式,也可以添加更多風格.  
            color = MaterialTheme.colorScheme.primary  
        ) {  
            //Surface函數的最後一個參數是content: @Composable () -> Unit  
            //@Composable註解修飾的函數只能被同樣@Composable修飾的函數調用  
            SayHello("Android")  
        }  
    }  
  
    //顯示一個文本  
    @Composable  
    fun SayHello(name: String, modifier: Modifier = Modifier) {  
        Surface(color = MaterialTheme.colorScheme.primary) {  
            Text(  
                text = "Hello $name!",  
                modifier = modifier.padding(24.dp)  
            )  
        }  
    }  
  
    //Preview可以預覽無參或者有預設參數的Compose函數  
    @Preview(showBackground = true, name = "Say Hello Preview")  
    @Composable  
    fun SayHelloPreview(name: String = "Compose") {  
        Study1Theme(dynamicColor = false) {  
            MyApp()  
        }  
    }  
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 引言 在我們上一篇文章瞭解了單元測試的基本概念和用法之後,今天我們來聊一下 TDD(測試驅動開發) 測試驅動開發 (TDD) 測試驅動開發英文全稱是Test Driven Development 簡稱 TDD。 根據 UncleBob 的 TDD 描述總結 我們先創建一個測試項目 直接在 VS 創建 ...
  • Keycloak是一個功能強大的開源身份和訪問管理系統,提供了一整套解決方案,包括用戶認證、單點登錄(SSO)、身份聯合、用戶註冊、用戶管理、角色映射、多因素認證和訪問控制等。它廣泛應用於企業和雲服務,可以簡化和統一不同應用程式和服務的安全管理,支持自托管或雲部署,適用於需要安全、靈活且易於擴展的用 ...
  • Avalonia是一個強大的跨平臺UI框架,允許開發者構建豐富的桌面應用程式。 它提供了眾多UI組件、靈活的佈局系統、可定製的樣式以及事件處理機制。 在這篇博客中,我們將詳細解析Avalonia的UI組件、UI組件的生命周期、佈局、樣式和事件處理。 一、UI組件 Avalonia提供了豐富的UI組件 ...
  • 在我寫虛擬記憶體時遇到一些問題,jalr t0就是可以的,而call main則沒辦法成功 而且這裡預設main是偏移前的地址,怪哉!!! 讓我們看看jalr 和call(偽指令!!!) 然後在鏈接後看看main的地址,主要看程式中main是不是偏移 懸著的心也死了!!! 查看一下ucore也有類似的 ...
  • linux伺服器部署了一個tcp服務,需要進行併發壓力測試 看看伺服器能支持多少個tcp長連接 預計會有50w個連接 需要設置linux 不然是無法支持這麼多連接的 如果達到這個值是無法建立新連接的 報錯信息一般為 too many open files 1 , fs.file-max linux系 ...
  • setreuid(-1,foo) 為何有時更新 saved set-user-id 有時不更新?man setreuid 中關於 SUID 變更的說明是否正確?如此設計有何考慮?本文通過閱讀 linux 源碼為你揭秘 ...
  • 痞子衡嵌入式半月刊: 第 97 期 這裡分享嵌入式領域有用有趣的項目/工具以及一些熱點新聞,農曆年分二十四節氣,希望在每個交節之日準時發佈一期。 本期刊是開源項目(GitHub: JayHeng/pzh-mcu-bi-weekly),歡迎提交 issue,投稿或推薦你知道的嵌入式那些事兒。 上期回顧 ...
  • @目錄前言簡介一、準備工作1.1 創建寫入腳本1.2 設置執行許可權1.3 添加定時任務1.4 配置生效二、Tomcat日誌 按每天分割2.1 創建一個 sh文件2.2 設置執行許可權2.3 設置crontab指令,指定每日定時任務2.4 配置生效總結 前言 請各大網友尊重本人原創知識分享,謹記本人博客 ...
一周排行
    -Advertisement-
    Play Games
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...
  • 目錄前言PostgreSql安裝測試額外Nuget安裝Person.cs模擬運行Navicate連postgresql解決方案Garnet為什麼要選擇Garnet而不是RedisRedis不再開源Windows版的Redis是由微軟維護的Windows Redis版本老舊,後續可能不再更新Garne ...
  • C#TMS系統代碼-聯表報表學習 領導被裁了之後很快就有人上任了,幾乎是無縫銜接,很難讓我不想到這早就決定好了。我的職責沒有任何變化。感受下來這個系統封裝程度很高,我只要會調用方法就行。這個系統交付之後不會有太多問題,更多應該是做小需求,有大的開發任務應該也是第二期的事,嗯?怎麼感覺我變成運維了?而 ...
  • 我在隨筆《EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)》中介紹了一些基本的EAV模型設計知識和基於Winform場景下低代碼(或者說無代碼)的一些實現思路,在本篇隨筆中,我們來分析一下這種針對通用業務,且只需定義就能構建業務模塊存儲和界面的解決方案,其中的數據查詢處理的操作。 ...
  • 對某個遠程伺服器啟用和設置NTP服務(Windows系統) 打開註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer 將 Enabled 的值設置為 1,這將啟用NTP伺服器功 ...
  • title: Django信號與擴展:深入理解與實踐 date: 2024/5/15 22:40:52 updated: 2024/5/15 22:40:52 categories: 後端開發 tags: Django 信號 松耦合 觀察者 擴展 安全 性能 第一部分:Django信號基礎 Djan ...
  • 使用xadmin2遇到的問題&解決 環境配置: 使用的模塊版本: 關聯的包 Django 3.2.15 mysqlclient 2.2.4 xadmin 2.0.1 django-crispy-forms >= 1.6.0 django-import-export >= 0.5.1 django-r ...
  • 今天我打算整點兒不一樣的內容,通過之前學習的TransformerMap和LazyMap鏈,想搞點不一樣的,所以我關註了另外一條鏈DefaultedMap鏈,主要調用鏈為: 調用鏈詳細描述: ObjectInputStream.readObject() DefaultedMap.readObject ...
  • 後端應用級開發者該如何擁抱 AI GC?就是在這樣的一個大的浪潮下,我們的傳統的應用級開發者。我們該如何選擇職業或者是如何去快速轉型,跟上這樣的一個行業的一個浪潮? 0 AI金字塔模型 越往上它的整個難度就是職業機會也好,或者說是整個的這個運作也好,它的難度會越大,然後越往下機會就會越多,所以這是一 ...
  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。 @Autowired預設按照類型自動裝配,而@Resource預設按照名稱自動裝配。 @Autowired支持@Qualifier註解來指定裝配哪一個具有相同類型的bean,而@Resourc... ...