カテゴリー
Kotlin言語

ゼロから始めるAndroidアプリ(Kotlin編)Unit1 – 4 第4回 後半 最終回:当たり画像を表示するアプリ

Android Developers > スタートガイド > Kotlin と Android をゼロから学ぶ > Unit1 – Kotlin を用いた Android の基本Unit1-4 第4回 後半 の内容をまとめたものです(翻訳ではありません)。Unit 1 の最終回です


Unit1 – 4 の 第4回 後半(最終回)

第4回 後半(最終回)の内容は以下の通りです

  • 前回作成のAndroidアプリをさらに改良します
  • サイコロの目の画像がランダムに表示されるようにします
  • TalkBack(Androidの読み上げ機能)で使うテキストを追加します
  • アプリ起動時からサイコロの画像が表示されるようにします

ランダムなサイコロ画像が表示されるようにKotlinコードを修正する

前回の続きですね

うん、Project から MainActivity.kt を開いてね( app > java > com.example.diceroller > MainActivity.kt

ボタンをタップすると、いつでも「2の目」の画像が表示されちゃうアプリですね

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 {
           rollDice()
       }
   }

    private fun rollDice() {
        val dice = Dice(6)
        val diceRoll = dice.roll()
        val diceImage: ImageView = findViewById(R.id.imageView)
        diceImage.setImageResource(R.drawable.dice_2)
    }

}

class Dice(val numSides: Int) {

    fun roll(): Int {
        return (1..numSides).random()
    }

}

これを出た目に合わせた画像を表示するように書き換えますね

書き換えるのは上のKotlinコードの赤い部分?

そう。まず diceRoll の値(出た目)を判定して、出た目に合わせた画像を setImageResource メソッドで表示すればいいの

値の判定は if とか使えばいいのかな?

うん、if でも大丈夫。でも今回は when を使うとすっきりするの

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 {
           rollDice()
       }
   }

   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)
       }
   }

}

class Dice(val numSides: Int) {

    fun roll(): Int {
        return (1..numSides).random()
    }

}

うまく改良できました!

when をもっとすっきり書いてみる

when のところ、もっとすっきり書くこともできるの

見てみたいかも

private fun rollDice() {
    val dice = Dice(6)
    val diceRoll = dice.roll()
    val diceImage: ImageView = findViewById(R.id.imageView)

   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)

}
  1. 出た目の値に応じた画像のリソースIDを取得、新たに宣言した drawableResource 変数に代入
  2. setImageResource メソッドを使って drawableResource 変数が示す画像を表示する

すごくすっきり!

うん、でもこれにはバグがあるの

えっ、そうなの?

サイコロが6面なら大丈夫なんだけど、たとえば12面とかに設定するとエラーがでちゃう

val dice = Dice(6) のところを val dice = Dice(12) にしたりできないんですね

private fun rollDice() {
    val dice = Dice(12)
    val diceRoll = dice.roll()
    val diceImage: ImageView = findViewById(R.id.imageView)

   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)

}

6 だったところが else になってる…

こうすると12面サイコロにしてもエラーは出なくなるの

出た目が 6 以上のときは、いつでも「6の目」の画像を表示しちゃうんですね

うん、とりあえずってことで…

出た目の読み上げ(TalkBack)に対応させる

  • Android の画面読み上げ機能を使って、出た目が読み上げられるようにします
  • ImageView content description 項目の内容を、出た目に書き換えます
  • diceImage インスタンス の contentDescription プロパティを書き換えます
  • diceRoll 変数は Int 型なので、文字列型に変換して代入します

rollDice() メソッドの最後にこんなコードを書き加えればいいそうです

diceImage.contentDescription = diceRoll.toString()

アプリを起動したときにサイコロ画像が表示されるようにする

アプリを起動したときにボタンしか出ないのがちょっと気になるかも…

うん、最後にそれ直しますね

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 {
           rollDice()
       }

       rollDice()

   }

   private fun rollDice() {
       val dice = Dice(6)
       val diceRoll = dice.roll()
       val diceImage: ImageView = findViewById(R.id.imageView)

       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)

       diceImage.contentDescription = diceRoll.toString()

   }

}

class Dice(val numSides: Int) {

    fun roll(): Int {
        return (1..numSides).random()
    }

}

これでどうかな?

最初のほうで rollDice() メソッドを1回実行しちゃえばいいんですね

うん、そうなの。あとはコードが何をしているのか分かるようにコメントを入れておくといいかも

まとめ

  • ImageView に表示される画像をKotlinコードから変更するときは setImageResource() メソッドを使います
  • if , else , when などを使うと、アプリの状況に応じた動作をさせられます
  • Unit1-4 第5回の締めの動画(What can you build with these basics?)は視なくても大丈夫です

お疲れさまでした。Android Developers(by Google)で公開されているスタートガイド「Kotlin と Android をゼロから学ぶ」Unit 1 のまとめ、これにて完了ですね