Jetpack Compose學習(1)——從登錄頁開始入門

原文地址:Jetpack Compose學習(1)——從登錄頁開始入門 | Stars-One的雜貨小窩

Jetpack Compose UI在前幾天出了1.0正式版,之前一直還在觀望,終於是出了正式版 😃 趁著無事,來篇入門教程,希望給各位一點參考

注:由於compose UI使用了kotlin的DSL語言特性,所以需要熟悉Kotlin

Jetpack Compose介紹

Jetpack Compose 是一個用於構建原生 Android UI 的現代工具包。Jetpack Compose 用更少的程式碼、強大的工具和直觀的 Kotlin API 簡化並加速了 Android 上的 UI 開發。

Jetpack Compose使用了聲明式來編寫UI,本質上就是用程式碼寫布局,這裡說的程式碼不是特指,主要是與htmlxml等標識語言進行區別,在xml等語言中,我們無法使用if或循環等結構體來構造UI,而JetCompose Compose 而可以實現這點,這樣會讓我們布局更加靈活

如果之前各位也是接觸過Flutter,就會和我有一樣的體會,Jetpack Compose裡面的組件類定義跟Flutter那邊十分一致,我猜測肯定是有借鑒,畢竟那邊也是Google公司旗下的團隊整的

過多的就不說了,上正文吧 😝

簡單Hello World

首先,你需要一台聯網的電腦,下載Android Studio最新版(2020.3.1) 🦊,好久沒升級了,介面都感覺煥然一新了 😮

之後的環境配置這裡不多說了,下SDK,下模擬器,新人來 估計得折騰一天 由於我之前就已經下載過Android Studio,這裡直接下載好之後就可以使用了

我們按照官方的教程,直接新建一個Jetpack Compose項目

之後常規操作 ,填寫相關的包名即可新建了,之後又是等待下載相關依賴的東西,一切下載完畢就準備OK了

可一看右邊,一個紅色的背景,頓時人就有點煩了,還好不是什麼大問題,它提示我們需要build一下項目

行吧,我build一下,然後,人傻了,直接爆紅了💢

一看提示 好傢夥,最低的Java環境要11了,我也是服了,百度一搜

原來是Android官方那邊的坑,直接把gradle升級到最新版,你說你升級就升級吧,可沒想到gradle那邊最新版棄用JDK8了

解決方法有兩個

  • 更改Android Gradle Plugin和Gradle版本
  • 使用JDK11環境

更改Android Gradle Plugin和Gradle版本,也就是下圖這兩個東西,自己參考下之前舊版本項目的版本號改即可

PS: 通過File -> Project Structure打開下面的介面

下圖是我自己舊項目使用的版本號,各位可以參考下

舊項目使用的版本號

至於換JDK11,其實也是比較簡單,我是環境變數都是用著JDK8,因為還有舊項目需要使用(TornadoFx),所以,我們只改項目里使用的JDK版本即可

進到設置里修改即可,如下圖

Android Studio其實內置有個JDK11,我們直接使用這個即可,而且,不會影響其他新開的項目

gradle使用JDK11

經過上面的設置後,我們可以重新build下項目,可以發現右側已經可以預覽了

我們先簡單分析一下程式碼

onCreate()中,有個setContent(),用來設置頁面的主體內容,我們先不管ComposeDemoThemeSurface,Greeting("Android")是我們要關心的

setContent {
    ComposeDemoTheme {
        // A surface container using the 'background' color from the theme
        Surface(color = MaterialTheme.colors.background) {
            Greeting("Android")
        }
    }
}

此方法上有個註解@Composable,用來表示當前方法返回的是一個組件,我們可以更改其中的數值,可以看到右側會實時的進行變化

提示: 實時渲染只針對數值的改變,如果你新增一個組件,是沒有實時變化效果的,需要重新build一次

下面也有個方法,除了@Composable註解,還有有個@Preview,Preview主要是標明用來預覽的

標有@Preview註解的方法,不能存在有參數,否則無法預覽

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    ComposeDemoTheme {
        // A surface container using the 'background' color from the theme
        Surface(color = MaterialTheme.colors.background) {
            Greeting("Android")
        }
    }
}

登錄頁實現

上面也是比較簡單的講解了下程式碼,下面我們來個登錄頁實例來操作下吧

與Flutter一樣,Jetpack Compose沒有線性布局(LinearLayout),但有Row和Column兩個布局,從名字可以看得出來,一種是水平布局,一種是垂直布局

我們先簡單搭建個登錄頁面

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    ComposeDemoTheme {
        Column() {
            Row() {
                Text(text = "用戶名")
                TextField(value = "", onValueChange = {str -> Log.e("test",str)})
            }
            Row() {
                Text(text = "密碼")
                TextField(value = "", onValueChange = {str -> Log.e("test",str)})
            }
            TextButton(onClick = { }) {
                Text(text = "登錄")
            }
        }
    }
}

上面程式碼中出現了幾個組件Text,TextField和TextButton,字面意思很好理解

組件名 作用
Text 文本
TextField 輸入框
TextButton 文字按鈕

預覽效果如下圖所示:

測試的發現,無法輸入文字,這是怎麼回事呢?

因為Jetpack Compose使用了類似MVVM的數據綁定的方式,所以,我們得給輸入框綁定一個變數,onValueChange方法數值改變的時候會回調,我們在回調更改變數的數值即可達到更改UI的效果

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    var name by remember { mutableStateOf("") }
    var pwd by remember { mutableStateOf("") }

    ComposeDemoTheme {
        Column() {
            Row() {
                Text(text = "用戶名")
                TextField(value = name, onValueChange = { str -> name = str })
            }
            Row() {
                Text(text = "密碼")
                TextField(value = pwd, onValueChange = { str -> pwd = str })
            }
            TextButton(onClick = { }) {
                Text(text = "登錄")
            }
        }
    }
}

上面程式碼出現了remembermutableStateOf的兩個關鍵字,但本章作為入門篇,先暫時不講解過多知識,先放著,後續再進行補充

最後,我們還差一步,就是判斷輸入的帳號和密碼是否正確,然後彈出登錄失敗或登錄成功的提示

這裡,我準備使用傳統簡單的Toast進行提示,但是Toast需要傳一個Context,由於組件的那個函數是寫在Activity外面的,所以是拿不到Activity本身的,但是我們可以把Activity本身傳到方法里(但不確定我這方法規不規範)

PS:看了下對話框的使用,覺得有些複雜,也是放在之後再講解吧

@Composable
fun DefaultPreview(context: Activity) {
    var name by remember { mutableStateOf("") }
    var pwd by remember { mutableStateOf("") }

    ComposeDemoTheme {
        Column() {
            Row() {
                Text(text = "用戶名")
                TextField(value = name, onValueChange = { str -> name = str })
            }
            Row() {
                Text(text = "密碼")
                TextField(value = pwd, onValueChange = { str -> pwd = str })
            }
            TextButton(onClick = {
                if (name == "test" && pwd == "123") {
                    Toast.makeText(context, "登錄成功", Toast.LENGTH_SHORT).show()
                } else {
                    Toast.makeText(context, "登錄失敗", Toast.LENGTH_SHORT).show()
                }
            }) {
                Text(text = "登錄")
            }
        }
    }
}

最後效果如下圖所示

登錄動圖

參考

Tags: