14
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

初心者がKotlinでAndroidアプリをつくってみた

Last updated at Posted at 2018-11-11

#はじめに
メルカリで買った本↓が届いたのでAndroidアプリをためしに作ってみた
https://www.sbcr.jp/products/4797395808.html

#準備
AndroidStudioをインストールする
https://developer.android.com/studio/install?hl=ja

#電卓アプリをつくろう

アプリ開発の流れは
①プロジェクトの作成
②リソースの作成
③画面レイアウトの作成
④機能の実装
⑤マニフェストファイルの定義
⑥テスト・デバッグ
だそうな

正直初心者の私にはどこから何を手をつけていけばいいやら全くわからないのである

##①プロジェクトの作成

AndroidStudioを起動するとこんな画面が表示される
スクリーンショット 2018-11-11 22.33.59.png

一番上の
スクリーンショット 2018-11-11 22.38.45.png
を押してみる

スクリーンショット 2018-11-11 22.53.22.png アプリ名とか保存するフォルダとか選んで スクリーンショット 2018-11-11 22.55.02.png ここにチェックをいれよう! これでKotlinが使えることになる

次はアプリが動く端末やOSのバージョンを選ぶところ
とりあえずPhone and Tablet のAndroid 8.1 にした
(私のスマホは7だけど…)
スクリーンショット 2018-11-11 22.56.41.png

ここはなんかテンプレを用意してくれるみたい
今回はおためしなのでEmpty Activityで
スクリーンショット 2018-11-11 22.59.01.png

アクティビティの名前とレイアウトの名前を入れろとのこと
ふむふむ
画面の単位のことをアクティビティと呼ぶらしい
こんかいはとりあえずこのままで

スクリーンショット 2018-11-11 23.00.22.png

こんな感じの画面になるのでちょっとまってFinishをおす

スクリーンショット 2018-11-11 23.05.08.png

これでプロジェクトの作成は完了だ
スクリーンショット 2018-11-11 23.11.33.png

##②リソースの作成 ③画面レイアウトの作成

リソースは画面に表示する文字とか色とか画像イメージとかのことを指すみたい
レイアウトファイルによって、リソースをどこに配置するかを決めるらしいよ

ということでまずはこの電卓ツールのレイアウトファイルであるactivity_main.xmlをひらいてみよう
(さっきアクティビティを作った時に名前を決めたファイルだね)

スクリーンショット 2018-11-11 23.19.46.png

場所はapp→res→layoutのとこにあるみたい
デフォルトでも開かれてたけどね

レイアウトファイルをいじる方法は
1.デザインビューをつかう
2.ソースコードを直接編集する
の2つの方法があるみたいだけど、今回はデザインビューを使ってみる

ちなみにデザインビューとテキストの切り替えは↓ここでできる(左下らへんにある)
スクリーンショット 2018-11-11 23.23.46.png

最初は「Hello World」が書かれているのがわかる
スクリーンショット 2018-11-11 23.25.48.png

左側がデザインビューで右側がブループリントと言うらしいよ
主に左側をいじるんだけど、ブループリントもなんかに使うみたい(後述のConstraintLayout)

#####最初に電卓アプリをつくると言ったな あれはウソだ
電卓と言ったら0から9のボタンがあっていろいろ計算ができるけど、
そこまでのものをおためしでつくれる気がしなかったので
単純な計算をするアプリにします…

「Hello World」の削除
せっかくこんにちはしてくれたのにごめんね(計算にはつかわないのだ)
スクリーンショット 2018-11-11 23.34.52.png

左側にあるPaletteにあるいろんなパーツを組み合わせることでデザインビューをそだてていく
まずはTextViewをドラッグ&ドロップして
スクリーンショット 2018-11-11 23.36.32.png
パーツを置きました
スクリーンショット 2018-11-11 23.36.48.png

次に置いたパーツの中身を編集します
右側のAttributesで編集できる
textを「定価」
textAppearanceを「AppCompact.Large」に変更
スクリーンショット 2018-11-11 23.39.37.png
するとこうなる
スクリーンショット 2018-11-11 23.40.08.png

#####ConstraintLayout
いまの状態でComponent Treeという場所をみてみると!マークのエラーが出ている
スクリーンショット 2018-11-11 23.45.19.png
ちょっと何言っているのかわからないけど
「This view is not constrained.」らしい

ConstraintLayoutという機能があります
Constraintを訳すと「制約」という意味で
パーツのひとつひとつにスマホ画面のどこらへんに表示するか制約を設ける必要があるそうな
よくわかんないので今置いた「定価」という文字を例にとってみる

ConstraintLayoutはブループリントで確認できる

これが制約が全くない状態
スクリーンショット 2018-11-11 23.59.47.png

制約をつけるのはAttributesのここ
スクリーンショット 2018-11-12 0.00.00.png

これをこうしてやると
スクリーンショット 2018-11-11 23.54.29.png

ブループリントがこんな感じになってエラーがなくなる
スクリーンショット 2018-11-11 23.54.40.png

この制約はスマホ画面の上から48dp、左から48dpの場所に「定価」という文字を表示しますよというもの
こんな感じで垂直方向や水平方向に制約を持たしてあげないといけないんだって

#####エディットテキストの追加
次は定価を入力するところをつくろう

PaletteのText→Numberを配置する
スクリーンショット 2018-11-12 0.07.29.png

制約をいれる
・水平方向:左側は「定価」文字列との間に38dp、右側は画面端との間に48dp

スクリーンショット 2018-11-12 0.10.21.png スクリーンショット 2018-11-12 0.10.32.png

・垂直方向:「定価」文字と同じ高さにしたいので以下の設定をする

shiftキーを押しながらふたつを選択
スクリーンショット 2018-11-12 0.13.27.png

ここのBaselinesをおす
スクリーンショット 2018-11-12 0.13.55.png
これでふたつのパーツの高さが同じになるようにベースラインが決まった
(うにょーん)
スクリーンショット 2018-11-12 0.14.14.png

あとここの入力値は後ほど使うので
このパーツのIDをわかりやすいものにしておこう
スクリーンショット 2018-11-12 0.17.15.png

#####もういっこ追加
スーパーで3割引とか書かれていてもパッと計算するのって大変だよね(そうでもない?)
このハイテクアプリはどんな割引シールが貼ってあっても即座に値段を教えてくれる優れものです

ということで割引率を入力するパーツも追加しよう

でーん
スクリーンショット 2018-11-12 0.24.22.png

スクリーンショット 2018-11-12 0.25.12.png スクリーンショット 2018-11-12 0.25.30.png

#####計算ボタンの追加

スクリーンショット 2018-11-12 0.27.50.png

「計算する」ボタンも置いてレイアウトは完成!

スクリーンショット 2018-11-12 0.28.07.png ID:calculate text:計算する と設定しました

#####エラーの消し込み
Component Treeにはまだエラーが残っています
スクリーンショット 2018-11-20 10.13.02.png

こいつらを消し込んで行こう

######priceとdiscountのエラー
前段で設定した定価と割引率を入力する箇所であるpriceとdiscountのエラーを消そう
スクリーンショット 2018-11-20 10.30.14.png

「Missing accessibility label」って言ってる
priceやdiscountはテキストエディットというコンポーネントで、テキストエディットはラベル(「定価」とか「割引率」っていう文字そのもの)に紐づいてなきゃいけないんだって
紐づけ方はこう↓
・「定価」ラベルをデザインビューから選択
スクリーンショット 2018-11-20 10.22.23.png
・Attributesの一番下の「View all attributes」をクリック
スクリーンショット 2018-11-20 10.22.44.png
・たくさんでてくるので「labelFor」を見つけて紐づけ対象の「price」テキストエディットを指定する
スクリーンショット 2018-11-20 10.23.18.png

・これで紐づけ完成!
スクリーンショット 2018-11-20 10.23.41.png

同じように「割引率」ラベルと「discount」テキストエディットの紐づけも行おう
スクリーンショット 2018-11-20 10.23.59.png

警告が消えた
スクリーンショット 2018-11-20 10.31.58.png

(最初以下の警告だったんだけどFixを押したら消えた)
スクリーンショット 2018-11-20 10.18.27.png

######「定価」「割引率」ラベルのエラー
「Hardcoded string "定価", should use '@string' resource」って言ってる
ハードコーディングしてるところがあるからなんとかせいって感じ

スクリーンショット 2018-11-20 10.35.12.png

よくわかんないけど誘導通りに↓のFixボタンを押してみる
スクリーンショット 2018-11-20 10.36.54.png

こんなのが出てくるので、Resource nameに「price_label」と入力
スクリーンショット 2018-11-20 10.38.02.png
警告が消えた…!
スクリーンショット 2018-11-20 10.39.16.png

「定価」ラベルのAttributesのtext項目を見てみるとさっき入力したprice_labelというのに置き換わっている
(元は「定価」って直書きしてたね)
スクリーンショット 2018-11-20 10.39.58.png

ここでちょっと以下のファイルを見てみよう
string.xmlというファイルがあるはずだ
スクリーンショット 2018-11-20 10.41.49.png
price_labelというタグがあってその中身が「定価」となっている
スクリーンショット 2018-11-20 10.41.54.png

さっきのFixボタンの処理はこのタグをつくる処理だったらしい
こうすることでラベルに「定価」とハードコーディングするのを回避しているんだね

同様に「割引率」と「計算する」ボタンもFixしてあげよう
スクリーンショット 2018-11-20 10.45.46.png
スクリーンショット 2018-11-20 10.46.12.png
スクリーンショット 2018-11-20 10.46.21.png
これで綺麗になった!
スクリーンショット 2018-11-20 10.47.13.png

##④機能の実装
入力画面はできた(結果を表示する画面はまだだけど)ので次は機能を実装しよう

機能はアクティビティとよばれる単位で実装されるみたい
画面ごとアクティビティを定義したり、1つのアクティビティで済ませたり色々作り方はあるみたいだけど、今回は入力画面と結果画面の2つのアクティビティを用意しよう

実はすでにアクティビティファイルが作られている
スクリーンショット 2018-11-20 10.54.11.png
スクリーンショット 2018-11-20 10.54.17.png

Kotlinのメソッドについてちょっと触れよう(私もあんまりわかってないけど)
####onCreate()
アクティビティが生成された時に呼ばれるメソッドだって
super.onCreate()でスーパークラスを呼んでるのがみえるけど、これは必須なんだって
onCreate()に関わらずアクティビティのライフサイクルに関するメソッドはスーパークラスを呼ぶことを強制させられるらしい
ふーん

####setContentView()
このアクティビティで使用するレイアウトファイルを指定するメソッドだそうだ
activity_main.xmlはさっきまでさんざんごにょごにょしてたファイルのことだね

###どんな機能が必要なのか?
レイアウトができたので、この画面にはどんな機能が必要なのか考えてみよう
・「計算する」ボタンを押した時に入力値の妥当性を検証する
・上記が妥当であった場合、計算結果画面に遷移する
主にこの二つかな?
計算処理を入力画面でするのか、計算結果画面でするのか考えるところだけど、入力画面でしてしまったら計算結果画面の仕事が表示だけになるから、計算機能は計算結果画面におまかせしよう

###クリックイベントのハンドリング
まあまずはコードを書いてみよう

MainActivity.kt

class MainActivity : AppCompatActivity() {

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

        val button = findViewById<Button>(R.id.calculate)

        button.setOnClickListener {
            // ここに任意の処理を実装する
        }
    }
}

val以降を追加した
####findViewById()
IDを指定することでビューを取得できるというもの
今回は「計算する」ボタンを取得してbutton変数に入れたい
IDは「calculate」だったね
スクリーンショット 2018-11-20 11.14.24.png

####setOnClickListener()
アプリはどうやってボタンが押されたことを察知するのかというと、このメソッドのおかげで察知できるのである
このようにリスナーを記述することによって、ボタンが押された時の処理を書くことができる

それじゃあ処理を書いてみよう

MainActivity.kt
package com.example.natsuki.dentaku

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText

class MainActivity : AppCompatActivity() {

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

        val button = findViewById<Button>(R.id.calculate)

        button.setOnClickListener {
            // ここに任意の処理を実装する
            //妥当かどうか
            var isValid = true

            val priceEditText = findViewById<EditText>(R.id.price)
            val priceText = priceEditText.text.toString()

            if (priceText.isEmpty()) {
                //定価が未入力
                priceEditText.error = "定価を入力してください"
                isValid = false
            }

            val discountEditText = findViewById<EditText>(R.id.discount)
            val discountText = discountEditText.text.toString()

            if (discountText.isEmpty()) {
                //割引率が未入力
                discountEditText.error = "割引率を入力してください"
                isValid = false
            }

            if(isValid) {
                //文字列を整数型に変換
                val price = Integer.parseInt(priceText)
                val discount = Integer.parseInt(discountText)

                //ここで画面遷移を行う
            }
        }
    }
}

未入力だったらエラーとするようにした

スクリーンショット 2018-11-20 11.28.45.png ここのスクリーンショット 2018-11-20 11.29.39.pngをおすとエミュレータが起動して実装した処理を確認できる スクリーンショット 2018-11-20 11.29.03.png エラーになってる!

####ちょこっとリファクタリング
現在、"定価を入力してください"や"割引率を入力してください"という文言をハードコーディングしている
せっかく「strings.xml」というのがあるのだからそっちに移そう

スクリーンショット 2018-11-25 14.55.49.png なんと左側に出てくるアイコンに従っていけばうつすことができるぞ! スクリーンショット 2018-11-25 14.57.14.png スクリーンショット 2018-11-25 14.57.36.png スクリーンショット 2018-11-25 14.57.58.png

###画面の追加
次は計算結果を表示する画面を追加してみよう
MainActivity.ktがある階層で右クリック→New→Activity→EmptyActivityで空のアクティビティをもう一個追加できる

スクリーンショット 2018-11-25 15.02.21.png 名前はResultActivityとしよう スクリーンショット 2018-11-25 15.03.07.png できた スクリーンショット 2018-11-25 15.03.18.png

###画面遷移機能の実装
実装途中だったMainActivity.ktに追記した

MainActivity.kt
package com.example.natsuki.dentaku

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.content.Intent

class MainActivity : AppCompatActivity() {

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

        val button = findViewById<Button>(R.id.calculate)

        button.setOnClickListener {
            // ここに任意の処理を実装する
            //妥当かどうか
            var isValid = true

            val priceEditText = findViewById<EditText>(R.id.price)
            val priceText = priceEditText.text.toString()

            if (priceText.isEmpty()) {
                //定価が未入力
                priceEditText.error = getString(R.string.price_error)
                isValid = false
            }

            val discountEditText = findViewById<EditText>(R.id.discount)
            val discountText = discountEditText.text.toString()

            if (discountText.isEmpty()) {
                //割引率が未入力
                discountEditText.error = getString(R.string.discount_error)
                isValid = false
            }

            if(isValid) {
                //文字列を整数型に変換
                val price = Integer.parseInt(priceText)
                val discount = Integer.parseInt(discountText)

                //ここで画面遷移を行う
                val intent = Intent(this, ResultActivity::class.java)
                intent.putExtra("price",price)
                intent.putExtra("discount",discount)
                startActivity(intent)
            }
        }
    }
}

android.content.Intentをimportして//ここで画面遷移を行う以降を追記しました
Kotlinで別のアクティビティを起動するにはIntentというのを使うんだって
よくわかんないけど使い方は↑の通り

####startActivity()
Intentに詰め込んだ情報で別のアクティビティを起動させるメソッドなんだって

###計算結果画面のレイアウト作成
遷移処理まで書いたので、遷移先の画面のレイアウトファイルを作成しよう
activity_result.xmlができているはずだ
スクリーンショット 2018-11-25 15.32.33.png

####ガイドラインをつかってみる
ツールバーにある「Add Horizontal Guideline」を押すとなんか水平な線が出てくる
このガイドラインに対しても制約をかけられるんだって
スクリーンショット 2018-11-25 15.35.06.png
左側の▲を%にかえて50%のところにガイドラインを移動させる
スクリーンショット 2018-11-25 15.36.23.png

そんで二つのTextViewに制約を与える
スクリーンショット 2018-11-25 15.42.42.png
スクリーンショット 2018-11-25 15.43.01.png
スクリーンショット 2018-11-25 15.42.52.png
スクリーンショット 2018-11-25 15.43.15.png
こんな感じ

###計算結果画面の実装
計算結果表示画面の機能を実装してみたよ

ResultActivity.kt
package com.example.natsuki.dentaku

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView



class ResultActivity : AppCompatActivity() {

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

        //入力画面でIntentに詰めた値を取り出す
        val price = intent.getIntExtra("price",0)
        val discount = intent.getIntExtra("discount",0)

        val expression = findViewById<TextView>(R.id.expression_label)
        expression.text = getString(R.string.expression,price,discount)

        //割引後の価格を計算
        val discountedPrice = price * (100 - discount) /100

        val result = findViewById<TextView>(R.id.result_label)
        result.text = getString(R.string.result,discountedPrice)

    }
}

完成!

##⑥テスト・デバッグ
ちゃんと動くよ!
スクリーンショット 2018-11-25 15.58.44.png
スクリーンショット 2018-11-25 15.58.51.png

#あとがき
最後らへん雑になってたけど初めてのAndroidアプリができて嬉しい
もうちょっと勉強しよ

14
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?