CSSにコメントを書く場合は/** こんな感じ */
でコメントを書く。
2023年4月5日水曜日
2023年4月3日月曜日
CSS 親要素を基準に位置を決めたい
親の領域を基準に特定の要素の位置を決める、AndroidでいうところのRelativeLayout
な位置調整をしたかったので実装方法を調べた。
親のスタイルに対して以下を設定する
position:relative
位置を決めたい要素のスタイルに対して以下を設定する
position:absolute
上記を設定したら、あとは特定の要素に対してleft
,top
,right
,bottom
を指定すればOK。特にやりたかった右下を指定する場合は以下。
right:0
bottom:0
参考
2023年2月17日金曜日
SQL テーブルを内部/外部結合するSQL文を解説
アプリの中でデータベースを実装するとき、いくつかのテーブルを結合させてまとめて情報取得したい機会が多く出てきます。テーブルの結合にはいくつか種類がありますが、使用頻度が多いのは、内部/外部結合でしょうか。
今回は、頑張ってテーブルを設計していい感じに正規化したけど、いざ必要なデータを取ろうとしたときに内部結合/外部結合どう書けばいいんだっけ...という時のために、それぞれの書き方を備忘録として説明します。
内部結合の場合
SELECT * FROM table_a INNER JOIN table_b ON table_a.id = table_b.id
内部結合は、結合する際に結合条件に合致するもののみ一覧として出力される結合方法です。本当に必要なものだけ取得したい、という場合はこちらになると思います。
外部結合の場合
SELECT * FROM table_a LEFT JOIN table_b ON table_a.id = table_b.id
内部結合は合致するもののみ出力してくれる一方で、外部結合は結合する際に結合条件に合致しないものもNULL
として出力してくれる結合方法です。すべての項目を一覧として表示したいなどはこちらになると思います。結合には上記の左外部結合(LEFT OUTER JOIN)だけでなく右外部結合(RIGHT OUTER JOIN)もありますが、今回は省略します。(もしくは追記します。)
2022年12月19日月曜日
2022年の振り返りと2023年への抱負
どうも。どっことです。
気がつけば2022年ももうすぐ終わりということで、開発者としての2022年の振り返りと来たる2023年への抱負なんて書かせてもらえればと思います。
2022年の振り返り
SimpleBookmarkについて
夏頃まではちょいちょい更新しました。しかし、これ以上の機能追加は利用者に対しての労力に見合わないなと思ったので、2022年の目標としていた大型アップデートはお蔵入りとなりました。また、今後もアップデートが入るか微妙です。
新規アプリ開発について
2022年の目標としてSimpleBookmarkに続いてさらに新しいアプリを公開することが目標となっていましたが、実現することができませんでした。アイディアはじゃんじゃか出てくるのですが、それを実現するための時間とエネルギーが全くもって足りませんでした。
技術ブログの更新
定期的に、とはいきませんでしたがAndroidやFlutterを中心に備忘録として技術ブログを更新しました。同じことを調べることが多いので、できる限り自分のブログにノウハウを集約させたいですね。
あとはDroidKaigiの登壇を視聴したときのメモ書きもブログページに載せました。DroidKaigiは毎年開催されるので、次回も気になるものは視聴+投稿しようと思います。本当はオフラインで参加してみたいんですけどね。
その他
GitHubPage上で、Flutter for web によるウェブページを構築しました。
Flutter for web によるUIは非常にネイティブ感の強いUIで、普通のウェブページとは一味違った印象を持てる反面「なんとなくコレジャナイ感...」を感じることになりました。もともとはFlutterで良さげなものを作ってみようというところから始めたので当初の目的は達成できたものの、ウェブサイトを作るならやっぱりReactのほうが良いのかなと思いました。
2023年への抱負
ReactによるGitHubPageの更新
GitHubPageをさらにリニューアルしようと思います。Flutterとは毛色が全然違いますが、アーキテクチャを意識した設計がしやすそうですし、また別の面白さを得られればと思います。
新規アプリ開発
...2023年こそね。まずは自分が一番の利用者として使いたいアプリを作れればと思います。
2022年8月28日日曜日
ShellScript 引数を参照する実装について解説
どうも。どっことです。今回はシェルスクリプトの引数を参照する実装について解説します。
手作業が面倒なものをスクリプトで自動化して、ゆくゆくは「自分はボタンを押すだけ」なんて野望は誰しもが持つかと思いますが、まずはその第一歩(笑)として、シェルスクリプトの引数を参照してみましょう。
引数を参照する方法について解説
さっそくサンプルを載せます。 $(数字)
の形でアクセスすることで、スクリプト名から各引数の値や文字列にアクセスすることができます。また、$#
とすることで、引数の個数を取得することもできます。
#! /bin/bash
#スクリプト名を表示
echo "script=" $0
#引数の個数を表示
echo "args=" $#
#1つ目の引数を表示
echo "argv[0]=" $1
#2つ目の引数を表示
echo "argv[1]=" $2
#渡された引数すべてを表示
echo "argv[]=" $@
わかってしまえば、簡単ですね。
2022年8月23日火曜日
Android seletorにcolorを設定するときの注意点
android:textColorに設定する場合は以下。
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="#aaa" />
<item android:state_selected="false" android:color="@android:color/transparent" />
</selector>
一方で android:background に設定する場合は以下。
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" >
<color android:color="#aaa" />
</item>
<item android:state_selected="false">
<color android:color="@android:color/transparent" />
</item>
</selector>
参考
Android TextViewの一部にだけリンクをつけたい時の実装方法を解説
どうも。どっことです。今回はTextView
の一部にだけ、外部リンクを表示したい時の実装方法を解説します。
TextViewのテキストの一部にリンクをつける
例えばお知らせの記事にある「詳しい内容はこちら」のこちらだけ別ページへのリンクにしたいとき、TextView
を横並びにすれば実現できますが、そのテキストが二行以上になったり、他のテキスト間に含まれた箇所にあるとこの方法では実現できません。これを解決する実装方法を2種類解説していきたいと思います。
実装方法
外部のWebページに遷移する場合であれば簡単です。以下の2種類を解説していきます。
-
TextView
のautoLink
にweb
を設定する方法 HtmlCompat.fromHtml
を利用する方法
TextViewのautoLink属性にwebを設定する方法
TextView
を配置しているレイアウトXML内で、autoLink="web"
を設定するだけです。仕込むリンクが単純なURLであれば、それをテキストとして設定するだけでそれっぽい表示になります。
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="https://www.google.co.jp/ とテキストを仕込むとGoogleページのリンクになります。"
android:autoLink="web"
/>
実際に表示した時のイメージは以下です。https://...のURL部分がリンクになっていると思います。タップするとURLのページに遷移します。
HtmlCompat.fromHtmlを利用する方法
こちらは上記の例で挙げたような「こちら」という文言をリンクにする方法です。AndroidにはSpan
というクラスがあります。HTMLを使ってホームページを作ったことがある方ならspan
というタグを使うことも頻繁にあると思いますが、Androidでもこの概念を使ってテキストの一部を装飾することができます。こちらを使って外部リンクをつけます。
HtmlCompat.fromHtml
に、HTMLのテキストを渡すとWebページのようにテキストを表示してくれるSpanned
を生成してくれるので、これを表示したいTextView
に設定してください。
val textView = findViewById(R.id.text_view)
val span = HtmlCompat.fromHtml("詳しい内容は<a href='url'>こちら</a>")
textView.setText(span)
textView.movementMethod = LinkMovementMethod()
実際に表示した時のイメージは以下です。こちらの部分がリンクになっていると思います。タップするとurlで指定したページに遷移します。
まとめ
今回はテキストの一部にだけリンクをつけたい時の実装方法について解説しました。実際に使うケースはかなり限定的になりますが、こういったポイントをおさえることで、アプリ全体の見栄えを良くしていければ嬉しいですね。
参考
2022年8月20日土曜日
Android deprecatedとされたsetTargetFragmentを推奨先に変える方法を解説
どうも。どっことです。今回はdeprecatedとなっているFragment#setTargetFragment
の移行対応について解説します。
setTargetFragmentの移行対応について
複数のFragment
を使って画面遷移を実装するとき、遷移先の画面で決めたことを遷移元の画面に教えてあげたいときがあります。たとえば
- 設定画面で設定の要素をタップしたらそれに関する設定値の一覧が表示される。
- ユーザは一覧から設定項目を選択する。
- 選択した値を設定画面に返してあげて、設定画面にはユーザが選択したものを最新の設定値として表示する。
などですね。
これまではFragment
間のデータのやりとりはtargetFragment
を使うことで実現できました。呼び出し元のFragment
を遷移先から参照できるようにして、その参照から呼び出しもとにデータを返してあげる。という具合です。
さて、「これまでは」と書いた通り、このメソッドdeprecated(非推奨)になってしまいました。これの扱いが簡単だったので個人的に非常にありがたかったのですが、Google様のお達しなので、今後は推奨されるやり方で実装する必要があります。今回は備忘録も含め、新しい実装方法を載せたいと思います。
解説
以下の順に解説していきます。
- 呼び出される側の実装
- 呼び出す側の実装
Activity
→Fragment
の場合Fragment
→Fragment
の場合
呼び出される側の実装
parentFragmentManager.setFragmentResult("request_key", Bundle())
呼び出される側の実装はシンプルで、(自身を管理している)parentFragmentManager
に渡したいデータを設定します。
通知したい情報をBundle
に詰める必要があるため、上記の例は必要最低限のスニペットです。
呼び出す側の実装
Activity -> Fragment の場合
supportFragmentManager.setFragmentResultListener("request_key", this) { _, result ->
// result を参照して結果を処理する
}
呼び出すFragment
はActivity
が持っているsupportFragmentManager
が管理しているので、それに対してResultListener
をセットしてあげます。Activity
がDialogFragment
を表示するときは上記の実装になります。
Fragment -> Fragment の場合
childFragmentManager.setFragmentResultListener("request_key", this) { _, result ->
// result を参照して結果を処理する
}
一方で Fragment
-> Fragment
の場合はちょっとだけ注意が必要です。呼び出すFragment
を呼び出し元のFragment
が持つFragmentManager
管理している場合、こちらの実装パターンが利用できます。例えばFragment
が、自身が持っているchildFragmentManager
を使ってDialogFragment
を表示するなどの場合は、こちらの実装が使えます。
ただし、表示するDialogFragent
をActivity
が持っているsupportFragmentManager
が表示する場合、このパターンではなく
Activity
->
Fragment
のパターンで実装することになります。表示するDialogFragment
をどのFragmentManager
が管理するかが違うためです。
まとめ
今回はdeprecatedとなっているFragment#setTargetFragment
の移行について解説しました。開発期間が長いアプリケーションでは、まだまだsetTargetFragment
でFragment
間での結果のやり取りを処理しているものも多いのではないでしょうか。deprecatedとなっているメソッドのため、なるべく早めに解消しておきたいですね。
Kotlin Collectionsをシャッフルするときの実装について解説
どうも。どっことです。今回はKotlinによる実装で、Collections
派生の要素をシャッフルする実装について解説します。
Collectionsの要素をシャッフルする時の実装
Javaでいう所の以下のメソッドのことです。
Collections.shuffle(List)
Kotlinでは、以下のように実装します。
// シャッフル対象となるList
var mutableList = mutableListOf<Any>()
Collections.shuffle(mutableList)
ポイントはシャッフルするCollectionsがMutable
である点です。
Kotlinでは同じCollectionsでも、要素を加工できるMutable
という概念があります。要素が加工できるCollectionsは、クラス名の接頭語にMutable
が付与されています(MutableList
, MutableHashMap
など)。逆に要素を加工できないものはMutable
が付与されていません。そのため、Kotlinに慣れていないJavaユーザがいざListなどのインスタンスを作っても「要素の追加や削除ができない...」といったトラブルが発生しがちです。
上記の経緯から、シャッフル対象のCollectionsはMutable
にする必要があります。という話でした。
まとめ
今回はCollections派生の要素をシャッフルする実装について解説しました。JavaユーザがKotlinに移行するときのすごくよくあるハマりポイントだと思うので、ぜひ参考にしてくださいね。
2022年8月13日土曜日
Android deprecatedとなったstartActivityForResult()の修正方法を解説
どうも。どっことです。今回は、deprecatedとなってしまったActivity#startActivityForResult()
の修正方法について解説します。
deprecatedとなったstartActivityForResult()の対応
一昔前のAndroidアプリ開発であればActivity#startActivityForResult()
による画面間のデータやり取りは鉄板中の鉄板として解説されていたネタですが、残念なことにこのメソッドがdeprecatedとなってしまいました。初級者でも使い勝手がよい背景から、さまざまなプロジェクトで使用されていたこのメソッドですが、いざdeprecatedとなっても修正できず困っている人も多いと思います。今回は、実は簡単にできるstartActivityForResult()
の修正方法について解説します。
修正方法
修正方法は以下の手順です。
-
registerForActivityResult()
でlauncher
を用意する。 Activity
が終了したときの結果をここで実装しておく。Activity
を起動するためのIntent
を生成する。-
launcher
を使ってIntent
をlaunch
する。
registerForActivityResult() でlauncherを用意する
Activity
に新しく用意されているregisterForActivityResult()
を使って、launcher
を用意します。この時に、Activity
から渡される結果を制御するための処理を実装しておきます。
val launcher = registerForActivityResult(StartActivityForResult()) { result ->
// onActivityResultに対応するコールバック
if (result.resultCode != Activity.RESULT_OK) {
// Activity.RESULT_OK 以外
return@registerForActivityResult
}
// RESULT_OK時の処理
// setResultで設定したintentから値を取得する
val value = result.data.getStringExtra(key)
// 取得した値を良しなにする
}
Activityを起動するためのIntentを生成する
ここまで実装すれば、あとはstartActivityForResult()
の時と同じです。Intent
を作成します。
val intent = Intent(applicationContext, NextActivity::class.java)
launcherを使ってIntentをlaunchする
作成したintent
をlauncher
でlaunch
してあげれば、修正できます。
launcher.launch(intent)
まとめ
今回はActivity#startActivityForResult
のdeprecated解消方法について解説しました。いまだにstartActivityForResult
を使っている開発者も少なからずいるかと思いますので、どんどん新しい機能を使えるよう情報をアップデートしていきたいですね。
参考
移行予定
どうも。どっことです。 タイトルの通りですが、諸事情により GitHubPage に移行予定です。 https://mkt120.github.io/ この備忘録に記載の内容を転記しつつ、今後はこちらのページを更新していく予定です。
-
どうも。どっことです。今回はGridLayoutの使い方について解説します。 GridLayout Androidのレイアウトを実装するとき、LinearLayoutやConstraintLayoutをよく利用しますが、Viewを格子状に配置する時は GridLayou...
-
どうも。どっことです。今回は zxing を使ってみたので紹介します。 zxingを使ってQRコード/バーコードリーダーを実装する 一時期流行りましたよね。バーコードとか、 QRコードとか読み取って、いい感じになにかやること。ネイティブアプリで。そんな時...
-
経緯 カスタムViewを作ったけど、ダークモードのことをまったく気にしなかったせいで、カスタムViewの背景が真っ白になってしまった。 思い values-night フォルダを用意して colors.xml を入れるのもいいけど、そこまでしなくても標準の設定で...