さて、引き続きデータの永続化について見ていきたいと思います。
今回はファイルを使った方法です。

Javaっぽい書き方とKotlinっぽい書き方を紹介してみたいと思います。
今回もプロジェクトは作らずにソースコードの紹介のみです。

もくじ

FileOutputStreamを使ってファイルに書き込もう
FileInputStreamを使ってファイルを読み込もう
Kotlin標準ライブラリを使ってファイルに書き込もう
Kotlin標準ライブラリを使ってファイルを読み込もう

FileOutputStreamを使ってファイルに書き込もう

まずは書き込みからやってみたいと思います。

Javaでファイル書き込みと言えばFileOutputStreamを使うのが定番で、Androidアプリに置いても使われているようです。
なのでまずはこちらのやり方から見ていきましょう。

ざっと書くと以下のようになります。

ContextクラスのメソッドであるopenFileOutput()を使ってFileOutputStreamを生成します。
Androidアプリではファイルの保存場所が決められているのですが、openFileOutput()を使うと保存場所を意識せずにファイルを作ることができます。
第一引数はファイル名、第二引数はモードを指定します。基本的にはContext.MODE_PRIVATEを使えばOKです。MODE_PRIVATE以外の定数も以前はありましたが、現在は非推奨になっているので、必ずMODE_PRIVATEを選択するようにしましょう。

あとは普通のFileOutputStreamと同じように使ってあげればOKです。

FileInputStreamを使ってファイルを読み込もう

ファイルの読み込みはFileInputStreamを使います。
ざっと書くと次のようになります。

ContextクラスのメソッドであるopenFileInput()を使ってFileInputStreamを生成します。
FileOutputStreamのときと同じように、openFileInput()を使うとファイルの保存場所を意識せずにファイルにアクセスできるようになります。
引数はファイル名です。

今回の例では一行ずつ取得しているので、BufferedReaderを使ってあげます。
val reader = inputStream.bufferedReader()のところで、BufferedReaderを生成しています。

その次のfor文ですが、Javaではよく次のように書かれます。

Kotlinはwhileの条件式の中に代入文を入れることができないのと、for eachの書き方が用意されているのでforを使って書いてあげます。

reader.readLines()で1行読み込んで、lineBufferに代入しています。
lineBufferはここではLogに出力しているだけですが、StringBufferに入れたりだとか用途に応じて使ってあげてください。

最後に一応BufferedReaderをクローズしてあげて終了です。
BufferedReaderを閉じてあげれば、FileInputStreamも閉じてくれるようです。

スポンサーリンク

Kotlin標準ライブラリを使ってファイルに書き込もう

次にKotlinの標準ライブラリを使った方法を見ていきたいと思います。

ひとまずソースを。

まずファイル名ですが、今回はファイルの保存場所を意識する必要があります。
といっても難しいことはなくて、保存場所はContextクラスのfilesDirプロパティで取得することができます。
なので、"$filesDir/hello.txt" というようにしてあげればOKです。

ファイルの操作を行うにはFileクラスを使ってあげます。File(fileName)というようにオブジェクトを作ってあげます。
あとは簡単で、writeTextメソッドを使えばさくっと書き込んでくれます。

FileOutputStreamを使うよりもスッキリかけていいですね。

Kotlin標準ライブラリを使ってファイルを読み込もう

では最後にKotlinの標準ライブラリを使ってファイルの読み込みのする方法をいきましょう。

まずソースを。

Fileの生成までは書き込みのときと同じです。

ファイルの中身を読み込むときですが、1行ずつの場合はforEachLineを使えばOKです。
イテレーターなのでちょっと特殊な書き方に思えますが、最後の行までループしてくれると思っておけばよいかと思います。
for文と違って、受け取る変数がないのですが、itというイテレーター専用の変数(ちょっと違うかも?)があるのでそれを使うと1行ずつのデータを受け取ることができます。
ここではitをログに出力しているだけですが、itをStringBufferに保存するなど用途に応じて使ってあげてください。

ファイルの読み込みもこちらのほうがFileInputStreamを使うよりもすっきりかけますね。

ソース量はKotlinの標準ライブラリを使ったほうが少なくなりますが、ファイルの場所をきちんと指定する必要があるなどのデメリットもあるので、どちらがいいのかは結局わかりません…。
どちらの書き方も知っておくと便利かなぁとは思います。

さて、今回はデータの永続化について見ていきたいと思います。
一番簡単な方法はSharedPreferencesを使う方法なので、まずはこちらから。

簡単に使えますが、キーと値のペアを保存するだけなので、アプリの設定値などごく小さい単位のデータの保存に使います。
大きなデータには向かないのでご注意を。

今回はSharedPreferencesの使い方だけ見ていきたいと思うので、AndroidStudioのプロジェクトは作らずに、コードの紹介だけしたいと思います。
いろいろなサイトで紹介されていますが、Kotlinでの書き方を紹介します。

もくじ

1. SharedPreferencesを生成してみよう
2. データを読み込んでみよう
3. データを書き込んでみよう
4. 複数のSharedPreferencesを使ってみよう

1. SharedPreferencesを生成してみよう

まずはSharedPreferenceのインスタンスを生成する必要があります。と言っても簡単でActivityにgetPreferencesというメソッドが用意されているのでそれを使います。

引数はアクセス権限の指定で、いろいろモードはあるのですが、現在推奨されているのはMODE_PRIVATEのみなようです。このアプリ内のみで使う、といった指定ですね。

上記の例はActivityから使う場合の書き方です。
もし、Fragmentなどから使う場合にはContextの取得が必要なので、以下のように書いてください。

以降はActivity内で実行することを前提として話を進めます。

2. データを読み込んでみよう

SharedPreferenceからデータを読み込むにはgetInt()getString()といった具合に、取得したいデータのデータ型に応じたメソッドを使う必要があります。

例えば、「count」というキー値に対応しているデータを取得したい場合には以下のように書いてあげます。

1つ目の引数がキー値ですね。2つ目の引数はキーが存在しない場合のデフォルト値になります。

なので上の例だと、countというキーのデータがSharedPreferenceにあればそれを取得、もしキーがなければ0が取得できるというわけです。

3. データを書き込んでみよう

データの書き込みはちょっと面倒だったりします。
SharedPreferenceのインスタンスから、SharedPreferences.Editorというのを生成して上げる必要があります。
それから、putInt()putString() といったメソッドを使用してキーと値をセットしたあとに、commit()メソッドを使って保存する、といった流れになります。

上記の例は、SharedPreferencesからcountのデータを取得して、countを更新後、再びSharedPreferencesに書き込む、といったものです。

最後のcommit()は忘れがちなのでご注意を…。(私はそれでしばらく悩みましたw)

書き込むのが1つだけでshardPrefEditorとかいちいち変数を用意するのが面倒な場合は、下記のようにまとめて書いちゃうことも可能です。

4. 複数のSharedPreferencesを使ってみよう

保存する値が少ない場合などは今までのやり方で問題ないのですが、例えば画面毎に分けたいなどといった場合は、複数個生成することが可能です。

SharedPreferencesのインスタンスを作るときに、getSharedPreferences()というメソッドを使ってあげればOKです。

1つ目の引数は識別子になります。ここを変更することで複数のSharedPreferencesを持つことができるようになります。
識別子は「com.example.myapp.PREFERENCE_FILE_KEY」といったようにアプリを一意に識別できるような名前にすることが推奨されています。

2つ目の引数はgetPreferences()のときと同じようにアクセス権限を指定します。こちらもMODE_PRIVATEを使うようにしましょう。

読み書きは今までと同様です。
シンプルなサンプルですが、次のように使えばOKです。ここでは同じActivityで2つのSharedPreferencesを使うようになっています。

SharedPreferencesの識別子が違うものになっていれば、キー値は同じものが使えます。
このソースが実行されるたびに、count1は1ずつ、count2は2ずつカウントアップされていきます。
本来、アプリの設定値などを保存するためのものなので、このサンプルの使い方はそれとは違うものになっているので、動作の参考にとどめてくださいね。

簡単でしたが、SharedPreferencesのKotlinでの使い方の紹介でした。

前回からずいぶん間が空いてしまいました💦
色々立て込んでまして…。またぼちぼち更新していけたらなと思ってます。

さて、今回はOptionsMenu(オプションメニュー)の使い方について見ていきたいと思います。
最近はナビゲーションメニューが追加されて、あまり使われていないのかなぁとも思ったのですが、
Androidの設定画面やTwitterクライアントとかいろいろなところで地味に今でも使われているので
ちょっと扱ってみたいと思います。

さて、今回の目次はこんな感じになりました。

もくじ

1. 開発環境
2. プロジェクトを作ろう
3. 画面を作ろう
4. メニューを作ろう
5. メニューを選択してみよう
6. メニューのアイテムをアイコンで表示してみよう
7. メニューのアイテムを非表示、無効化してみよう

今回紹介したアプリのソースはGitHubにもあるので合わせてご参照ください。

1. 開発環境

  • AndroidStudio 3 Preview (Canary 3)
  • Kotlin
  • Java 1.8
  • macOS Sierra (10.12.6)

基本的にはAndroidStudio 2.3でも同じように作れます。

バージョンが変わるとエラーが出たり動かなくなったりするかもしれませんが、
エラーメッセージをよく読んで指示に従ったり、検索などして調べてみてくださいませ。

AndroidStudio と Java はすでにインストールされている前提で進めますのでご了承ください。

2. プロジェクトを作ろう

さて、プロジェクトを作っていくわけですが、前回までとちょっとだけ変わっているので、順を追って説明していこうと思います。

Kotlin Android OptionsMenu(オプションメニュー)を使ってみよう

「Application Name」は「OptionsMenuSample」にしました。お好きなものにしてくださいませ。
「Company Domain」は適当なものを指定してください。
「Include Kotlin support」には必ずチェックを入れてください。
「Project Location」は保存場所になるのでデフォルトの場所で大丈夫だと思います。
設定できたら、「Next」をクリックしましょう。

Kotlin Android OptionsMenu(オプションメニュー)を使ってみよう

ターゲットデバイスは今回は「Phone and Tablet」にチェックをします。

この画面ではターゲットOSのバージョンを決めるのですが、現状のシェア率を考慮したり、ご自分の端末に合わせるなど任意のバージョンを選択してください。
各OSがどの程度シェアがあるのかは、「Help me choose」から確認できるので、そちらも参考にしてみてください。

設定できたら「Next」で次に進みましょう。

Kotlin Android OptionsMenu(オプションメニュー)を使ってみよう

この画面ではプロジェクトのテンプレートを決めますが、ここが前回までと違うポイントです。
今回は「Basic Activity」を選択してください。

前回までは「Empty Activity」を選択していましたが、このテンプレートだとオプションメニューの設定が大変なので、もともと設定されている「Basic Activity」を使っていきましょう。

では、「Next」で進みましょう。

Kotlin Android OptionsMenu(オプションメニュー)を使ってみよう

この画面では作成されるActivityやLayoutの名前を決めることができますが、今回はこのままでOKでしょう。
「Finish」をクリックしましょう。

色々ごにょごにょとプロジェクトを作成してくれるので、しばしお待ちいただくと、プロジェクトが作成されると思います。

Android Studio 2.3をお使いの方は第1回の4. JavaをKotlinにしようまでを参考にしてプロジェクトの作成とKotlinの設定を行なってください。
Activityのテンプレートの作成はAndroid Studio3のときと同様に「Basic Activity」を選択してください。

3. 画面を作ろう

画面を作っていくのですが、今回はオプションメニューの操作だけに焦点を絞りたいので、画面上には何も表示させないようにしたいと思います。

では、レイアウトファイルを修正していきたいのですが、今回選んだBasic Activityはちょっと構成が変わっています。
layoutフォルダを見てみるとactivity_main.xmlcontent_main.xmlがあります。

ここでは詳しくは説明しませんが以前とActionBarの扱い方が変わっているからです。

content_main.xmlを編集しよう

まずは、content_main.xmlを開いてください。
TextViewが1つあると思いますが、今回は使わないので、削除してしまいましょう。

AndroidStudioのバージョンによってはDesignタブのプレビュー画面でエラーが出ていてる可能性があります。
その場合は「Component Tree」からTextViewを選択してdeleteキーで削除するか、
Textタブを選択して、xmlから<TextView .../>の記述を削除してください。

activity_main.xmlを編集しよう

次に、activity_main.xmlを開いてください。

Basic Activityを選択するとデフォルトでFloatingActionButtonが配置されています。
今回は使わないので削除しましょう。
この場合もプレビュー画面がエラー等が出ていて使えない場合はComponent TreeやTextタブから削除してください。

MainActivty.ktを編集しよう

activity_main.xmlからFloatingActionButtonを削除しましたが、MainActivity.ktにクリック時の処理が書かれているので、そこを削除しましょう。

onCreate()内の、以下のコードを削除してください。

FloatingActionButtonは最近のアプリでよく使われるので後々扱ってみたいと思います。

今回は画面についてはこれだけです。
オプションメニューに注力したいので、極力シンプルに…。

4. メニューを作ろう

さて、いよいよメニューを作ってみましょう!
といってもすでにできていたりもしますが…。

res/menuフォルダのなかに、menu_main.xmlというファイルがあるので開いてください。

オプションメニューはDesignで作っていくより、Textのほうが作りやすい気がするので、Textタブを開いてください。
そうすると、以下のようなソースになっていると思います。

ざっくり説明するとmenuタグがオプションメニューの大枠と思っていただいて、その中のitemタグがメニューの項目になります。

現状でエミュレータで確認してみると、右上にメニューアイコン(︙のアイコン)があって、

Kotlin Android OptionsMenu(オプションメニュー)を使ってみよう

クリックするとSettingsという項目があるはずです。

メニューを追加してみよう

では、メニューを追加してみたいのですが、その前にざっくりとitemのプロパティを説明しておきます。

android:id: 言わずもがなIDですね
android:orderInCategory: itemが複数のときの表示順を設定します
android:title: 表示される文字列ですね
app:showAsAction: 表示方法を指定します。複数指定可能。いろいろ設定値がありますがのちほど説明します。

ひとまず単純にメニューを増やしてみましょう。今あるitemをコピー&ペーストで次のように書いてみましょう。
(ハイライト部分が今回の追加箇所です)

上から、設定、追加、削除、保存といった項目になります。
android:orderInCategoryは上から順に1を足していった数値を書いておきます。
順番を変えたい場合はそれぞれ足したり引いたりしてお好きな順番にしてください。

android:titleは今はエラーになっていると思いますが、あとでstrings.xmlで設定していくのでとりあえずこのままでOKです。

app:showAsActionも今のところは初期設定のままにしておきましょう。

メニューも文字列を設定しよう

android:titleに設定する文字列を定義していきましょう。
もちろん直接書いてしまってもいいのですが、文字列はstrings.xmlに定義しておくことが推奨されているのでそれに従います。

res/values/strings.xmlを開いてください。

Settingsをコピー&ペーストして、action_addaction_deleteaction_saveを作成しましょう。
それぞれの設定値は以下のコードを参照してください。

これで、menu_main.xmlのエラーは消えていると思うので、確認してください。

もう一つstringを定義しておきたいと思います。ここではまだ使いませんがのちほど使うので…

メニューを表示しよう

メニューを表示してみましょう。と言っても、すでに表示されていますが…。

メニュー用のxmlファイルを作っても、もちろん自動で表示されるようになるわけではありません。
ソースから設定して上げる必要あります。

なので少し見ていきたいので、MainActivity.ktを開いてください。

onCreate()の下あたりに次のソースがあると思います。
(実際はコメントがたくさん書いてあるかもしれませんが、コメントは削除してもOKです)

onCreateOptionsMenu()というその名もズバリのメソッドが定義されています。
渡されてくるMenuに対して、menuInflater.inflate()を使って、レイアウトファイルを指定してあげればOKです。
Activityのときと同様ですね。
最後にreturn trueとするのはお忘れなく…(っていってもなにも返さなければエラーになりますがw)

では、ここまででエミュレータで確認してみましょう。

メニューアイコン(︙のアイコン)をクリックすると追加した項目も表示されるはずです。

Kotlin Android OptionsMenu(オプションメニュー)を使ってみよう

5. メニューを選択してみよう

無事にメニューが表示されるようになったので、次はメニューを選択してみましょう。

選択されたときの処理もMainActivity.ktに最初から書かれていたります。

onOptionsItemSelected()が選択されたときに呼ばれるメソッドです。

引数のitemに選択されたメニューの項目のオブジェクトが渡されるので、
whenでメニューのitemのIDを判定しています。
IDはmenu_main.xmlでつけてあげたIDですね。

ここでは該当するIDが会った場合はreturn trueとしていて、
該当するIDがなかった場合には親クラスを呼んで終了しています。

普通のアプリだったらメニューを選択したら違う画面に遷移したりすることが多いのですが、
今回はシンプルにToastを表示するだけにしておきます。
画面遷移する場合は普通にstartActivityをするだけなのでこちらの記事を参考にしてください♪

というわけで次のように書き換えてみましょう。

whenでIDを調べて分岐するのは先程と同じですが、ここではToastに表示するメッセージを返して、messageに代入しているだけです。
strings.xmlであとで使うので、と言って追加した文字列はここのelseのときのメッセージとして使っています。
(といっても、elseになることがそもそもないのですが…)

messageが作れたら、Toastを作って表示します。
最後はreturn trueとしてもいいと思いますが、一応親クラスを呼び出してその戻り値を返すようにしました。

ではここまでできたらエミュレータを起動して、動作を確認してみましょう。

メニューの項目を選んだときに該当のメッセージが表示されればOKです!

もう少し突っ込んだ使い方をしてみましょう。

最近はFloatingActionButtonが出てきて、少なくなってきた気もしますが、「︙」のメニュー以外にアイコンをActionBarに表示することも可能です。

その辺のやり方を見ていきましょう。とは言え簡単なのですが。

今回はAddのアイコンを「︙」の横に表示されるようにしてみます。
アイコンを使うにはandroid:icon属性を設定してあげます。今回はAndroidが標準で用意している@android:drawable/ic_menu_addというアイコンを使いましょう。

これだけだとアイコンが今までと同じように「︙」のなかにメニューが入るだけなので、ActionBarに表示されるように設定します。
そこで使うのがapp:showAsAction属性です。いままでneverと設定していた箇所ですね。

このshowAsAction属性は他にも種類があって、それらを使うことでアイコン表示できるようになります。
属性値は以下のようなものがあります。

属性値 意味
never 常に表示しない
ifRoom 表示する余裕があれば表示
always 常に表示
withText android:titleのテキストを表示

今まで使用していたneverは常に表示しない、なので、ActionBarには直接表示されていなかった、というわけです。
なので、Addアイコンを表示させるにはalwaysifRoomを使えばいいのですが、ifRoomが推奨されているようです。

これだけでもアイコンが表示されるのですが、ついでにwithText属性も追加してみましょう。(この属性は|を使用することで他の属性と同時に指定することが可能です。)
withText属性はスペースがあればandroid:titleの内容を表示してくれます。

というわけで変更したAddのitemは以下のようになります。

では、エミュレータで確認してみましょう。

Kotlin Android OptionsMenu(オプションメニュー)を使ってみよう

このように+マークのアイコンが表示されればOKです。

withText属性が効いているか確認するにはエミュレータを横向きにしてみましょう。

Kotlin Android OptionsMenu(オプションメニュー)を使ってみよう

そうするとアイコンの横に「ADD」とテキストが表示されるようになったかと思います。

7. メニューのアイテムを非表示、無効化してみよう

メニューのアイテムを状況に応じて非表示にしたり無効化したりすることもあると思うのでその辺もやってみましょう。

このような操作は動的に行うことが多いはずなので、プログラムから制御していくので、MainActivity.ktを開きましょう。

色々やり方はあると思いますが、オプションメニューが表示される前に呼ばれるonPrepareOptionsMenuというメソッドを使っていきましょう。

こんな感じになっています。Booleanを返す必要があるので、親クラスを呼んでそのままreturnすればいいでしょう。

アイテムを非表示にする

ではまずは非表示にする方法から見ていきましょう。
本来はここで何かしらの条件分岐をすることになると思いますますが、今回はやり方の紹介だけなのでいきなり非表示にします(笑)

たとえば、deleteメニューを非表示にしたい、という場合はmenuからアイテムを取得して、isVisibleプロパティをfalseにしてあげればOKです。

menuからアイテムを取得するにはmenu?.findItem(アイテムのID)で取得できます。
ちなみにmenuはnullable型で渡されるので、?を使って安全に処理をしてあげる必要があります。

次のように書いてあげればOKです。

アイテムを無効化する

では次に無効化にする方法を見ていきましょう。
こちらもはやり方の紹介だけなのでいきなり無効化します。

今度は、saveメニューを無効化したいとしましょう。
非表示のときの同じようにmenuからアイテムを取得して、isEnabledプロパティをfalseにしてあげればOKです。

次のように書いてあげればOKです。

これで実行するとdeleteメニューは表示されなくなり、saveメニューは無効化されて押せなくなるはずです。

Kotlin Android OptionsMenu(オプションメニュー)を使ってみよう

こうですね。deleteはなくなり、saveは薄く表示されていてクリックしても反応しないはずです。

といったわけでざっくりではありましたが、オプションメニューの使い方について見てみました。

前回に引き続き、ListViewを扱ってみたいと思います。
いままではAndroidが用意していたレイアウトを使っていましたが、今回は独自のレイアウトのアイテムを表示してみましょう。

完成版はこんな感じです。

kotlin-customlist-01.png

お花の名前と写真、説明が表示されるようになります。
今まではテキストだけだったので、他のViewと組み合わせて独自のレイアウトを使った方法を解説していきます。

というわけで、今回のもくじはこんな感じになります。

もくじ

1. 開発環境
2. プロジェクトを作ろう
3. 画面を作ろう
4. ListViewの行のレイアウトを作ろう
5. 画像を用意しよう
6. データを作ろう
7. 独自のAdapterを作ろう
8. ListViewを表示してみよう
9. ViewHolderを使ってみよう
10. 動作確認してみよう

今回紹介したアプリのソースはGitHubにもあるので合わせてご参照ください。

1. 開発環境

  • AndroidStudio 3 Preview (Canary 3)
  • Kotlin
  • Java 1.8
  • macOS Sierra (10.12.3)

基本的にはAndroidStudio 2.3でも同じように作れます。

バージョンが変わるとエラーが出たり動かなくなったりするかもしれませんが、
エラーメッセージをよく読んで指示に従ったり、検索などして調べてみてくださいませ。

AndroidStudio と Java はすでにインストールされている前提で進めますのでご了承ください。

2. プロジェクトを作ろう

Android Studio 3 をお使いの方はこちらの記事を参考にしてプロジェクト作成とKotlinの設定を行なってください。

Android Studio 2.3をお使いの方は第1回の4. JavaをKotlinにしようまでを参考にしてプロジェクトの作成とKotlinの設定を行なってください。

プロジェクトの Application Name は「CustomListView」にしました。

Activity Name はデフォルトのまま「MainActivity」です。

3. 画面を作ろう

では、activity_main.xmlを開いて、画面を作っていきましょう。

部品を追加しよう

今回、必要となってくる部品はListViewだけです。

Palette の Containers の中にある 「ListView」 を画面に適当な位置に配置してください。

Kotlin de Android 第4回 ListViewを使ってみよう

部品の設定をしよう

次は部品の設定を行っていきましょう。
といっても、今回はIDを付けるだけです。
「myListView」 にしましょう。

部品の位置を設定しよう

部品の位置はLayoutEditorで設定してきましょう。

Android Studio 3 から少しだけ操作方法が変わっているので、バージョン別に記載しておきます。

Android Studio 3

WidthとHeightの設定である「match_parent」がなくなって、「match_constraint」に変わりました。
名前の通りで制約に合わせるということなようで、先に制約をつけておく必要があります。
右下の2つの制約をつけてください。縦横の中央に配置する制約ですね。

まず画面の中央に配置したいので、下の画面の整列に関する制約をつけてあげます。
右下の2つににあります。縦位置の中央と横位置の中央にする制約です。

Kotlin de Android 第5回 ListViewで2つのテキストを表示してみよう

制約がつけられたら、WidthとHeightの設定を「match_constraint」にしてあげてください。

kotlin_listview2-01.png

このような状態になっていれば大丈夫なはずです。
念のため、プレビューを画面サイズの違う機種にしてみて、ListViewが全画面表示になってればOKです。

Android Studio 2.3

全面に表示したいので、WidthとHeightを「match_parent」にすればいいのですが、部品を適当に配置しただけの状態ではなぜがうまく反映されません。

で、配置したsimpleListViewを選択して、左下に表示される「×」印をクリックしてください。

Kotlin de Android 第5回 ListViewを使ってみよう

こうすると、今ついている制約を全部削除してくれます。
制約自体はつけていないはずなですが、適当に配置した状態ではなにか制約が付いてしまっているのかもしれません。

そのあとにWidthとHeightを「match_parent」にしてください。
そうすると縦横ピッタリに配置されるはずです。

念のため、プレビューを画面サイズの違う機種にしてみて、ListViewが全画面表示になってればOKです。

4. ListViewの行のレイアウトを作ろう

今までは標準で用意されていたレイアウトを使っていましたが、今回は独自に作成してみます。

レイアウトファイルを追加しよう

まずレイアウトファイルを追加する必要があります。
メニューの File > New > Android resource file を選択してください。
kotlin-customlist-03-01.png

そうするとリソースファイルの追加画面が表示されます。

kotlin-customlist-03-02.png

以下のように設定してください。

File name: listview_item
Resource type: Layout
Source set: main
Directory name: layout

設定できたらOKをクリックしましょう。新しくxmlファイルが生成されるはずです。

部品を追加しよう

さて、レイアウトファイルができたので、部品を配置していきたいのですが、デフォルトだとベースのレイアウトがLinearLayoutになっています。
せっかくなので、ConstraintLayoutに変えましょう。

今、「Component Tree」にはLinearLayoutがひとつだけある状態になっていると思いますので、LinearLayoutを選択して、右クリックをします。

メニューが表示されるので、一番下の「Convert LinearLayout to ConstraintLayout」をクリックしてください。kotlin-customlist-03-03.png

なにやらダイアログボックスが表示されますがデフォルトのまま「OK」をクリックしてください。
そうするとベースのレイアウトがConstraintLayoutに変わっているはずです。

kotlin-customlist-03-04.png

では、部品を配置していきましょう。
今回は画像とテキストなので、ImageViewが1つ、TextViewが2つ必要です。

まずImageViewから配置していきましょう。
「Palet」の「Images」から「ImageView」をドラッグ&ドロップして左上あたりに適当に置いておきましょう。
配置するときに画像の選択画面が表示されますが、プログラムから変更していくのでここでは適当なものを選んでおいてください。
ic_launcher_roundにしておきました。

それから、TextViewを2つ、ImageViewの隣に置いておきます。

部品を設定しよう

それぞれの部品にIDをつけましょう。

View ID
ImageView profileImageView
TextView nameTextView
TextView contentTextView

nameTextViewとContentTextViewは文字を左揃えにしたいので「TextAlignment」を一番左側のアイコンを選んでおきます。
それからnameTextViewは太字にしたいので「TextStyle」で「B」を選んでください。

部品の位置を設定しよう

部品の位置はLayoutEditorで設定してきましょう。

まずはprofileImageViewからやっていきましょう。
上と左をそれぞれ端っこまで持っていって、マージンを16にします。
layout_widthとlayout_heightは正方形にしたいのでそれぞれ72dpにします。
下の画像の様になっていればOKです。

kotlin-customlist-04.png

次はnameTextViewですが、左はprofileImageViewの右に、上は上端に、右は右端にそれぞれ接続します。
layout_widthは「match_constraint」にします。
上左右のマージンは16ずつにしておきます。

下の画像の用になっていればOKです。

kotlin-customlist-05.png

最後にcontentTextViewですが、左はprofileImageViewの右に、上はnameTextViewの下に、右は右端にそれぞれ接続します。
上のマージンは0、下左右のマージンは16ずつにしておきます。

下の画像の用になっていればOKです。

kotlin-customlist-06.png layout_widthは「match_constraint」にします。

ちょっと崩れてるように思えますが、実際はテキストに合わせた高さになるので問題ないです。

これでListViewの行のレイアウトが完成です。

5. 画像を用意しよう

適当なサイズ(正方形)の画像を5枚用意してください。
学習用途のみだったらGitHubからダウンロードして使っていただいてもOKです。

本来は画面の解像度毎にサイズを変えたものを用意するのが推奨されるのですが、ちょっと大変なので今回はワンサイズのみにしたいと思います。なので少し大きめのサイズにしています。

用意した画像はres/drawableにコピーしておいてください。
Finderで画像をコピー、AndroidStudioのdrawableを選択して貼り付けで大丈夫です。

6. データを作ろう

次はmyListViewに表示するためのデータを作っていきましょう。

データクラスを作ろう

今まではテキストだけだったのでListやMapでOKだったのですが、今回は画像も必要なのでデータクラスを作って対応します。

MainActivityに書いていってもいいのですが、せっかくなので別ファイルにしておきたいと思います。
今回のサンプルでは必要ないのですが、別の画面からも使いたいという場合に使いまわしができるようになるのでそのようにしておきましょう。

メニューのファイル > New > Kotlin File/Class を選択します。

そうするとこのような画面になるので、

kotlin-customlist-07.png

Name: FlowerData
Kind: Class

このように設定して、OKとするとファイルが作成されるはずです。

クラス名だけ定義されている状態になっていると思うので、データクラスに変えていきましょう。

引数はそれぞれ、お花名前、説明文、写真のIDになります。

これだけでデータクラスは完成です。
JavaだとプロパティやらSetter、Getterやら作らないといけないので、Kotlinって楽ちんですね♪

FlowerDataを作ろう

ではこれで準備ができたので、データを作っていきましょう。
MainActivity.ktを開いてください。

といってもゴリゴリ書くだけなのですが…。

onCreate()のなかに書いていきましょう。

ひとまず名前、説明文、画像のリストを作ります。
今回画像はアプリ内に格納したものを使っていくのでIDで管理します。

説明文はWikipediaから拝借しています。
これらのリストですが数は合わせておいてくださいね。

では、これらの配列をFlowerData型のリストに格納していきましょう。

MutableListを使うのがあまり好きじゃないのですが、ここではしょうがないので…。
単純にどんどん追加していくだけです。

これでひとまず表示させるデータは完成です。

7. 独自のAdapterを作ろう

いままではデータの型が1つだったので、ArrayAdapterやSimpleAdapterで事足りていましたが、
今回はStringとIntになってくるのでAdapterを独自に作る必要があります。

MainActivityクラスのなかに書いていきましょう。

今回はArrayAdaperのサブクラスとして作成します。

FlowerAdapterという名前にして、コンストラクタ引数にはContextとFlowerDataのリストを受け取るようにします。
親クラスであるArrayAdapterには第一引数にContext、第二引数はレイアウトファイルのIDですがここでは0にしておいて、第三引数にはFlowerDataのリストをそれぞれ渡してあげます。

次にプロパティを1つ用意しておきます。

あとでレイアウトファイルからViewの取得をしたりするので最初に生成しておきます。

次にListViewを表示するときに呼ばれるgetView()というメソッドをoverrideします。

引数ですが、positionは表示するviewが何番目なのか、convertViewは表示するView、parentはconvertViewの親ビューとなります。

そして、viewを返すのですが、基本的にはconvertViewを返しますが、ここがNullableになっているとおりnullで渡されてくることがあります。
nullのときはViewを生成して返してあげます。行のViewは最初はない状態で当たり前ですよね。
じゃあ、nullじゃないときってなんなの?となるわけですが、ListViewは例えば100行必要という場合に100個のViewを作るわけではありません。
画面に表示される分のViewだけ作成して、スクロールして見えていなかった分の行を表示するときは見えなくなった分のViewを再利用するという仕組みになっています。
いちいち生成していたらリソースが増えていく一方なのでこのような仕組みが取られています。

というわけなので、convertViewがnullだったらViewを生成しないといけないのですが、引数は変更できないので別の変数を用意してそちらに代入しておきます。

それから、viewがnullかどうかチェックして、nullだった場合はlayoutInflaterを使って、Viewを作ってあげればいいですね。

Viewが生成できたら、それぞれの部品にFlowerDataを反映させたいのですが、getItem()というメソッドでデータを取得できます。
引数にはpositionを指定します。

データが取得できたら、部品のViewを取得して、データを反映させて、viewを返せばOKです。

nameTextViewとcontentTextViewはtextプロパティにそれぞれ文字列を入れてあげればOKですね。
profileImageViewに関しては画像のIDが入っているだけなので、画像に変換してあげれる必要があります。
BitmapFactory.decodeResource()というメソッドを使ってあげて、第一引数にはcontext.resourcesを、第二引数に画像のIDを指定するとBitmapに変換してくれるので、それをImageViewのsetImageBitmapに渡してあげればOKです。

これでひとまず独自Adapterは完成です。
(あとで少しだけ手直ししますが)

8. ListViewを表示してみよう

さて、独自AdapterのFlowerAdapterが完成したので、ListViewに表示してみましょう。

使い方はArrayAdapterのときと同様です。
onCreate()のFlowerDataのリストを作ったあとに書いていきましょう。

まずはFlowerAdapterを生成します。引数にはContextのthisと、FlowerDataのリストを渡してあげればOKですね。
作ったadapterをmyListView.adapterにセットしてあげればOKです。

ではここまでできたら、エミュレータで確認してみましょう。
完成版と同じように表示されればOKです。

9. ViewHolder

さて、ほとんどできているのですが、少しだけ改良してみましょう。
どこかというと、アダプタの中でデータをセットするときに毎回findViewById()をして部品を探しているのでこのあたりをviewを作ったときに1回だけになるようにしてあげましょう。

よく使われるテクニックとしてViewHolderというクラスを使う方法があるのでやってみましょう。

ではまずViewHolderクラスをデータクラスで作っておきます。
FlowerAdapterの上辺りに作っておけばいいでしょう。

内容はいたって簡単で各部品のプロパティを用意しておけばOKです。

そうしたらViewHolderを使うようにFlowerAdapterを書き換えてみましょう。
getView()メソッドを以下のように修正していきます。

まず、ViewHolderの変数を用意しておきます。
viewがnullだったときにviewを生成しますが、そのときにViewHolderを作って各部品をfindViewByIdで取得しておきます。
そして、viewのtagプロパティに保存しておきます。

viewがnullじゃなかったとき、すなわち再利用できるviewがあったときは、view?.tagからViewHolderを取り出します。

ここまでできたら、FlowerDataの内容を反映させるところを以下のように書き換えてあげます。

ViewHolderに格納されている部品のviewにそれぞれ新しいFlowerDataのデータを反映させてあげればOKです。
これで、viewが生成されるときだけしか部品の生成は行わないので無駄がなくなる、というわけです。

さて、少し長くなりましたが、これで実装は完了です。

10. 動作確認してみよう

では、エミュレータで動作確認をしてみましょう。

kotlin-customlist-01.png

このように表示されればOKです。
ちょっとデータ量が少ないのでスクロールはあまりされませんが、下にスクロールすると隠れた上の行のViewが再利用されているだなぁーと思ってもらえるといいのかな、と思います。
これだとたぶん最後の行を表示しても一番上もまだ表示されているので再利用はされてないですね(汗)

基本的にこの記事ではKotlinでの書き方をメインとしているので、ListViewの仕組みをもっとしっかり学びたい!という場合はご自身で調べて見てもらえるとありがたいです。すみません(´-﹏-`;)

さて、前回にListViewを扱ってみたいと思います。
今回はテキストを2つ表示してみたいと思います。

完成版はこんな感じです。

Kotlin de Android 第5回 ListViewで2つのテキストを表示してみよう

今回も非常に単純です。
前回同様にクリックしたらToastで表示する、というところまでになります。

というわけで、今回のもくじはこんな感じになります。
今回も短めですので、ぜひ読んでいただけるとうれしいです!

もくじ

1. 開発環境
2. プロジェクトを作ろう
3. 画面を作ろう
4. データを作ろう
5. ListViewに表示してみよう
6. ListViewをクリックしてみよう
7. 動作確認してみよう

今回紹介したアプリのソースはGitHubにもあるので合わせてご参照ください。

1. 開発環境

  • AndroidStudio 3 Preview (Canary 3)
  • Kotlin
  • Java 1.8
  • macOS Sierra (10.12.3)

基本的にはAndroidStudio 2.3でも同じように作れます。

バージョンが変わるとエラーが出たり動かなくなったりするかもしれませんが、
エラーメッセージをよく読んで指示に従ったり、検索などして調べてみてくださいませ。

AndroidStudio と Java はすでにインストールされている前提で進めますのでご了承ください。

2. プロジェクトを作ろう

Android Studio 3 をお使いの方はこちらの記事を参考にしてプロジェクト作成とKotlinの設定を行なってください。

Android Studio 2.3をお使いの方は第1回の4. JavaをKotlinにしようまでを参考にしてプロジェクトの作成とKotlinの設定を行なってください。

プロジェクトの Application Name は「SimpleListView2」にしました。

Activity Name はデフォルトのまま「MainActivity」です。

3. 画面を作ろう

では、activity_main.xmlを開いて、画面を作っていきましょう。

部品を追加しよう

今回、必要となってくる部品はListViewだけです。

Palette の Containers の中にある 「ListView」 を画面に適当な位置に配置してください。

Kotlin de Android 第4回 ListViewを使ってみよう

部品の設定をしよう

次は部品の設定を行っていきましょう。
といっても、今回はIDを付けるだけです。
「myListView」 にしましょう。

部品の位置を設定しよう

部品の位置はLayoutEditorで設定してきましょう。

Android Studio 3 から少しだけ操作方法が変わっているので、バージョン別に記載しておきます。

Android Studio 3

WidthとHeightの設定である「match_parent」がなくなって、「match_constraint」に変わりました。
名前の通りで制約に合わせるということなようで、先に制約をつけておく必要があります。
右下の2つの制約をつけてください。縦横の中央に配置する制約ですね。

まず画面の中央に配置したいので、下の画面の整列に関する制約をつけてあげます。
右下の2つににあります。縦位置の中央と横位置の中央にする制約です。

Kotlin de Android 第5回 ListViewで2つのテキストを表示してみよう

制約がつけられたら、WidthとHeightの設定を「match_constraint」にしてあげてください。

kotlin_listview2-01.png

このような状態になっていれば大丈夫なはずです。
念のため、プレビューを画面サイズの違う機種にしてみて、ListViewが全画面表示になってればOKです。

Android Studio 2.3

全面に表示したいので、WidthとHeightを「match_parent」にすればいいのですが、部品を適当に配置しただけの状態ではなぜがうまく反映されません。

で、配置したsimpleListViewを選択して、左下に表示される「×」印をクリックしてください。

Kotlin de Android 第5回 ListViewを使ってみよう

こうすると、今ついている制約を全部削除してくれます。
制約自体はつけていないはずなですが、適当に配置した状態ではなにか制約が付いてしまっているのかもしれません。

そのあとにWidthとHeightを「match_parent」にしてください。
そうすると縦横ピッタリに配置されるはずです。

念のため、プレビューを画面サイズの違う機種にしてみて、ListViewが全画面表示になってればOKです。

4. データを作ろう

次はListViewに表示するためのデータを作っていきましょう。
と言っても普通にStringのListを作るだけです。

onCreate()の中に書いていきます。

今回はスクロールできるように少し多めにデータを作りましょう。
前回は項目が1つだったのでStringのArrayだったのですが、今回は項目が2つになるのでMapでデータを作って、それをListに入れていきます。

MutableListなのがちょっとあれですけども…。ここは仕方ないということで…。
他にいい方法を思いついたら更新するかもです。

5. ListViewに表示してみよう

先程作ったデータをmyListViewに表示してみましょう!

と言っても割りと簡単にできちゃいます。
ListViewの表示内容は自分で作ることもできますが、Androidが標準で用意してくれているものもありますので、今回も標準装備のものを使っていきます。

先程のlistの後に、ひとまず以下のように書いていきましょう。

引数の内容はコメントに書いたのでそちらを見てください。
ここでのキモとなる部分はコメントに from と to と書いた部分です。
from で書いたキー名の順番と to のアイテムのIDの順番が重要で、fromで一番目に書いた title は to のandroid.R.id.text1 に対応します。
title の value が android.R.id.text1 に反映されるということですね。

でも、これだけで表示されるので便利ですねー!

一応このandroid.R.layout.simple_list_item_2の中身がどのようになっているか確認しておきましょう。
Commandキーを押しながら(WindowsだとCtrlだったと思います…)、ID名をクリックするとファイルが開くはずです。
そうすると、このようになっているはずです。

Kotlin de Android 第5回 ListViewで2つのテキストを表示してみよう

ちょっと見慣れないタグもあったりしますが、今回は気にせずにスルーっと…。
重要なのは TextView が2つ定義されていて、それぞれのIDが text1、text2 になっているということです。

ここまでできたら、このSimpleAdapterをListViewに設定してあげます。

ListViewにはadapterというプロパティが用意されているので、そこに先程作ったListAdapterを入れてあげればOKです。
ただし、型変換をする必要があるので、as ListAdapterとしましょう。

ちなみにいきなりmyListViewという変数がでてきましたが、これは通常であればfindViewById()を使って部品を取得する必要があるのですが、このプロジェクトではKotlin Extensionを組み込んでいてるので、部品のIDをそのまま変数として使うことができるようになっているので注意してください。

ここまででできるとcnCreate()は以下のようになっているはずです。

これで表示されるはずなのでエミュレータで確認してみましょう。

Kotlin de Android 第5回 ListViewで2つのテキストを表示してみよう

ずらずらーっとテキストが2つある状態で表示されればOKです!

スポンサーリンク

クリックイベントを受け取ろう

Buttonのときもそうでしたが、クリックしされたという状態を受け取ってあげる必要があります。
ButtonのときはonClickプロパティにメソッド名を指定しておけばOKでしたが、ListViewの場合はちょっと違った仕組みになってきます。

ListViewの場合はListenerという仕組みを使っていきます。
こちらもイベントハンドラではあるのですが、書き方がかなり変わってきます。

色々書き方はあったりしますが、とりあえず以下のように書いていきましょう。
これもonCreate()の中に書いていきます。

ちなみにJavaだとこのように書きます。

JavaだとOnItemClickListenerをnewしてそのなかでメソッドをoverrideする感じなのですが、Kotlinだとなんともスッキリかけて素敵ですね♪

ちなみにOnItemClickの引数ですが、以下のようになります。
parent : Adapter
view : クリックされたView
position : クリックされた行番目
id : クリックされたViewのid

なので、viewからTextViewを取得して、名前を表示してみるようにしましょう。

まずはviewからTextViewを取得しないといけないのですが、findViewById()を使います。
ここで指定するIDですが、SimpleAdapterを作ったときにみたレイアウトファイルを見てみてください。
そうするとIDが指定されているのがわかると思います。text1text2いうIDですね。

なので、以下のように書いてあげれば title と detail の TextView を取得することができます。

Activityのレイアウトファイル内の部品であれば、Kotlin Extensionの機能でfindViewById()をする必要はないのですが、ここではきちんとやってあげる必要があるので注意しましょう。

TextViewが取得できたら、あとはToastで表示してあげればいいですね。

以下のように書いてあげます。

Toast.makeText() でToastを生成します。
第一引数はToastを表示するContextなので、this でOKです。
第二引数には表示したいメッセージを指定します。
第三引数は表示する時間になります。LENGTH_SHORTLENGTH_LONGがあるのでお好きな方を指定してください。
最後に.show() とすることでToastを表示してくれます。

たった1行でできちゃうんです。簡単ですよね♪
AlertDialogと違い、数秒表示されるだけなので、使用用途は限られてきますが、ちょっとした表示をするときにはとっても便利です。

ここまでで、onCreate() は以下の様になっているはずです。

さて、今回の実装はこれで全部できたので、動作確認をしてみましょう!

エミュレータで起動して、アプリが立ち上がったら、お好きな行をクリックしてみましょう。
画面下の方にToastでクリックした動物の名前が表示されれば完成です!

今回も非常に簡単な例でしたが、今後もう少し複雑なListViewの使い方についても取り上げたいと思っています。

さて、2017/05/17からGoogle I/O が開催中ですが、
Kotlinユーザーにビックニュースが舞い込んでまいりましたね。

Kotlin、Androidの公式開発言語になりましたー!

Kotlinでの発表はこちら
Kotlin on Android. Now official

めでたいですね!

これと同時に発表されたAndroid Studio3.0から正式対応になるそうです。

Android Studio 3.0 Preview も公開されたのでちょっぴりですが早速試してみました!

ちなみに現行版のAndroid Studio 2.3でのKotlinの使い方についてはこちらをどうぞ。
[Kotlin de Android] 最初はやっぱりHello world !

以下、Mac OSでの手順や画像になります。基本的にはWindowsも同じだと思いますが、インストール手順などは公式サイトを参照してください。

Android Studio 3.0 Preview をインストールしよう

Android Studio 3.0 Preview は開発版でまだ正式版ではないのでご注意ください。
その辺をご理解できる人だけインストールしてください。

といっても、Android Studioは別のバージョンを共存できるので、現行の2.3もそのまま使うことが可能です。

Android Studio 3.0は
こちらのページ からダウンロードできます。

ダウンロードしたらZIPファイルを解凍して、appファイルをアプリケーションフォルダに移動してください。
これでインストール完了です。

Kotlinプロジェクトを作ろう

インストールしたAndroid Studio 3.0を起動しましょう。
起動時にいろいろ聞かれますが、いつもの質問なので適当にやり過ごしてください(笑)

Android Studio が起動するといつもどおりの Welcome画面が表示されるので、
「Start a new Android Studio project」 をクリックします。

プロジェクト作成画面が表示されます。

Kotlin Android Studio 3.0

ここの画面で重要なのは「Include Kotlin support」 にチェックを入れることです。
これを入れないとAndroid Studio2.3のときとほぼ同じ設定が必要になってきちゃいますので。
(一度これを入れずにやってがっかりした私…w)

Application name 等はお好みのものにして「Next」としましょう。

APIのバージョンですがここもお好みの設定やデフォルトでいいと思うので選択したら、「Next」しましょう。

Kotlin Android Studio 3.0

次はActivityの選択画面ですが、これもお好きなものでいいと思いますが、一番シンプルなEmptyActivityにしています

Kotlin Android Studio 3.0

最後にActivityとLayoutファイルの名前に設定です。
ここではデフォルトのままでいいでしょう。
「Finish」をクリックしましょう。

Kotlin Android Studio 3.0

しばらくすると、プロジェクトが立ち上がります。

Kotlin Android Studio 3.0

MainActivityを見てください!
すでにKotlinになっているんです!

Android Studio2.3まではJavaでプロジェクトが生成されるので、ここからKotlinに変換する必要があったり、設定を変えたり、ちょっと面倒だったのですが、Android Studio 3.0からはこれだけでOKです。

ちょっと感動。

Kotlin Extensionを使えるようにしよう

さて、ここまででもちろんそのままKotlinを書くこともできるのですが、KotlinをAndroid向けにもう少しだけ便利に書けるようにしたExtensionがあるので使えるようにしましょう。

これは設定画面からどうにかできるものでもないようで、build.gradleに手動で追加する必要があります。

では、build.gradle(Module:app) を開きましょう。

冒頭にpluginの設定がいくつか書かれていますが、その最後の一行を追加してください。

これで拡張機能が使えるようになります。
拡張機能いいところは、findViewById をする必要がなくなる、というものですね。
使用例は冒頭で紹介したAndroid Studio2.3の記事を見てください…(汗)

そんなこんなでほぼ自動でKotlinのプロジェクトが作れるようになって便利になりそうですね!
これを機にKotlinが流行っていくといいな〜と勝手に思っています。