初めてのAndroidアプリ開発(Kotlin編)- プログラミングの基本

こちらの資料は、東北Tech道場の参加者向けに作成したハンズオン資料
[初めてのAndroidアプリ開発ープログラミングの基本](http://qiita.com/ktaka/items/8cc997e464442aae4e18)
を参考にした、Kotlin編の資料となります。

---


JavaでAndroidの開発をしているが、最近Kotlinが気になっていて使ってみたいけれども、
実際にどうやって開発をするんだろう？
という方を想定してこの資料を作成しました。

この２つの資料を見比べながら、JavaとKotlinでの書き方の違いを理解して頂けると幸いです


---

※ 本資料作成時は Android Studio の最新バージョンが2.3.3のため、Kotlinのプラグインのインストールから説明をしていきます。
(Android Studio 3.0からはプラグインがプリインストールされるため、プラグインのインストール作業が不要となると思います)

---

## プログラミングの基本要素

- 変数
- 分岐
- ループ

---

## 前準備(Kotlin)
---

### 新規プロジェクト作成

AndroidStudioでプロジェクトを作成します。
![スクリーンショット 2017-08-30 14.42.22.png](https://qiita-image-store.s3.amazonaws.com/0/75515/86476314-bb8a-c6e8-579b-b7b95397b073.png)

Add an Activity to Mobile の画面では"Empty Activity"を選択します。
![スクリーンショット 2017-08-30 14.42.47.png](https://qiita-image-store.s3.amazonaws.com/0/75515/89cac99b-efa7-87a4-6497-2baa24d87522.png)

プロジェクトが生成されましたがこの時点ではまだJavaのプロジェクトです。
![スクリーンショット 2017-08-30 14.43.49.png](https://qiita-image-store.s3.amazonaws.com/0/75515/476ef14f-faa5-9223-e120-635178167dca.png)

---

### Android Studio に Kotlinプラグインをインストールする

---


Android Studio 2.3.3でKotlinを使うには、Kotlinのプラグインが必要なため、
まずはKotlinのプラグインをインストールします。

AndroidStudioメニュー > Preferencesを選択
![スクリーンショット 2017-08-30 14.44.27.png](https://qiita-image-store.s3.amazonaws.com/0/75515/28273574-9b27-0a52-9af6-289196a51eda.png)

plugins > Install JetBlains plugin を選択
![スクリーンショット 2017-08-30 14.46.06.png](https://qiita-image-store.s3.amazonaws.com/0/75515/b73f0835-f6ff-05e3-59f5-955cb941afe2.png)

一覧からKotlinを選択 > Install をクリック
![スクリーンショット 2017-08-30 14.46.46.png](https://qiita-image-store.s3.amazonaws.com/0/75515/a6511feb-7a3c-ec10-952b-fd2df03595e6.png)

インストールが完了したら、Android Studio を一度再起動します。
再起動したら、プラグインのインストールが完了です。

---


### プロジェクトをKotlin用にセッティング

プラグインをインストールしただけではまだKotlinは使えません。
プロジェクトをKotlin用にセッティングすることでKotlinが使えるようになるのです。

---


#### build.gradle にKotlin用の記述を追加する

Kotlinでビルドできるように build.gradleを変更します。

Android Studioメニューから
Tools > Kotlin > Configure Kotlin Project を選択

<img width="1368" alt="スクリーンショット 2017-08-31 13.31.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/75515/ec865cd4-b28d-9405-6642-921324cd2108.png">

次に出て来るウィンドウで
Android with Gradle を選択

<img width="248" alt="スクリーンショット 2017-08-31 13.31.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/75515/f5ef3c25-6685-7c11-2636-2b473367dd93.png">

次のウィンドウでKotlinのバージョンを設定。
特に指定がなければ最新バージョンを選択する。
<img width="497" alt="スクリーンショット 2017-08-31 13.32.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/75515/c6b0d7a2-1185-c5b7-8662-92f0dc230973.png">

OKを選択すると build.gradle にKotlin用の設定が自動で追加され、この画面に切り替わるので、最後に Sync Now をクリックします。

<img width="1548" alt="スクリーンショット 2017-08-31 13.32.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/75515/2a769b8a-02b2-b267-db19-6f95c379c5e7.png">

---


#### app/build.gradle に extentions ライブラリを追加

app/build.gradle に
`apply plugin: 'kotlin-android-extensions'`
を１行追加し、 Sync Now を選択します。

<img width="1548" alt="スクリーンショット 2017-08-31 14.38.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/75515/e4ff02f7-ddc8-9644-5106-cfa89b6ecfdf.png">

この extentions ライブラリは、今までJavaで行っていた`FindViewById()`を使わず、直接Viewのidを指定して、テキストの設定等ができる便利なライブラリです(詳しい使い方は後ほど説明します)。

Sync Now が無事に終われば build.gradle の設定は完了です。

---


### JavaのソースコードをKotlinに変換する

---


#### 変換するJavaファイル(ここでは MainActivity.java)を表示します

<img width="1548" alt="スクリーンショット 2017-08-31 13.42.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/75515/5947ad16-95fa-8aec-81ab-9c418094e5e3.png">

---


#### JavaファイルをKotlinに変換

Android Studio メニューの
Code > Convert Java File to Kotlin File を選択します

<img width="518" alt="スクリーンショット 2017-08-31 13.42.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/75515/c21f900f-fca9-7bc6-140a-bbc86e8cd106.png">

変換が完了すると、このようにJavaがKotlinに変換されます

<img width="1548" alt="スクリーンショット 2017-08-31 13.42.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/75515/003ff109-75ce-275b-7961-20a9c22ca616.png">

---


## 前準備(xml)

### レイアウトの編集

ここでは activity_main.xml を編集します。

まず、 `android:id="@+id/textview"`の部分を追加します。

```activity_main.xml
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/rootLayout"
    tools:context="org.tohokutechdojo.test.sleeping.MainActivity">

    <TextView 
        android:id="@+id/textview"
        android:text="hello world" android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</android.support.constraint.ConstraintLayout>
```

---


## 変数

計算結果や文字列などを入れておくための箱
String, int, float などがあります。
Kotlinで変数を宣言する際は `var`や`val`を使って宣言します。

---


## 変数を使ってみる

//追加 の行を入力しましょう。

```MainActivity.kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        var greeting = "こんにちは" //追加
        textview.text = greeting   //追加
    }
}
```

---


## String型

Java編では
`String greeting = "こんにちは"`
という風にString型を宣言していました。

これをKotlinで書くと、
`val greeting: String = "こんにちは"`
となります。

また、Kotlinは自動的に代入される型を推論してくれるので、
`val greeting = "こんにちは"`
と書くことも出来ます。

---


## TextView型

Androidで画面に文字を表示する際はTextView という型(クラス)を使います。

前準備のところでレイアウト中のTextViewに
`android:id="@+id/textview"`
とIDを割り振っておいたのはここで使うためです。

Javaでは、このViewのIDを使ってテキストをセットする場合、
```TextView textView = (TextView) findViewById(R.id.textview)
textView.setText("こんにちは");
```
となりますが、Kotlinでは
`textview.text = "こんにちは"`
この割り振ったViewのidを直接指定して、テキストの設定等を行うことができます。

---


## 分岐
```
if (条件式）{
    …
} else {    
    …
}
```

---


## 時間で挨拶を変えてみる

- 0時から１２時
 - おはよう
- １２時から１６時
 - こんにちは
- １７時から２４時
 - こんばんは

---


## 現在時刻を取得して分岐させる

//追加 の行を入力しましょう。

```MainActivity.kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        var greeting = "こんにちは"
        val trialTime = Date()                         //追加
        val calendar = GregorianCalendar()             //追加
        calendar.time = trialTime                      //追加

        val hour = calendar.get(Calendar.HOUR_OF_DAY)  //追加
        if (hour in 1..11) {                           //追加
            greeting = "おはよう"                       //追加
        } else if (15 < hour) {                        //追加
            greeting = "こんばんは"                     //追加
        }                                              //追加

        textview.text = greeting
    }
}
```

入力したら実行してみましょう。

---


## これから作るアプリ

羊の数を数える睡眠誘導アプリを作ります

---


### 羊を３匹数えてみる

//追加 の行を入力しましょう

```MainActivity.kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        var greeting = "こんにちは"
        val trialTime = Date()
        val calendar = GregorianCalendar()
        calendar.time = trialTime

        val hour = calendar.get(Calendar.HOUR_OF_DAY)
        if (hour in 1..11) {
            greeting = "おはよう"
        } else if (hour > 15) {
            greeting = "こんばんは"
        }
        greeting += "。。。ひつじが１匹。。。ひつじが2匹。。。ひつじが3匹。。。" //追加

        textview.text = greeting
    }
}
```

入力したら実行してみましょう。

---


## 眠れるまで何十回も書くのか？

---


## ループ(繰り返し処理)

ひつじが1匹
ひつじが2匹
ひつじが3匹
ひつじが4匹
ひつじが5匹
.
.
.

---


### forループ

```
for (i in 1..10) {

}
```
i --- カウンタ
in 1..10 --- 1〜10までの範囲でカウンタを増やす条件式

---


### for ループでやってみる

//追加 行を入力しましょう。

```MainActivity.kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        var greeting = "こんにちは"
        val trialTime = Date()
        val calendar = GregorianCalendar()
        calendar.time = trialTime

        val hour = calendar.get(Calendar.HOUR_OF_DAY)
        if (hour in 1..11) {
            greeting = "おはよう"
        } else if (hour > 15) {
            greeting = "こんばんは"
        }

        val sheepNum = 10                          //追加
        for (i in 1..sheepNum) {                   //追加
            greeting += "。。。ひつじが" + i + "匹"     //追加
        }                                          //追加

        textview.text = greeting
    }
}
```

入力したら実行してみましょう。

---


## もっとインタラクティブに

画面をタップするとカウントするように

---


## 前準備

レイアウトXMLを編集

`android:id="@+id/rootLayout"`の部分を追加します。

```activity_main.xml
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/rootLayout"
    tools:context="org.tohokutechdojo.test.sleeping.MainActivity">

    <TextView android:id="@+id/textview"
        android:text="@string/hello_world" 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</android.support.constraint.ConstraintLayout>
```

---


## タップ処理の実装

//追加 の行を入力、//削除 の行を削除しましょう

```MainActivity.kt
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import java.util.*


class MainActivity : AppCompatActivity() {
    var sheepCount = 0 // 追加

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        var greeting = "こんにちは"
        val trialTime = Date()
        val calendar = GregorianCalendar()
        calendar.time = trialTime

        val hour = calendar.get(Calendar.HOUR_OF_DAY)
        if (hour in 1..11) {
            greeting = "おはよう"
        } else if (hour > 15) {
            greeting = "こんばんは"
        }

//        val sheepNum = 10                          //削除
//        for (i in 1..sheepNum) {                   //削除
//            greeting += "。。。ひつじが" + i + "匹"     //削除
//        }                                          //削除

        greeting += "ねむれませんか？"                  //追加

        textview.text = greeting

        rootLayout.setOnClickListener {             //追加
            sheepCount++                            //追加
            val sheepText = "ひつじが$sheepCount 匹"  //追加
            textview.text = sheepText               //追加
        }                                           //追加
    }
}
```

入力したら実行してみましょう。

---


### 文字の連結

Kotlinでは、String型の文字にInt型の値や変数を連結する際は
`val sheepText = "ひつじが$1匹"`
`val sheepText = "ひつじが$sheepCount 匹"`
という風に`$`を使って連結する事が可能です。

[補足]
あるクラスの値を連結したい場合は
`val sheepText = "ひつじが${sheep.count}匹"`
という感じで`${}`を使うと連結が出来ます。