Tina Tang's Blog

在哪裡跌倒了,就在哪裡躺下來

0%

Android筆記(5)-新增圖片至Dice Roller應用程式

將新增骰子的圖片至現有的Dice RollerAndroid應用程式。

學習目標

  • 如何在應用程式執行時更新ImageView
  • 如何根據不同條件自訂應用程式行為(使用when陳述式)。

更新應用程式的版面配置

新增顯示擲骰子結果圖片的ImageView,以取代版面配置中的TextView

  1. 在 Android Studio 中,開啟並執行先前程式碼研究室的 Dice Roller 應用程式。
  1. 刪除TextView,新增ImageView並放置在Button上方。

  2. 在「Pick a Resource」對話方塊中,選取「Sample data」下的「avatars」。這是您在下一項工作中新增骰子圖片前,暫時使用的圖片。

  1. 在「Component Tree」中,您會看到兩項錯誤。Button不受垂直限制,ImageView則不受垂直或水平限制。

調整 ImageView 和 Button 的位置

無論 Button 在什麼位置,ImageView 都必須垂直置於畫面中間。

  1. ImageView中加入水平限制條件。將ImageView的左側連結至父項ConstraintLayout的左側邊緣,右側連結至父項的右側邊緣,使ImageView水平置中。
  1. ImageView加入垂直限制,然後連結ImageView的頂端與父項的頂端。ImageView會向上滑動至 ConstraintLayout的頂端。
  1. Button中加入垂直限制,然後連結Button的頂端與ImageView底部。Button會向上滑動至 ImageView下方。

  2. 再次選取ImageView並加入垂直限制,然後連結ImageView的底部與父項的底部。這會讓ImageViewConstraintLayout中垂直置中。

完成所有操作後,「Design」(設計) 檢視畫面應該如下所示,ImageView位於中央,Button則緊靠在下方。


新增骰子圖片

下載骰子圖片
  1. 開啟這個網址下載骰子圖片的 ZIP 檔案至電腦上。
  2. 解壓縮dice_images資料夾,可以看到骰子點數 1 到 6 共 6 張圖片。
新增骰子圖片至應用程式
  1. 依序按一下選單中的「View」>「Tool Windows」>「Resource Manager」,或點選「Project」視窗左側的「Resource Manager」分頁標籤。
  2. 按一下「Resource Manager」下方的「+」圖示,然後選取「Import Drawables」,即可開啟檔案瀏覽器。
  1. 找出並選取這 6 個骰子圖片檔案。您可以選取第一個檔案,然後按住 Shift 鍵並選取其他檔案。
  2. 按一下「Open」。依序點選「Next」和「Import」,確認要匯入這 6 項資源。
  1. 如果成功匯入檔案,應用程式的「Resource Manager」(資源管理員) (「app」(應用程式) >「res」(解析度) >「drawable」(可繪項目)) 中會顯示 6 張圖片。

使用骰子圖片

更換範例顯示圖片
  1. 在「設計編輯器」中,選取ImageView
  2. 在「Declared Attributes」部分的「Attributes」中,找到已設為該顯示圖片工具「srcCompat」屬性。
  • 工具「srcCompat」屬性只會在建構應用程式時向開發人員顯示,所以在模擬器或裝置上執行應用程式時不會顯示。
  1. 按一下顯示圖片的縮圖預覽。系統會開啟對話方塊,請選擇ImageView使用的新資源。
  2. 選取dice_1可繪項目,然後按一下「OK」。

接著,調整ImageView的寬度和高度,避免遮掩Button

  1. 在「Constraints Widget」下方的「Attributes」視窗中,找出「layout_width」和「layout_height」屬性。
  • 這兩項屬性目前設為「wrap_content」,即 ImageView 的高度和寬度與其中的內容 (來源圖片) 相同。
  1. ImageView的寬度改設為固定的160 dp,並將高度設為固定的200 dp
  1. 最後,由於Button太靠近圖片,在「限制小工具」中,設定上邊界 16dp。

按下按鈕時變更骰子圖片

更新 MainActivity 類別才能使用骰子圖片。

  1. 刪除TextView相關的程式碼。
  2. 建立名為類型ImageViewdiceImage的新變數。使用findViewById()方法,傳入ImageViewR.id.imageView的資源識別碼作為輸入引數。
1
val diceImage: ImageView = findViewById(R.id.imageView)
  1. 設定顯示骰子圖片
1
diceImage.setImageResource(R.drawable.dice_2)
  1. 使用if/elsewhen陳述式,根據擲骰子的結果顯示正確的骰子圖片。

if/else:

1
2
3
4
5
6
if (diceRoll == 1) {
diceImage.setImageResource(R.drawable.dice_1)
} else if (diceRoll == 2) {
diceImage.setImageResource(R.drawable.dice_2)
}
...

when:

1
2
3
4
when (diceRoll) {
1 -> diceImage.setImageResource(R.drawable.dice_1)
2 -> diceImage.setImageResource(R.drawable.dice_2)
...

完成後如下方所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private fun rollDice() {
// Create new Dice object with 6 sides and roll it
val dice = Dice(6)
val diceRoll = dice.roll()

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

// Update the dice image with the dice roll
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)
}
}

最佳化程式碼

呼叫diceImage.setImageResource()在陳述式中出現 6 次。
我們可以建立變數,儲存使用的資源識別碼。

更換程式碼,以下列取代。

1
2
3
4
5
6
7
8
9
10
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)

這時when會顯示錯誤訊息:「‘when’ expression must be exhaustive, add necessary ‘else’ branch」。
原因在於 when 運算式的值已指派給 drawableResource,因此 when 必須詳盡無遺,也就是說,這個運算式必須處理所有可能的情況,以確保即使您變更為有 12 面的骰子,仍一律會傳回值。
若要修正錯誤,請將案例的 6 變更為 else。

1
2
3
4
5
6
7
8
9
10
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)

在 ImageView 上設定適當的內容說明

更新 ImageView的內容說明,有助螢幕閱讀器說明內容。

1
diceImage.contentDescription = diceRoll.toString()
  • 螢幕閱讀器可以朗讀內容說明,因此如果螢幕上顯示骰子擲出「6」的圖片,內容說明會大聲朗讀「6」。

採用完善的程式設計做法

使用者首次開啟應用程式時,應用程式顯示的空白畫面 (「Roll」按鈕除外) 看來很突兀。這可能會導致使用者不清楚應用程式的功能,因此您需要變更使用者介面,在首次啟動應用程式時顯示隨機擲骰子的畫面,並建立 Activity。這樣一來,使用者就較有可能理解,只要輕觸「Roll」按鈕就能擲骰子。

1
2
3
4
5
6
7
8
9
10
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val rollButton: Button = findViewById(R.id.button)
rollButton.setOnClickListener { rollDice() }

// Do a dice roll when the app starts
rollDice()
}

最終顯示的畫面: