Android Kotlin Fundamentalsで学ぶ その2

7 min read読了の目安(約6400字

はじめに

この記事はGoogleが提供しているCodelabの中のAndroidを作りながら学ぶAndroid Kotlin Fundamentalsコースで学習した内容を自分用に残していくものです。間違っていることなどあればコメントをいただけるとありがたいです!

この記事について

その2では、Lesson2について残していきます。
このレッスンでは、LinearLayoutConstraintLayoutを用いてレイアウトを作成する方法を学びます。また、findViewByIdメソッドとdatabindingによる呼び出しの方法も説明しています。

2-1 LinearLayout using the Layout Editor

LinearLayout

Imgur
の2種類がある。

padding margin

  • padding: ビューとコンテントとの内側のスペース
  • margin: ビューの境界の外側のスペース

2-2 Add user interactivity

この章では、AboutMeアプリを作成しながら、EditTextButtonのイベントハンドラを作成していきます。

ビューについて

  • EditText: ユーザに期待する入力をしてもらうために、
    • hint: 何を入力したらいいか未入力のEditTextに表示
    • inputType: 入力する形式を指定する。passwordを指定すると入力している文字列がマスキングされたり、phoneを指定すると数字キーパッドが表示され、数字のみ入力できるようになる。

などの属性を追加するべき。

Attribute

  • layout_gravity: 親のビューを中心に位置を指定

レイアウトファイルについて

レイアウトを編集する上で、ある程度決まっている部分(配色とか、文字サイズなど)はapp/src/main/res/values/内にxmlファイルで指定する。大まかに以下のファイルがある。

  • colors.xml: 色の指定に使用するカラーコードなどをまとめる
  • strings.xml: ビューに表示する文字列をまとめる
  • dimens.xml: フォントサイズ(sp)やデザインする際の大きさを(dp, px)などをまとめる
  • styles.xml: ビューの外観や書式を指定するプロパティをまとめる
activity_main.xml
<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textColor="#00FF00"
    android:typeface="monospace"
    android:text="@string/hello" />

を下のスタイルにまとめることで、

styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="CodeFont" parent="@android:style/TextAppearance.Medium">
        <item name="android:layout_width">fill_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:textColor">#00FF00</item>
        <item name="android:typeface">monospace</item>
    </style>
</resources>

このようにすっきり書ける。

activity_main.xml
<TextView
    style="@style/CodeFont"
    android:text="@string/hello" />

クリックリスナー

ボタンイベントの追加について

*.kt
findViewById<Button>(R.id.button).setOnClickListener {
            action(it)
        }

このようにfindViewByIdでビュー(今回はボタン)と対応づけ、setOnClickListenerで処理を行う。この時、対応づけられたビューはsetOnClickListener内ではitとして定義される。

2-3 ConstraintLayout using the Layout Editor

ConstraintLayoutについて

  • ビューを柔軟な方法で配置、またはサイズ変更することができるViewGroup
  • LinearLayoutのようにビューの配置をネストすることなしに、フラットな階層でxmlファイルをい記述できる
  • レイアウトエディタ(言い方が正しいかわからないけど)を使ってドラッグアンドドロップで配置できる
  • 簡単なレイアウトはテキストを編集せずレイアウトを作ることができる
  • constraint=制約と訳される
  • 親レイアウトや他のビューとの水平垂直の位置関係・制約を設けることで配置していく

こんな感じ

Imgur
上のレイアウトの場合、少し省略しますが、

buttons.xml
    <Button
        android:id="@+id/button1"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@id/button2" />

    <Button
        android:id="@+id/button2"
        app:layout_constraintTop_toTopOf="@+id/button1"
        app:layout_constraintStart_toEndOf="@+id/button1"
        app:layout_constraintEnd_toEndOf="parent"/>

こんな感じでレイアウトされる。
制約としては、

  • ボタン1
    • Top: 親Top
    • Start: 親Start
    • End: ボタン2Start
  • ボタン2
    • Top: ボタン1Top
    • Start: ボタン1End
    • End: 親End
      こんな感じ。

viewの制約について

Imgur
layout_constraintA_toBOf
A, Bに入る制約は以下の通り

  • 上部: Top
  • 下部: Bottom
  • 右部: End(Right)
  • 左部: Start(Left)

で、Aは自身の制約, Bは相手の制約になる
だから上の例ではボタン1のStart(左側)は親レイアウトの左側との制約があり、ボタン1のEnd(右側)はボタン2の左側と制約がある。
(この制約あるなしって言い方が正しいのかどうか...)

実際に作ってみた

完成形
Imgur

LinearLayoutと比較した時、ネストの少なさがとても魅力的だと感じた。
今回のレイアウトだと少し見にくいですが、この3つのレイアウトをネストする必要があるため、コードに記述しても見にくくなってしまう。
Imgur

2-4 Data binding basics

通常、ビューの参照にはfindViewById()関数を使用する。ただ、ビューの数が多くなったり、レイアウトのネスト、階層が深く、大きくなってしまうと、ビューの検索に時間がかかり、パフォーマンスが落ちてしまう。
そこで、Bindingと呼ばれる各ビューの参照を含むオブジェクトを使うことで解決する。これをデータバインディングという。

Imgur
こんな感じで記述する。(参照: Data binding basics)

Data Binding のメリット

  • findViewById()よりもコードが短く、読みやすく、保守も簡単
  • データとビューの分離
  • アプリ起動時に1度全てのビューを取得
  • ビューの型安全性を得られる

手順

  • データバインディングを有効にする
build.gradle(app)
android{
	(省略)
    buildFeatures {
        dataBinding true
    }
	(省略)
}
  • レイアウトファイルの変更
activity_sample.xml
<layout> <-最も外側のタグに指定
   <LinearLayout ... >
   ...
   </LinearLayout>
</layout>
  • バインディングオブジェクトの作成
SampleActivity.kt
import com.example.android.aboutme.databinding.ActivityMainBinding <- import部分に追加
import androidx.databinding.DataBindingUtil <- import部分に追加

private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?){
    binding = DataBindingUtil.setContentView(this、R.layout.activity_main)
		(省略)
}

これでデータバインディングの設定は終了
binding.{ビューのid}で参照可能

データクラス

データバインディングを使うことで、データクラスを直接利用できる。

手順

  • データクラスの作成
SampleData.kt
package jp.sample.aboutme

data class SampleData(var name: String = "", var age: int = 0)
  • レイアウトにデータクイラスを追加
    xmlファイルの<layout>の下に以下を追記
sample_activity.xml
<layout>
    <data>
        <variable
	     name='sampleDataClass(データクラスの変数名)'
	     type='完全修飾名(パッケージ名+変数名)'
	/>
    </data>
	    (省略)
    <TextView
        ~
	android:text="@={sampleDataClass.name}"
</layout>
  • データを作成する
SampleActivity.kt
    private val sampleData: SampleData = SampleData("Aleks Haecky")
    override fun onCreate(savedInstanceState: Bundle?) {
        ~
        binding.sampleData = sampleData
	~
    }

まとめ

今回はLinearLayout, ConstraintLayoutのレイアウトの仕組み、書き方を学びました。ConstraintLayoutがとてもシンプルかつわかりやすく記述できることがとても有用であり、使うべきレイアウトだと感じました。また、ConstraintLayoutの制約の付け方はもっと自分でやってみてサラサラっと書くことができるようになればいいと思ってます。