駆け出しエンジニアぱかぱかの成長記録

引くほど忘れっぽい新卒2年目駆け出しSEぱかぱかの備忘録です。

【Android】リストビューのカスタマイズ

どうも、月曜日仕事終わりのぱかぱかです!
週末に取り組んでいた内容の記事投稿が月曜になってしまいました。

 

先週末はなかなか良い時間の過ごし方をできたように思います。

土曜日は謎に朝4時に目覚めてアプリのお勉強をした後

お友達とカフェに行ったり、部活の後輩とご飯を食べたりして過ごしました。

日曜日は昼までぐっすり寝た後、美味しいランチを食べ

カラオケで勉強した後ちょっと歌って、夜は居酒屋でしこたま飲みました。

 

毎週こんな感じで過ごせたらいいですね😳

 

さて今日まとめるのは、先日の記事でも取り組んでいたリストビューの応用編です!

こちらは懐かしきブログ開設1日目の記事です。

radish-se.hatenablog.com

前回の記事ではリストとリストビューを紐づけるアダプタとして

以下の中からArrayAdapterを使用していました。

 

◆アダプタオブジェクトの種類

ArrayAdapter

 元データとしてArrayもしくはMutableListを利用

SimpleAdapter

 元データとしてMutableList<MutableMap<String, *>>を利用

SimpleCursorAdapter

 元データとしてCursorオブジェクトを利用

 

今回はSimpleAdapterを使用してリストビューを作成していきます!

手順はArrayAdapterとほとんど同じですが

MutableList<Mutable<String, *>>を元データとして使っていくので

1行にいくつかの情報を持たせられ、より柔軟性が高くなります。

 

前回は以下のような1行のリストを作成しました。

とてもシンプルですね。

前回作成した1行のリストビュー

 

今回はSimpleAdapterの強みを活かして2行以上のリストを作ってみたいと思います!

よくいる鳥ばかりの発見した鳥リスト

前回のリストビューでは「見たい鳥リスト」を作成しましたが

今回は「発見した鳥リスト」を作成してみたいと思います。

発見した時の情報として発見日時や発見場所もリストに表示されるようにします。

それでは作り方を見ていきましょう!

 

①リストビュー各行のレイアウトファイルを作成

リストビューをカスタマイズするために

まずは各行のレイアウトファイルを作成します。

今回は以下のようにLinearLayoutを組み合わせた構成で作成しています。

リスト1行のレイアウト構成

自分で作ったレイアウトを使えるなら

可能性は無限大ですね…!

 

②発見した鳥リストを生成

今回はSimpleAdapterを使うので

MutableList<MutableMap<String, *>>でデータを作成していきます。

まだDBなどと連携できているわけではないので

手動で以下のようにMutableMapをMutableListに地道に追加してあげますよ…

鳥の名前(birdName)と発見日時(date)と発見場所(place)の

3つの情報を持ったMapにしてみます。

val watchBirdList: MutableList<MutableMap<String, Any>> = mutableListOf()
var watchBird = mutableMapOf<String, Any>("birdName" to "スズメ", "date" to "2023/4/9", "place" to "近所の公園")
watchBirdList.add(watchBird)

 

この"birdName" to "スズメ"という書き方は正直初見なんですよね。

KotlinのMutableMap特有の書き方っぽいです。

なんかわかりやすいですね。

 

③アダプタオブジェクトを作成

SimpleAdapterはインスタンスを生成する際に引数が5個必要になります。

// 上で引数の中身を宣言しておく
private var
_birdList: MutableList<MutableMap<String, Any>> = mutableListOf()
private val _from = arrayOf("birdName", "place", "date")
private val _to = intArrayOf(R.id.tvBirdNameRow, R.id.tvBirdWatchPlaceRow, R.id.tvWatchDateRow)

// onCreateの中でインスタンス生成
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_watch_bird_list)
_birdList =createWatchBirdList()
val lvWatchBirdList = findViewById<ListView>(R.id.lvWatchBirdList)
val adapter = SimpleAdapter(this@WatchBirdListActivity, _birdList, R.layout.row, _from, _to)
lvWatchBirdList.adapter = adapter
lvWatchBirdList.onItemClickListener = ListItemClickListener()
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}

・context: Context 

 表示させたいアクティビティオブジェクト(コンテキスト)

・data: MutableList<MutableMap<String, *>>

 リストデータそのもの

・resource: Int

 リストビューの各行のレイアウトを表すR値

・from: Array<String>

 MutableMapのキー名配列

・to: IntArray

 MutableMapのキー名に対してデータを割り当てられる画面部品のR値配列

 

引数が多いとウッってなっちゃいます…

でも落ち着いてみると、どの画面にどういうデータを

どんなレイアウトに当てはめて表示するかを指定しているだけですね。

配列で持てるので、たくさんの情報を紐づけられそうですが

実務ではそういう使い方してるのか気になります…

他にもやり方ありそうな気がしますね。

 

最後に生成したアダプタオブジェクトを

ListViewのadapterプロパティにセットしてあげたら

生成したデータを持ったリストビューの完成です。

lvWatchBirdList.adapter = adapter

 

この発見した鳥リストのセルをタップしたら

発見した鳥の詳細画面に行けるようにしたいのですが

続きはまた今度ということで!

 

お付き合いいただきありがとうございました😊

【Android】Androidの画面遷移

とってもお久しぶりです…

気づいたら前回の投稿から15日以上経ってしまいました😇

投稿していない期間ですが、ほとんど遊びで多忙な日々を送っておりまして…

東京・横浜旅行に出かけたり飲み会に盛んに参加したりしておりました…🍻

(いつか旅行した時の記事も書きたいような)

 

勉強しなきゃという気持ちはあれど、帰宅すると眠気が圧勝する毎日…

家に帰ってしまえば終わりということで、今日はモスバーガーに来ています。

とろったまチーズ テリヤキバーガー

期間限定メニューのとろったまチーズテリヤキバーガーを注文。

その名の通り卵がとろとろでとっても美味しいのでおすすめです🍔

左の枝豆コーンフライというものも初めて食べたのですが

これまたリピート確定のおいしさでしたよ🌽

 

 

言い訳タイムはさておいて、本題に入っていきます。

本日はAndroidの画面遷移について学んだことをまとめていきます!

 

画面遷移とIntentクラス

画面遷移なんて基本中の基本のような気がしますが

業務ではある程度出来上がったプロジェクトをいじることしかしていないので

画面遷移自体を作ることってまだ経験がありませんでしたし

行っている処理も正直まだ見かけたことがありませんでした…😳

 

お試しで作っている「野鳥コレクション」アプリの雑なトップ画面から

見たい鳥リスト画面に遷移してみましょう。

雑なトップ画面

①Intentクラスを生成

画面遷移にはIntentクラスというものを使うようです。

このクラスは画面すなわちアクティビティの起動を司っています。

 

まずは「見たい鳥リストへ」ボタンのonClickListnerにIntentクラスを生成します。

 

◆Intentのインスタンス生成

以下の2つの引数を渡してインスタンスを生成します。

val intentWantList = Intent(this@TopPage, WantBirdList::class.java)

・packageContext: Context

もう自分の中でお馴染みになってきたコンテキストです。

表示させたいアクティビティオブジェクトを指します。

今回はTopPageを指定します。

 

・cls:Class

ここでは起動するアクティビティをJavaクラス化したものを渡します。

KotlinのクラスをJavaクラス化するにはクラス名::class.javaと記述するそうです。

Javaクラスを渡すのがIntentの仕様のようですね。

 

②アクティビティを起動する

Intentクラスで遷移先が指定できたら後は簡単。

ActivityクラスのstartActivity()メソッドにIntentオブジェクトを渡すだけです。

startActivity(intentWantList)

 

これでボタンを押した際に画面遷移が行われるようになりました。

見たい鳥リストに遷移

 

遷移先の画面に遷移前のデータを引き継ぐこともできるようですが

今回の遷移では渡したいデータもなかったので一旦これにて終了とします。

ちょっとずつアプリらしくなってきましたね。

 

悲しいことにテザリングしているiPhoneの充電がピンチなので

今日はこれにてモスバーガーを退散したいと思います。

家に帰ってから自分は果たしてこの続きをやるのでしょうか…

乞うご期待です🥹

 

次回の投稿は日が空きすぎないよう頑張ります!😅
お付き合いいただきありがとうございました!

【Android】ダイアログ入門

どうも、仕事終わりのぱかぱかです!

今配属されているプロジェクトがまあまあ忙しめで

20時や21時まで帰れないことがほとんどなのですが

今日は定時退社決められました😉

明日お休みということもあり、今日有給とっている人が多いんですよね。

今のプロジェクトは木→水の1週間スクラムアジャイル開発をやっています。

水曜日のスプリントレビューに向けて今日1日足掻いても

できることは限られているというわけで、戦略的退社です笑

春分の日ありがとう。

 

本日はダイアログについて学んだことをメモしていきたいと思います!

ちょうど今日業務で処理中を示すダイアログ表示中にエラーが発生した場合に

エラーのダイアログが表示されないというバグを解消してきたところだったので

めっちゃタイムリーでした。

 

ダイアログって何?

ユーザーによる意思決定や追加情報の入力を求める小さなウィンドウのこと。

ダイアログ  |  Android デベロッパー  |  Android Developers

 

ユーザーの対応を求めるものなので

必ずコンテンツエリアとアクションボタンを持ちます。

 

お試しで作っている「発見した野鳥を記録するアプリ」では

以下のような感じで使ってみました。

ユーザーによる意思決定として、タップした野鳥を

見たい鳥に登録するかキャンセルするかが選べます。

それではダイアログの作り方を順を追ってみていきます。

リストビューの鳥をタップしたときに表示されるダイアログ

①ダイアログ生成クラスを作成

ダイアログを表示するにはまず、DialogFragmentを継承したクラスを作成します。

様々なアクティビティから使われることを想定して

privateなメンバクラスではなくトップレベルクラスで作るのが良いそうです。

(私の業務のプロジェクトではそうなってなかったな…)

 

②ダイアログ生成処理を記述


class
FavoriteConfirmDialogFragment: DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
// アクティビティがnullでないならばダイアログオブジェクトを生成。
val dialog = activity?.let {
val builder = AlertDialog.Builder(it)
// ダイアログのタイトルを設定。
builder.setTitle(R.string.dialog_title)
// ダイアログのメッセージを登録。
builder.setMessage(R.string.dialog_message)
// Positive Buttonを設定。
builder.setPositiveButton(R.string.dialog_btn_ok, DialogButtonClickListner())
// Negative Buttonを設定。
builder.setNegativeButton(R.string.dialog_btn_ng, DialogButtonClickListner())
// ダイアログオブジェクトを生成。
builder.create()
}
// 生成したダイアログオブジェクトをリターン
return dialog ?: throw java.lang.IllegalStateException("アクティビティがnullです")
}

 

onCreateDialog()メソッドをオーバーライドしてダイアログ生成処理を記述します。

Androidでダイアログを表すクラスはAlertDialogクラスですが

このダイアログオブジェクトはビルダーを用いて生成します。

まずAlertDialog.Builderオブジェクトを生成し、

呼び出し元を表すactivityというプロパティを引数に渡します。

 

activityはNullableプロパティなので

nullチェックとしてセーフコール演算子(?.)let関数を使っています。

val dialog = activity?.let {}

こういうのはKotlinで初めて出会う書き方です…

慣れたら便利なのでしょうね…

let関数はなんらかの変数に対する処理を拡張関数としてまとめて記述する

スコープ関数というものの一種らしいですが、まだletしか出会ったことないです。

 

ビルダーオブジェクトが生成できたら

そこにどんどん表示の設定を行なっていきます。

これはわかりやすいですね。

ボタンに関しては第2引数にボタンタップ時のリスナクラスインスタンスを渡します。

 

// ダイアログのタイトルを設定。
builder.setTitle(R.string.dialog_title)

// ダイアログのメッセージを登録。
builder.setMessage(R.string.dialog_message)

// Positive Buttonを設定。
builder.setPositiveButton(R.string.dialog_btn_ok, DialogButtonClickListner())

// Negative Buttonを設定。
builder.setNegativeButton(R.string.dialog_btn_ng, DialogButtonClickListner())

 

create()メソッドでダイアログオブジェクトが生成され

これがlet関数の戻り値となるので変数dialogに格納されます。

// ダイアログオブジェクトを生成。
builder.create()

 

最後にdialogをonCreateDialog()メソッドの戻り値としてリターンしてあげます。

return dialog ?: throw java.lang.IllegalStateException("アクティビティがnullです")

 

ここでもまた見慣れないエルビス演算子(?:)というのがでてきました。

nullの場合の処理を:以降に書くことができるんですね。

これも実務で見たことがあります。普通に便利じゃん…

 

③ダイアログのボタンタップ処理を記述

// ダイアログのアクションボタンがタップされた時の処理が記述されたメンバクラス。
private inner class DialogButtonClickListner: DialogInterface.OnClickListener {
override fun onClick(dialog: DialogInterface, which: Int){
// トーストメッセージ用文字列を用意。
var msg = ""
// タップされたアクションボタンで分岐。
when(which) {
DialogInterface.BUTTON_POSITIVE ->
msg = getString(R.string.dialog_ok_toast)
DialogInterface.BUTTON_NEGATIVE ->
msg = getString(R.string.dialog_ng_toast)
}
Toast.makeText(activity, msg, Toast.LENGTH_LONG).show()
}
}

ダイアログのタップに対するリスナクラスは

OnClickListnerインターフェースを実装しonClick()メソッドに処理を記述します。

この時onClick()メソッドの第2引数に渡されるwhichを利用して

処理を分岐させるのが効率良いようです。

DialogInterfaceに定数が用意されているので便利です。

今回はボタンタップ時にトーストを表示する処理を書いています。

 

ひとまずこれで、ダイアログが完成しました。

 

 

ダイアログは意外と思っていたよりなんだかごちゃごちゃしていました…

でも、書いてみると頭の中が整理されて良い感じです。

他の方が見てわかりやすいかは別ですが…

 

今日はこれくらいで終わりにしたいと思います。

明日はお休みなので、美容室に行ってカフェでお勉強でもしようかな?

それでは、ここまで読んでくださりありがとうございました。

【Android】リストビュー入門

どうも、ぱかぱかです!

ブログ開設1日目、自己紹介に続き2記事目の投稿となります!
果たしてこのブログ、どれくらい続けられるんでしょうか…

以前もほぼ日記のようなブログをやっていた時期がありましたが

その時は約1年くらいで投稿をやめてしまいました…

今回は技術向上という永遠のテーマがお供なので

もっと続けられるといいな〜😌

サボり始めたら一喝お願いしたいところですね😶

まだ記事数少なく自己紹介成分多めですが、お付き合いください🙇🏻‍♀️

2023年の1月からモバイルアプリ開発のプロジェクトに配属となり

もうすぐ3ヶ月が経とうとしております。

やってみた感想、アプリ開発おもろ?って感じです。


前のプロジェクトではJavaのWebアプリケーション開発案件に半年くらいいましたが

プロジェクト状況が忙しすぎて新人の私が律速段階になることが許されず

コーディングというよりはテストメインの業務をやっておりました。

コードを探ることはあっても書く機会はそこまで多くない…

 

一方で今ではコードをいじってなんぼな案件に入ることができました!

自分でコードを直してそれによってアプリの動きが変わるというのを

毎日この目で見ることができるので、些細な修正でもやりがいを感じます🥹

しかも一般の方が使うようなアプリなので、エンドユーザーをイメージしやすい…

友達もそのアプリ使ってるよ〜!と言ってて嬉しくなりました。

前置きが長くなりましたが

モバイル開発という全く新たな分野に配属されたということで

ひとまず以下の本を買って勉強を進めているというのが今の状況です。

この業界も技術書が多すぎてどれ選べばいいのか困っちゃうのですが

おすすめ本として紹介されてたのでこれを選んでみました。

(リンク貼ってみて気づきましたが、もう第3版が出ているんですね…悲しい…

 私が1月に書店で購入した時は第2版でした…😔
 ちょっと見なかったことにします…)

 

購入してからもう2ヶ月くらい経ったわけなのですが

全17章あるうちまだ第5章までしか進んでません😰

業務後や休日にやろうという気持ちだけはあるのですが

どうしても寝落ちしちゃうんですよね…意思弱い…

そんな自分を律するためにブログ始めたみたいな節もあります。

 

本日は「第5章 リストビューとダイアログ」のうち

リストビューについてメモしておきます。

サンプルとして、自分のお試しで作ろうとしている

「発見した野鳥を記録するアプリ」のキャプチャを載せておきます🐥

 

リストビューって何?

・情報をリスト形式で表示できる。

・データ数が多い場合、スクロールできるようになる。

私が見たらテンション上がりそうな野鳥のListView

リストビューが使われてないアプリって少ないのでは?

ってくらい一般的なビューですね。

私が業務で開発しているアプリにもやっぱり使われています。

 

アダプタオブジェクトでデータを管理

リストに表示したい情報は可変なことがほとんどだと思います。

(見たらテンション上がりそうな野鳥も私の中で変動していくかもしれない…?)

その場合はアクティビティ中でリストデータを生成する方法をとる必要があります。

 

本の手順に倣ってまず、以下のようにデータとして

MainActivityのonCreate()メソッド内にmutableListを作ります。

(コードにベタ打ちしている時点で可変とは言わないと思いますが…)

 

val birdsList = mutableListOf("シマエナガ", "シジュウカラ", "アカゲラ", "カワセミ", "オオルリ", "キビタキ", "マミチャジナイ", "ハクセキレイ", "カケス", "イソヒヨドリ", "ムクドリ", "センダイムシクイ", "ルリビタキ", "ブッポウソウ", "ベニマシコ", "シメ")

あとKotlin初心者なのでMutableListってそもそもなんだ?ってなってしまったのですが

どうやらJavaArrayListと同じと考えて良いみたいですね。

 

このリストとリストビューを紐づけるのがアダプタオブジェクトです。

アダプタオブジェクトには以下のようにいくつか種類があります。

 

◆アダプタオブジェクトの種類

ArrayAdapter

 元データとしてArrayもしくはMutableListを利用

SimpleAdapter

 元データとしてMutableList<MutableMap<String, *>>を利用

SimpleCursorAdapter

 元データとしてCursorオブジェクトを利用

 

今回は野鳥の名前データをMutableListで生成したので、ArrayAdapterを使用します。

SimpleAdapterを使用する例も次章で登場する模様。

ArrayAdapterのインスタンスは以下のように生成します。

 

◆ArrayAdapterのインスタンス生成

以下の3つの引数を足してインスタンスを生成します。

ArrayAdapter(this@MainActivity, android.R.layout.simple_list_item_1, birdsList)

context: Context

 表示させたいアクティビティオブジェクト(コンテキスト)

resource: Int

 リストビューの各行のレイアウトを表すR値

 今回は1行表示なのでandroid.R.layout.simple_list_item1を使用

objects: MutableList<T>

 リストデータそのもの

 

ここで出てくるコンテキストというワードもアプリ開発で初めて出会いました。

調べてみてもなかなか掴みきれていないのですが

アプリに関する様々な要素を紐づけるために渡すもの

というざっくり理解に落ち着きました…

(わかりやすい説明があれば助言をお願いいたします…)

今回はthisで自分自身のインスタンスを指定して

表示させたいアクティビティを紐づけているって感じでしょうか。

今回のように@MainActivityと明確に指定することで

インナークラスでthisを指定したときなどに

意図しないインスタンスを指定するといったことを防げるようですね。

 

最後に生成したアダプタオブジェクトを

ListViewのadapterプロパティにセットしてあげたら

生成したデータを持ったリストビューの完成です。

 

lvBirds.adapter =adapter

ここからリストの項目をタップした時のイベントとして

トーストやダイアログを表示するところまで学習したのですが

長くなりそうなのでまた別の記事にまとめることとします。

 

拙い内容でしたがお付き合いいただきありがとうございました🙇🏻‍♀️

【自己紹介】駆け出しエンジニアぱかぱか

はじめまして!

ぱかぱかと申します!🐴

 

2022年4月から右も左もわからぬまま未経験で地方のSIerに新卒入社😳

エンジニア歴がようやく1年になろうとしている駆け出しSEです。

今はモバイル開発のプロジェクトでAndroidiOSの両方触ってます。

使用言語はJava, Kotlin, Swiftです(Objective-Cはさっぱり…)

 

自分でも引くほど忘れっぽい性格なので

備忘録とモチベアップのためにブログを開設してみました!

業務でもエンジニアの方の残した記事に救われる場面が数え切れないほどあり

自分の他愛ないメモがいつか誰かの役に立てば…なんて思っています。

もしかしたら日記がてら、趣味の話とかも書いちゃうかも…

 

ひとまずSEを1年やってみての感想ですが

この業界入れて良かった!って心から思ってます!

大学までは全く別の分野の研究をしており

まさか自分がこのような業界に入るとは思ってもみませんでしたが

いざやってみると学んだ技術の汎用性の高さに驚き桃の木。(古い)

今までは特に何も考えず、流れに身を任せて生きてきたタイプなので

「自分のやりたいことがよくわからない」というのがある意味悩みだったのですが

これからどんなやりたいことができても

このスキルがあれば叶えられるじゃんと思っています。
(と言って結局やりたいこと考えるのを後回しにしている)

スキルの高い先輩方を見て、「つよつよエンジニアかっこいい…」と憧れを抱いたので

自分もつよつよになれるよう頑張っていきたいと思います!

よろしくお願いします!