Kotlin 中的 Android 基礎(chǔ)知識(shí) - Kotlin basics

教程取自于Google官方課程之Android Basics in Kotlin

Android Basics in Kotlin

Welcome to Android Basics in Kotlin! In this course, you'll learn the basics of building Android apps with the Kotlin programming language. Along the way, you'll develop a collection of apps to start your journey as an Android developer.


Unit 1: Kotlin basics

1.3 構(gòu)建基本布局

了解如何向 Android 應(yīng)用中添加圖片和文本。

1.3.2 創(chuàng)建 Birthday Card 應(yīng)用

界面簡(jiǎn)介

應(yīng)用的界面 (UI) 就是您在屏幕上所看到的內(nèi)容,包括文本、圖片、按鈕和許多其他類(lèi)型的元素。它既是應(yīng)用向用戶顯示內(nèi)容的方式,也是用戶與應(yīng)用展開(kāi)互動(dòng)的載體。

其中的每個(gè)元素都是所謂的 View。您在應(yīng)用屏幕上看到的所有內(nèi)容幾乎均屬于 View。Views 還可以是互動(dòng)元素,例如可點(diǎn)擊的按鈕或可修改的輸入字段。

Android 應(yīng)用中的 Views 并非獨(dú)自懸浮在屏幕上。各個(gè) Views 之間彼此存在關(guān)聯(lián)。例如,圖片可能位于某些文本旁邊,幾個(gè)按鈕也可能會(huì)自成一行。若要整理 Views,您可以將它們放到一個(gè)容器中。ViewGroup 就是一個(gè)可在其中放入 View 對(duì)象的容器,負(fù)責(zé)排列內(nèi)部的各個(gè) Views。排列方式(即布局)可能會(huì)因運(yùn)行應(yīng)用的 Android 設(shè)備的屏幕尺寸和寬高比而發(fā)生變化,并且可以根據(jù)設(shè)備是處于縱向還是橫向模式做出調(diào)整。

ConstraintLayout 就是一種 ViewGroup,可幫助您靈活地排列其內(nèi)部的 Views。

ViewGroup
布局編輯器簡(jiǎn)介

打開(kāi)布局編輯器后,您會(huì)看到許多窗口。在本 Codelab 中,您將學(xué)習(xí)如何使用其中的大部分窗口。請(qǐng)參考下方帶有注解的屏幕截圖,幫助您識(shí)別布局編輯器中的窗口。在更改應(yīng)用時(shí),您將會(huì)對(duì)每一個(gè)窗口作進(jìn)一步了解。

  • 左側(cè)標(biāo)注 (1) 處就是您之前已看到的 Project 窗口,其中列出了構(gòu)成您項(xiàng)目的所有文件。
  • 在中心區(qū)域,您能看到標(biāo)注 (4) 和 (5) 的兩個(gè)繪圖窗口,代表應(yīng)用的屏幕布局。左側(cè)標(biāo)注 (4) 的窗口呈現(xiàn)的是應(yīng)用在運(yùn)行時(shí)屏幕將呈現(xiàn)的近似效果,也就是所謂的 Design 視圖。
  • 右側(cè)標(biāo)注 (5) 的窗口呈現(xiàn)的是 Blueprint 視圖。在執(zhí)行特定操作時(shí),該視圖會(huì)非常有用。
  • 標(biāo)注 (2) 的 Palette 窗口包含的是您可以向應(yīng)用添加的各類(lèi) Views 的列表。
  • 標(biāo)注 (3) 的 Component Tree 窗口則是屏幕視圖的另一種呈現(xiàn)形式。它會(huì)列出屏幕的所有視圖。
  • 最右邊標(biāo)注 (6) 的窗口是 Attributes 視圖,其中顯示了 View 的各個(gè)屬性。您可在此處更改這些屬性。
布局編輯器
放置 TextView

向頂部和左側(cè)添加的約束條件將帶有外邊距。外邊距用于指定 View 離它所在容器的邊緣有多遠(yuǎn)。

  1. 在右側(cè)的 Attributes 中,找到 Layout 部分中的 Constraint Widget。其中顯示的方形代表您的視圖。


    Constraint Widget
  2. 點(diǎn)擊方形頂部的 +。這會(huì)在文本視圖的頂部與約束布局的上邊緣之間添加約束條件。
  3. 系統(tǒng)會(huì)顯示一個(gè)帶數(shù)字的字段,用于設(shè)置上外邊距。該外邊距是指從 TextView 到容器(即 ConstraintLayout)邊緣的距離。顯示的數(shù)字會(huì)因您放下 TextView 的位置而有所不同。在您設(shè)置上外邊距時(shí),Android Studio 還會(huì)在文本視圖的頂部和 ConstrainLayout 的頂部之間自動(dòng)添加約束條件。

1.3.3 向 Android 應(yīng)用添加圖片

為項(xiàng)目添加圖片
  1. 在 Android Studio 中,在菜單中依次點(diǎn)擊 View > Tool Windows > Resource Manager,或者點(diǎn)擊 Project 窗口左側(cè)的 Resource Manager 標(biāo)簽頁(yè)。
  2. 點(diǎn)擊 Resource Manager 下方的 +,然后選擇 Import Drawables。系統(tǒng)隨即會(huì)打開(kāi)一個(gè)文件瀏覽器。


    Resource Manager

    3.在文件瀏覽器中,找到已下載的圖片文件,然后點(diǎn)擊 Open。點(diǎn)擊 Next。Android Studio 會(huì)向您顯示該圖片的預(yù)覽。點(diǎn)擊 Import。
    如果圖片導(dǎo)入成功,Android Studio 就會(huì)將此圖片添加到 Drawable 列表中。此列表包含該應(yīng)用的所有圖片和圖標(biāo)。

添加 ImageView 并設(shè)置其圖片
  1. 在布局編輯器中,轉(zhuǎn)到 Palette 并將 ImageView 拖動(dòng)到應(yīng)用上,將其放在靠近中心的位置,且不與任何文本重疊
    此時(shí),系統(tǒng)會(huì)打開(kāi) Pick a Resource 對(duì)話框。此對(duì)話框列出了可供您應(yīng)用使用的所有圖片資源。請(qǐng)注意生日?qǐng)D片列于 Drawable 標(biāo)簽頁(yè)下??衫L制資源是圖形的一般概念,是指可在屏幕上繪制的圖形,其中包括圖片、位圖、圖標(biāo)以及許多其他類(lèi)型的繪圖資源。
  2. 在 Pick a Resource 對(duì)話框中,從 Drawable 列表里找到蛋糕圖片。點(diǎn)擊該圖片,然后點(diǎn)擊 OK。
放置 ImageView 并調(diào)整其大小
  1. 在布局編輯器中點(diǎn)擊并拖動(dòng) ImageView。在拖動(dòng)時(shí),您會(huì)看到 Design 視圖中應(yīng)用屏幕的周?chē)鷷?huì)顯示粉色矩形邊框。粉色矩形邊框表示放置 ImageView 的屏幕邊界。
  2. 拖動(dòng) ImageView,使其左右邊緣與粉色矩形對(duì)齊。當(dāng)您靠近時(shí),Android Studio 便會(huì)讓該圖片“貼靠”邊緣。ConstraintLayout 中的 Views 需要具有水平和垂直約束條件,以便告知 ConstraintLayout 如何放置這些視圖。接下來(lái),您將添加這些約束條件。
  3. 將指針懸停在 ImageView 輪廓頂部的圓圈上,這個(gè)圓圈便會(huì)與另一個(gè)圓圈一起突出顯示。如果將圓圈拖向應(yīng)用屏幕的頂部,那么在您拖動(dòng)時(shí),會(huì)有一個(gè)箭頭將該圓圈連接到指針。請(qǐng)進(jìn)行拖動(dòng),直至貼靠到屏幕頂部。這樣,您就在 ImageView 的頂部與ConstraintLayout 的頂部之間添加了約束條件。
    在 ImageView 的底部和 ConstraintLayout 的底部之間添加約束條件。有可能會(huì)因?yàn)榫嚯x邊緣太近而無(wú)法像對(duì)頂部那樣進(jìn)行拖動(dòng)。在這種情況下,您可以點(diǎn)擊 Attributes 窗口中 Constraint Widget 底部的 +,添加約束條件。請(qǐng)務(wù)必將外邊距設(shè)為0。現(xiàn)在,圖片已經(jīng)居中,但尚未占據(jù)整個(gè)屏幕。在接下來(lái)的步驟中,您將解決此問(wèn)題。
添加約束條件
  1. 在 Constraints 部分的 Constraint Widget 下,將 layout_width 設(shè)為 0dp (match constraint)。0dp 是一種簡(jiǎn)寫(xiě)形式,用于指示 Android Studio 對(duì) ImageView 的寬度使用匹配約束條件。“匹配約束條件”意味著,由于您剛剛添加的約束條件,這會(huì)讓它與 ConstraintLayout 一樣寬,所有外邊距都會(huì)被減去。將 layout_height 設(shè)為 0dp (match constraint)。由于您添加的約束條件,這會(huì)讓 ImageView 與 ConstraintLayout 一樣高,所有外邊距都會(huì)被減去。
    ImageView 與應(yīng)用屏幕一樣高、一樣寬,但圖片位于 ImageView 的中心,并且圖片的上方和下方還有很多空白區(qū)域。這看起來(lái)不太好看,因此請(qǐng)調(diào)整 ImageView 的 scaleType,告知系統(tǒng)如何調(diào)整圖片的大小和對(duì)齊方式。
  2. 找到 scaleType 屬性。您可能需要向下滾動(dòng)或搜索該屬性。嘗試為 scaleType 設(shè)置不同的值,看看不同值的效果。完成后,請(qǐng)將 scaleType 設(shè)為 centerCrop。這樣一來(lái),圖片將填滿整個(gè)屏幕,而不會(huì)變形。
將 ImageView 移到文本后面

在 Component Tree 中,點(diǎn)擊 ImageView,將它拖動(dòng)到 TextViews 的上面,ConstraintLayout 的正下方。系統(tǒng)會(huì)顯示一個(gè)帶三角形的藍(lán)色線條,指示 ImageView 的目標(biāo)位置。請(qǐng)將 ImageView 拖至 ConstraintLayout 的正下方。

1.4 向應(yīng)用中添加按鈕

了解類(lèi)、對(duì)象和邏輯條件等更多 Kotlin 編程概念,并運(yùn)用所學(xué)知識(shí)為用戶構(gòu)建一個(gè)互動(dòng)式應(yīng)用。

1.4.1 Kotlin 中的類(lèi)和對(duì)象實(shí)例

游戲通常具有隨機(jī)性。您可以贏得隨機(jī)獎(jiǎng)勵(lì),或在棋盤(pán)游戲中移動(dòng)隨機(jī)步數(shù)。在日常生活中,您可以使用隨機(jī)數(shù)字和字母來(lái)生成更安全的密碼!

您可以編寫(xiě)一個(gè)程序來(lái)模擬擲骰子,而無(wú)需真的擲骰子。每次擲骰子時(shí),結(jié)果可以是可能值范圍內(nèi)的任何數(shù)字。幸運(yùn)的是,您無(wú)需為此類(lèi)程序自行構(gòu)建隨機(jī)數(shù)字生成器。大多數(shù)編程語(yǔ)言(包括 Kotlin)都內(nèi)置有用于生成隨機(jī)數(shù)字的方法。在此任務(wù)中,您將使用 Kotlin 代碼來(lái)生成隨機(jī)數(shù)字。

使用隨機(jī)函數(shù)
  1. 在 main() 函數(shù)中,將一個(gè)變量定義為名為 diceRange 的 val。將其分配給 1 到 6 的 IntRange,用于表示 6 面骰子可以擲出的整數(shù)值范圍。
val diceRange = 1..6
  1. 在 main() 中,將一個(gè)變量定義為名為 randomNumber 的 val。
    為 randomNumber 設(shè)置對(duì) diceRange 范圍調(diào)用 random() 的結(jié)果值,如下所示。
val randomNumber = diceRange.random()
  1. 為了顯示隨機(jī)生成的數(shù)字,請(qǐng)使用字符串格式表示法(也稱為“字符串模板”)${randomNumber} 進(jìn)行輸出,如下所示。
println("Random number: ${randomNumber}")
定義 Dice 類(lèi)

在 main() 函數(shù)下,添加一個(gè)空行,然后添加代碼以創(chuàng)建 Dice 類(lèi)。如下所示,先輸入關(guān)鍵字 class,后跟類(lèi)名稱,再跟左大括號(hào)和右大括號(hào)。在大括號(hào)內(nèi)留出空間,以便放入類(lèi)的代碼。在 Dice 類(lèi)中,添加一個(gè)名為 sides 的 var,用于表示骰子將具有的面數(shù)。將 sides 設(shè)置為 6。

class Dice {
    var sides = 6
}
創(chuàng)建 Dice 類(lèi)的實(shí)例
類(lèi)與實(shí)例
  1. 為了創(chuàng)建 Dice 的對(duì)象實(shí)例,請(qǐng)?jiān)?main() 函數(shù)中創(chuàng)建一個(gè)名為 myFirstDice 的 val,并將其初始化為 Dice 類(lèi)的實(shí)例。請(qǐng)注意類(lèi)名稱后面的括號(hào),其表示您在通過(guò)該類(lèi)創(chuàng)建一個(gè)新的對(duì)象實(shí)例。
fun main() {
    val myFirstDice = Dice()
}
  1. 在 myFirstDice 聲明的下方,添加 println() 語(yǔ)句以輸出 myFirstDice. 的 sides 數(shù)量。
println(myFirstDice.sides)
擲骰子
  1. 在 Dice 類(lèi)的 sides 變量下方,插入一個(gè)空行,然后創(chuàng)建一個(gè)用于擲骰子的新函數(shù)。首先輸入 Kotlin 關(guān)鍵字 fun,再輸入方法的名稱,然后是括號(hào) (),然后再是左大括號(hào)和右大括號(hào) {}。可以在大括號(hào)內(nèi)留一個(gè)空行,以便輸入更多代碼,如下所示。您的類(lèi)應(yīng)如下所示。
class Dice {
    var sides = 6

    fun roll() {

    }
}
  1. 在 roll() 方法中,創(chuàng)建一個(gè) val randomNumber。在 1..6 范圍內(nèi)為其分配一個(gè)隨機(jī)數(shù)字。使用點(diǎn)分表示法對(duì)該范圍調(diào)用 random()。生成隨機(jī)數(shù)字后,將其輸出到控制臺(tái)。完成后的 roll() 方法應(yīng)如以下代碼所示。
fun roll() {
     val randomNumber = (1..6).random()
     println(randomNumber)
}
  1. 為了真實(shí)地滾動(dòng) myFirstDice,請(qǐng)?jiān)?main() 中對(duì) myFirstDice 調(diào)用 roll() 方法。您使用“點(diǎn)分表示法”調(diào)用方法。因此,為了對(duì) myFirstDice 調(diào)用 roll() 方法,請(qǐng)輸入 myFirstDice.roll(),這讀作“myFirstDice dot roll()”。
myFirstDice.roll()

1.4.2 創(chuàng)建交互式 Dice Roller 應(yīng)用

為應(yīng)用創(chuàng)建布局
  1. 將 Button 從 Palette 拖動(dòng)到 Design 視圖中,并將其置于“Hello World”TextView 下方。在 Design 視圖中,在 Button 的頂部邊緣,按住帶藍(lán)色邊框的白色圓圈。拖動(dòng)指針,箭頭將跟隨指針移動(dòng)。當(dāng)指針到達(dá)“Hello World”TextView 的下邊緣時(shí)釋放。這樣就建立了布局約束條件,Button 會(huì)滑動(dòng)到 TextView 正下方。


    確定 Button 的位置
  2. 請(qǐng)查看布局編輯器右側(cè)的 Attributes。在 Constraint Widget 中,您會(huì)看到針對(duì) TextView 的底部設(shè)置的一個(gè)新的布局約束條件,即, Top → BottomOf textView (0dp)。(0dp) 表示邊距為 0。您還會(huì)遇到缺少水平約束條件的錯(cuò)誤。


    缺少水平約束條件
  3. 添加一個(gè)從 Button 的左側(cè)到父級(jí) ConstraintLayout 的左側(cè)的水平約束條件。然后對(duì)右側(cè)執(zhí)行同樣的操作,將 Button 的右邊緣與 ConstraintLayout 的右邊緣連接起來(lái)。結(jié)果應(yīng)如下所示:


    水平約束條件
  4. 在 Design Editor 中,選擇 TextView,使其屬性出現(xiàn)在 Attributes 窗口中。將 TextView 的 textSize 更改為 36sp,使其足夠大,易于用戶讀取。您可能需要滾動(dòng)才能找到 textSize。清除 TextView 的 text 屬性。在用戶擲骰子之前,您不需要在 TextView 中顯示任何內(nèi)容。

  5. 在 Component Tree 中選擇 TextView。在 Common Attributes 下,找到 text 屬性,在其下方會(huì)顯示另一個(gè)帶有工具圖標(biāo)的 text 屬性。text 屬性是應(yīng)用運(yùn)行時(shí)向用戶顯示的內(nèi)容。帶有工具圖標(biāo)的 text 屬性是專為開(kāi)發(fā)者提供的“tools text”屬性。在 TextView 中將 tools text 設(shè)置為“1”(以假設(shè)您擲骰子的結(jié)果為 1)?!?”只會(huì)在 Android Studio 的 Design Editor 中顯示,在實(shí)際設(shè)備或模擬器上運(yùn)行應(yīng)用時(shí)不會(huì)顯示。


    工具圖標(biāo)的 text 屬性

Activity 簡(jiǎn)介
Activity 提供窗口供應(yīng)用在其中繪制界面。通常,Activity 會(huì)占用正在運(yùn)行的應(yīng)用的整個(gè)屏幕。每個(gè)應(yīng)用都有一個(gè)或多個(gè) Activity。頂級(jí) Activity 或第一個(gè) Activity 通常稱為 MainActivity。例如,在“Photo Gallery”應(yīng)用中,您可以使用一個(gè) Activity 來(lái)顯示照片網(wǎng)格,一個(gè) Activity 來(lái)查看單張照片,以及另一個(gè) Activity 來(lái)修改單張照片。

Activity 簡(jiǎn)介

點(diǎn)擊 Button 時(shí)顯示消息
  1. 在調(diào)用 setContentView() 后,將以下代碼添加到 onCreate() 方法中。findViewById() 方法在布局中找到 Button。R.id.button 是 Button 的資源 ID,該 ID 是 Button 的唯一標(biāo)識(shí)符。代碼將 Button 對(duì)象的引用保存到名為 rollButton 的變量中,而不是保存 Button 對(duì)象本身。
val rollButton: Button = findViewById(R.id.button)

onCreate() 方法現(xiàn)在應(yīng)如下所示:

override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   setContentView(R.layout.activity_main)

   val rollButton: Button = findViewById(R.id.button)
}
  1. 使用 rollButton 對(duì)象,并調(diào)用 setOnClickListener() 方法為其設(shè)置點(diǎn)擊監(jiān)聽(tīng)器。實(shí)際上,在方法名稱后面您將使用大括號(hào),而不在方法名稱后面使用圓括號(hào)。這是用于聲明 Lambda 的特殊語(yǔ)法,在未來(lái)的 Codelab 中可了解詳情。
    通過(guò)調(diào)用 Toast.makeText() 創(chuàng)建包含文字 "Dice Rolled!" 的 Toast。
    然后,通過(guò)調(diào)用 show() 方法告知 Toast 自行顯示。
class MainActivity : AppCompatActivity() {

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_main)

       val rollButton: Button = findViewById(R.id.button)
       rollButton.setOnClickListener {
           Toast.makeText(this, "Dice Rolled!", Toast.LENGTH_SHORT).show()
       }
   }
}
添加擲骰子邏輯
  1. 在 MainActivity 類(lèi)中最后一個(gè)大括號(hào)后,使用 roll() 方法創(chuàng)建 Dice 類(lèi)。將指針懸停在 numSides 上,系統(tǒng)會(huì)顯示一個(gè)彈出式窗口,顯示 Property ‘numSides' could be private。然后點(diǎn)擊 Make ‘numSides' ‘private'。


    系統(tǒng)會(huì)顯示一個(gè)彈出式窗口
  2. 通過(guò)調(diào)用 rollDice() 替換用于將文字設(shè)置為“6”的點(diǎn)擊監(jiān)聽(tīng)器中的代碼。選擇 Create function ‘rollDice'。Android Studio 會(huì)為 MainActivity 內(nèi)的函數(shù)創(chuàng)建空定義。
private fun rollDice() {
    TODO("Not yet implemented")
}
  1. 在 rollDice() 中,刪除 TODO() 調(diào)用。添加代碼以創(chuàng)建包含 6 個(gè)面的骰子。通過(guò)調(diào)用 roll() 方法擲骰子,并將結(jié)果保存在名為 diceRoll 的變量中。通過(guò)調(diào)用 findViewById() 查找 TextView。將 diceRoll 轉(zhuǎn)換為字符串,并使用該字符串更新 resultTextView 的文本。
private fun rollDice() {
    val dice = Dice(6)
    val diceRoll = dice.roll()
    val resultTextView: TextView = findViewById(R.id.textView)
    resultTextView.text = diceRoll.toString()
}

運(yùn)行您的應(yīng)用。除 6 外,骰子結(jié)果應(yīng)更改為其他值!由于它是一個(gè) 1 到 6 的隨機(jī)數(shù),值 6 有時(shí)也會(huì)出現(xiàn)。


骰子結(jié)果

1.4.3 在 Kotlin 中添加條件行為

在代碼內(nèi)做出決策

在您的 Lucky Dice Roller 程序中,應(yīng)用應(yīng)處理不同的情況,例如:

  • if 用戶擲出幸運(yùn)數(shù)字,就顯示祝賀消息!
  • else if 用戶未擲出幸運(yùn)數(shù)字,就顯示重試消息。
查看是否已擲出幸運(yùn)數(shù)字

先創(chuàng)建幸運(yùn)數(shù)字,然后將擲出的數(shù)字與該數(shù)字進(jìn)行比較。

  1. 在 main() 中,刪除 println() 語(yǔ)句。在 main() 中,添加一個(gè)名為 luckyNumber 的 val,并將其設(shè)置為 4。您的代碼應(yīng)如下所示。
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4
}
  1. 在下面添加一個(gè) if 語(yǔ)句,在括號(hào) () 中放置條件,用于檢查 rollResult 是否等于 (==) luckyNumber。在大括號(hào) {} 內(nèi)留一些空間,以便添加更多代碼。在大括號(hào) {} 內(nèi),添加一個(gè) println 語(yǔ)句以輸出 "You win!"
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    if (rollResult == luckyNumber) {
        println("You win!")
    }
}
在尚未擲出幸運(yùn)數(shù)字時(shí)做出響應(yīng)

添加 else if 語(yǔ)句以針對(duì)每次擲骰輸出不同的消息。如果需要,請(qǐng)參考您在上一任務(wù)中學(xué)到的格式。

fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    if (rollResult == luckyNumber) {
        println("You win!")
    } else if (rollResult == 1) {
        println("So sorry! You rolled a 1. Try again!")
    } else if (rollResult == 2) {
        println("Sadly, you rolled a 2. Try again!")
    } else if (rollResult == 3) {
        println("Unfortunately, you rolled a 3. Try again!")
    } else if (rollResult == 5) {
        println("Don't cry! You rolled a 5. Try again!")
    } else {
        println("Apologies! You rolled a 6. Try again!")
    }
}
使用 when 語(yǔ)句
  1. 在您的程序內(nèi),在 main() 中,選擇從第一個(gè) if 語(yǔ)句到括住最后一個(gè) else 語(yǔ)句的大括號(hào) } 之間的代碼并將其刪除。在 main() 中的 luckyNumber 聲明下方,創(chuàng)建一個(gè) when 語(yǔ)句。由于 when 需要針對(duì)擲出的結(jié)果進(jìn)行測(cè)試,因此請(qǐng)將 rollResult 放置在括號(hào) () 內(nèi)。
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    when (rollResult) {

    }
}
  1. 在 when 語(yǔ)句的大括號(hào) {} 內(nèi),添加一個(gè)針對(duì) luckyNumber 測(cè)試 rollResult 的語(yǔ)句,如果二者相同,就輸出獲勝消息。使用相同格式為可能的擲骰結(jié)果 1 至 6(4 除外)添加代碼行和消息,如下所示。完成后的 main() 函數(shù)應(yīng)如下所示。
fun main() {
    val myFirstDice = Dice(6)
    val rollResult = myFirstDice.roll()
    val luckyNumber = 4

    when (rollResult) {
        luckyNumber -> println("You won!")
        1 -> println("So sorry! You rolled a 1. Try again!")
        2 -> println("Sadly, you rolled a 2. Try again!")
        3 -> println("Unfortunately, you rolled a 3. Try again!")
        5 -> println("Don't cry! You rolled a 5. Try again!")
        6 -> println("Apologies! you rolled a 6. Try again!")
    }
}

1.4.4 向 Dice Roller 應(yīng)用添加圖片

下載骰子圖片
  1. 打開(kāi)此網(wǎng)址,將包含骰子圖片的 ZIP 文件下載到您的計(jì)算機(jī)。等待下載完成。在計(jì)算機(jī)上找到該文件(可能在 Downloads 文件夾中)。雙擊 ZIP 文件進(jìn)行解壓縮。這將新建一個(gè) dice_images 文件夾,其中包含 6 個(gè)骰子圖片文件,分別顯示從 1 到 6 的骰子值。
    骰子圖片
  2. 在 Android Studio 中,依次點(diǎn)擊菜單中的 View > Tool Windows > Resource Manager,或者點(diǎn)擊 Project 窗口左側(cè)的 Resource Manager 標(biāo)簽頁(yè)。點(diǎn)擊 Resource Manager 中左上角的 +,然后選擇 Import Drawables。系統(tǒng)隨即會(huì)打開(kāi)一個(gè)文件瀏覽器。


    導(dǎo)入圖片
  3. 查找并選中上述 6 個(gè)骰子圖片文件。您可以先選中第一個(gè)骰子圖片,然后在按住 Shift 鍵的同時(shí)選中其他圖片。點(diǎn)擊 Open。點(diǎn)擊 Next,然后點(diǎn)擊 Import,以確認(rèn)您要導(dǎo)入這 6 項(xiàng)資源。如果文件已成功導(dǎo)入,那么應(yīng)用的 Resource Manager (app>res>drawable) 中會(huì)顯示這 6 張圖片。
使用骰子圖片
  1. 在 Design Editor 中,選擇 ImageView。在 Declared Attributes 部分的 Attributes 中,找到設(shè)置為頭像圖片的工具 srcCompat 屬性。點(diǎn)擊頭像的小預(yù)覽圖。系統(tǒng)會(huì)打開(kāi)一個(gè)對(duì)話框,供您選擇要用于此 ImageView 的新資源。選擇 dice_1 可繪制對(duì)象,然后點(diǎn)擊 OK。


    替換圖片
  2. 在 Constraints Widget 下的 Attributes 窗口中,找到 layout_width 和 layout_height 屬性。它們當(dāng)前設(shè)置為 wrap_content,這意味著 ImageView 的高度和寬度將與其中的內(nèi)容(源圖片)保持一致。為 ImageView 設(shè)置 160dp 的固定寬度和 200dp 的固定高度。按 Enter 鍵。在 Constraint Widget 中將按鈕的上邊距設(shè)置為 16dp。


    調(diào)整圖片
點(diǎn)擊按鈕時(shí)改變骰子圖片
  1. 在 rollDice() 中,創(chuàng)建一個(gè)新變量 diceImage(類(lèi)型為 ImageView)。將其設(shè)置為與布局中的 ImageView 相同。使用 findViewById() 方法,并將 ImageView 的資源 ID R.id.imageView 作為輸入?yún)?shù)傳入。

如果您想知道如何確定 ImageView 的確切資源 ID,請(qǐng)查看 Attributes 窗口頂部的 id。


資源 ID
  1. 添加以下代碼行,以測(cè)試點(diǎn)擊按鈕時(shí)是否可以正確更新 ImageView。擲出的骰子并不總是“2”,我們只是使用 dice_2 圖片進(jìn)行測(cè)試。rollDice() 方法現(xiàn)在應(yīng)如下所示:
private fun rollDice() {
    val dice = Dice(6)
    val diceRoll = dice.roll()
    val diceImage: ImageView = findViewById(R.id.imageView)
    diceImage.setImageResource(R.drawable.dice_2)
}
  1. 運(yùn)行應(yīng)用以驗(yàn)證它是否正常運(yùn)行而不出現(xiàn)錯(cuò)誤。啟動(dòng)應(yīng)用時(shí)應(yīng)顯示空白屏幕(只有 Roll 按鈕)。點(diǎn)按按鈕后,會(huì)出現(xiàn)顯示值 2 的骰子圖片。太好了??!


    顯示骰子圖片
根據(jù)擲骰子結(jié)果顯示正確的骰子圖片
  1. 在 rollDice() 方法中,刪除每次將圖片資源 ID 設(shè)置為 dice_2 圖片的代碼行。將其替換為 when 語(yǔ)句,該語(yǔ)句可根據(jù) ImageView 值更新 diceRoll。完成更改后,rollDice() 方法應(yīng)如下所示。
private fun rollDice() {
   val dice = Dice(6)
   val diceRoll = dice.roll()

   val diceImage: ImageView = findViewById(R.id.imageView)

   when (diceRoll) {
       1 -> diceImage.setImageResource(R.drawable.dice_1)
       2 -> diceImage.setImageResource(R.drawable.dice_2)
       3 -> diceImage.setImageResource(R.drawable.dice_3)
       4 -> diceImage.setImageResource(R.drawable.dice_4)
       5 -> diceImage.setImageResource(R.drawable.dice_5)
       6 -> diceImage.setImageResource(R.drawable.dice_6)
   }
}
  1. 運(yùn)行應(yīng)用。點(diǎn)擊 Roll 按鈕會(huì)將骰子圖片更改為除 2 以外的值。成功啦!
優(yōu)化您的代碼

您可能已經(jīng)注意到,在 when 語(yǔ)句中對(duì) diceImage.setImageResource() 調(diào)用了 6 次。每種情況之間唯一改變的是所使用的資源 ID。這意味著您可以創(chuàng)建一個(gè)變量,用于存儲(chǔ)要使用的資源 ID。然后,在代碼中只調(diào)用 diceImage.setImageResource() 一次并傳遞正確的資源 ID 即可。

  1. 將上述代碼替換為以下代碼。
val drawableResource = when (diceRoll) {
   1 -> R.drawable.dice_1
   2 -> R.drawable.dice_2
   3 -> R.drawable.dice_3
   4 -> R.drawable.dice_4
   5 -> R.drawable.dice_5
   6 -> R.drawable.dice_6
}

diceImage.setImageResource(drawableResource)

這里運(yùn)用的新概念是,when 表達(dá)式實(shí)際上可以返回一個(gè)值。使用此新代碼段后,when 表達(dá)式會(huì)返回正確的資源 ID,該 ID 將存儲(chǔ)在 drawableResource 變量中。然后,您可以使用該變量更新顯示的圖片資源。

  1. 請(qǐng)注意,when 現(xiàn)在帶紅色的下劃線。如果將指針懸停在它的上面,您會(huì)看到一條錯(cuò)誤消息:‘when' expression must be exhaustive, add necessary ‘else' branch。出現(xiàn)該錯(cuò)誤的原因是 when 表達(dá)式的值被賦給 drawableResource,因此 when 必須涵蓋所有情況,它必須處理所有可能的情況,這樣,即使您更改為 12 面的骰子,也始終會(huì)返回值。Android Studio 建議添加一個(gè) else 分支。您可以通過(guò)將 6 的情況更改為 else 來(lái)解決此問(wèn)題。從 1 到 5 的情況不變,但包括 6 在內(nèi)的所有其他情況都通過(guò) else 處理。
val drawableResource = when (diceRoll) {
   1 -> R.drawable.dice_1
   2 -> R.drawable.dice_2
   3 -> R.drawable.dice_3
   4 -> R.drawable.dice_4
   5 -> R.drawable.dice_5
   else -> R.drawable.dice_6
}

diceImage.setImageResource(drawableResource)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容