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
  • 前言 插件化的需求主要源於對軟體架構靈活性的追求,特別是在開發大型、複雜或需要不斷更新的軟體系統時,插件化可以提高軟體系統的可擴展性、可定製性、隔離性、安全性、可維護性、模塊化、易於升級和更新以及支持第三方開發等方面的能力,從而滿足不斷變化的業務需求和技術挑戰。 一、插件化探索 在WPF中我們想要開 ...
  • 歡迎ReaLTaiizor是一個用戶友好的、以設計為中心的.NET WinForms項目控制項庫,包含廣泛的組件。您可以使用不同的主題選項對項目進行個性化設置,並自定義用戶控制項,以使您的應用程式更加專業。 項目地址:https://github.com/Taiizor/ReaLTaiizor 步驟1: ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • Channel 是乾什麼的 The System.Threading.Channels namespace provides a set of synchronization data structures for passing data between producers and consume ...
  • efcore如何優雅的實現按年分庫按月分表 介紹 本文ShardinfCore版本 本期主角: ShardingCore 一款ef-core下高性能、輕量級針對分表分庫讀寫分離的解決方案,具有零依賴、零學習成本、零業務代碼入侵適配 距離上次發文.net相關的已經有很久了,期間一直在從事java相關的 ...
  • 前言 Spacesniffer 是一個免費的文件掃描工具,通過使用樹狀圖可視化佈局,可以立即瞭解大文件夾的位置,幫助用戶處理找到這些文件夾 當前系統C盤空間 清理後系統C盤空間 下載 Spacesniffer 下載地址:https://spacesniffer.en.softonic.com/dow ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • 一、ReZero簡介 ReZero是一款.NET中間件 : 全網唯一開源界面操作就能生成API , 可以集成到任何.NET6+ API項目,無破壞性,也可讓非.NET用戶使用exe文件 免費開源:MIT最寬鬆協議 , 一直從事開源事業十年,一直堅持開源 1.1 純ReZero開發 適合.Net Co ...
  • 一:背景 1. 講故事 停了一個月沒有更新文章了,主要是忙於寫 C#內功修煉系列的PPT,現在基本上接近尾聲,可以回頭繼續更新這段時間分析dump的一些事故報告,有朋友微信上找到我,說他們的系統出現了大量的http超時,程式不響應處理了,讓我幫忙看下怎麼回事,dump也抓到了。 二:WinDbg分析 ...
  • 開始做項目管理了(本人3年java,來到這邊之後真沒想到...),天天開會溝通整理需求,他們講話的時候忙裡偷閑整理一下常用的方法,其實語言還是有共通性的,基本上看到方法名就大概能猜出來用法。出去打水的時候看到外面太陽好好,真想在外面坐著曬太陽,回來的時候好兄弟三年前送給我的鍵盤D鍵不靈了,在打"等待 ...