20210414のAndroidに関する記事は3件です。

楽してAndroid/iOSアプリ個人開発

はじめに どうも、@nittannittanです。 趣味でAndroid/iOS/Webアプリを作成しているアニメオタクです。 今まではAndroid/iOSアプリはそれぞれJava, Kotlin, Objective-c, Swiftなどの言語でそれぞれ開発していました。 しかし、どちらか一方を開発して公開したあとにまた同じようなことを繰り返すのは勉強にはなりますが、仕事の合間にやる個人開発ではあまり楽ではないなーと感じていました。 そこで「最近マルチプラットフォームも流行ってきているようだし、そろそろ本腰を入れてみるかー」という軽い気持ちからFlutterでAndroid/iOSアプリを同時開発することにしました。 Flutterを選んだ理由 Googleが開発しているからまずAndroidは間違いなく相性は良いだろうし、個人開発でFirebaseを使わないわけがないので、Flutterを採用しました。WebアプリでReact使っているわけでもないし、iOS版に対応していなかった時代を知っているのでReact Nativeは今回はやめました。 ReactでWeb開発してたらReact Nativeを選んだのかもしれません。 参考にしたサイト まずはDartを知る必要があるため言語の公式ドキュメントをさらっと読みました。深くは読み込みません、私のやり方的に実際に手を動かして覚えるほうがやりやすくてわからなくなった時に再度読みます。手を動かさないとモチベーション維持も難しいですし、個人開発だとやる気が下がったらおしまいですからね。 ぱっとソースを見た時に全然わからないと投げ出しそうになったUIの構築方法も公式のドキュメントを見たらあっさり理解できました。慣れたらxmlやStoryboardでUIを作るのが面倒に思えてきます。特にStoryboardはgitでの差分確認がよっぽどの超人じゃないとできないですしね。 私が作ろうとしていたアプリはTODOアプリの作り方が参考にできそうだったので下記を見ながらベースを作りました。 利用パッケージの参考にしたのは下記。 最終的に利用したパッケージ pubspec.yaml dependencies: flutter: sdk: flutter cupertino_icons: ^1.0.0 # MVVMで作るのに利用 provider: ^4.3.3 # データベースにデータ保存するのに利用 moor: ^4.1.0 sqlite3_flutter_libs: # Also use the latest version. path_provider: path: # アイコンを表示するのに利用 flutter_icons: ^1.1.0 # ダイアログの見栄えを良くするのに利用 awesome_dialog: ^1.3.2 # アプリからブラウザを開くために利用 url_launcher: ^6.0.3 # 必要なアプリアイコンを自動生成するのに利用 flutter_launcher_icons: ^0.9.0 # スプラッシュ画面を自動生成するために利用 flutter_native_splash: ^1.1.5+1 # Firebase関連 firebase_core: ^1.0.2 firebase_analytics: ^7.1.1 firebase_crashlytics: ^1.0.0 firebase_auth: ^1.0.3 google_sign_in: ^5.0.1 # GoogleDriveにバックアップファイルを保存するのに利用 googleapis: ^2.0.0 楽したポイント moor AndroidとiOSで差が出やすかったデータベースへのデータ保存もパッケージを利用することで簡単に対応できました。何も悩まずにマルチプラットフォームでデータ保存が実現できたのは衝撃的でした。 awesome_dialog 参考サイトでも紹介されていたパッケージですが、こちらも少ない工数でダイアログの見栄えが劇的に良くなるのでおすすめです。 flutter_launcher_icons iOSアプリをApp Storeに公開したことがある人ならわかると思いますが、iOSアプリは用意しなければならないアプリアイコンの数がとても多いです。それを画像一つ用意するだけで自動設定できるのはまたまた衝撃的でした。Androidのアダプティブアイコンにも対応しているのでかゆいところに手が届きます。 flutter_native_splash このパッケージもスプラッシュ画面が画像一つで表示できるようにできるのでとても楽ができます。 開発したトラウマ解消アプリの紹介 トラウマ解消アプリは、ふとした瞬間にフラッシュバックするトラウマを認知行動療法によって解消するためのアプリです。 使い方は以下です。 まずは、トラウマがフラッシュバックした時にそのトラウマに名前をつけて保存しましょう。 フラッシュバックした時に詳細な情報まで記録できるとは限らないと思います。名前以外の詳細は時間があるときにゆっくり書き出しましょう。 トラウマに名前をつけたり、詳細を書き出すことによって客観的に考えを整理することができ決めつけでネガティブになっていたことに気がついたり、バランスがいい考え方ができるようになります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Jetpack Compose Beta Overviewの動画を見たのでまとめる

注意 本記事はYouTubeのAndroid Developersチャンネルにおいて投稿された動画である Jetpack Compose: Beta overviewについて、動画内で述べられていることと、一部筆者の主観が入っている記事となっております。 記事内で使用される画像は、Jetpack Compose: Beta overviewより引用させていただいております。(不都合等ありましたらコメントをお願いします) 動画を全範囲網羅している記事ではありません。 Jetpack Composeとは? 1. Modern, declarative UI tool kit Composeは、宣言的UIを可能にするUIツールキット。 宣言的UIとは? どのように見えるか(What)を記述し、どのように作るか(How)を記述しない 2. Built on Kotlin Kotlinで作られており、Composeの関数のような、直感的なAPIを構築するのに十分な表現力 3. Unbundled Composeは他のJetpackライブラリと同様にアンバンドルされています。 プロジェクトのペースで更新できるように、APIバージョン間で一貫した動作をする アンバンドルとは? Androidのプラットフォームに含まれておらず(unbundle)、ライブラリとして追加できる 4. Built for interop 相互運用(interop)を重視している 例えば、新規の画面から徐々にComposeに移行することができるみたいな 現在のJetpack Composeの状況 Jetpack Composeは現在Betaである(2021/04/15時点) APIの洗練と安定化に焦点を当てて開発中 Jetpack Composeの推しポイント ComposeはAndroidのUIをよりはやく・簡単に実装することができる なぜ、はやく・簡単に実装することができるのか? 宣言的とUIツールの2つに分解して説明していく まず宣言的について 従来のアプローチ(慣例的なアプローチ) 上の図の例は、入門書などに書かれている一般的な例。 XMLがあり、その状態を変更するために、findViewById()などをして、プロパティを設定する。 例えば、DBやネットワークから情報をActivity・Fragmentが受け取ったとき、その情報をもちいてUIを更新するなど。 この問題点はStateがXMLとFragment/Activityの両方に存在すること。 例えば、上図のTextViewのテキストをAPIの結果に応じて変化させる場合を考える。 XMLのレイアウトファイルにTextViewがあり、初期のテキストが設定されているとする そして、APIの結果として、文字列を受け取ったときにその情報を格納する変数をFragment・Activityに定義していたとする。 TextViewの状態、Fragment・Activityの状態の2つが存在する。 Fragment・Activity間の状態を、TextViewの状態に反映するには、setText()などを使用しなければいけない。 この手続き的な操作は、開発者の責任で行う必要があり、バグの原因となってしまう。 JetPack Composeのアプローチ 上図のようにStateとUIがあり、Stateは変化するもので、UIは普遍で変更されないもの。 状態が変化した際に、UI全体が再生成される(効率化のために実際には差分のみの再生成となる) 先ほどの例(TextViewのテキストをAPIの結果に応じて変化させる場合)について考えてみる。 状態はFragment・Activityで保持する1つのみとなり、状態としてTextViewに表示する文字列が入っている。 APIリクエストがあり、状態の変更を検知して、状態をもとにUIを再生成する。 何が良いのか? これにより、状態に応じて自動的にUIが変更されることになる。 例えば、先ほどの例でいうところの、setText()という手続きが不要になる。 結果として、手続きの記述漏れなどによるバグがなくなる。 コードレベルで確認していく! 上記コードの説明 文字列のリストを表示する単純なコンポーネント 関数は何も返さないが、UIをemitする messageの中身が空の場合は「No messsages」を、それ以外の場合はメッサージをテキストとして表示 関数が実行されたら、新しいUIが作成される これをRecomposingと呼ぶ。メッセージの状態が変わったら、UIが再生成される messageの変化をどう検知するのか? messageをLiveDataとする。 上記のコードの説明 ViewModelにおいて、messageをLiveDataで公開 ConverationViewmodel.kt // おそらくこんな感じ class ConversationViewModel: ViewModel() { private val _message = MutableLiveData("") val message: LiveData<String> = _message : LiveDataで新しいデータを検知するたびにMessageList(message)が呼ばれUIが再生成される 注意点 Composableはimmutableなので、参照を保持して、後で照会したり、内容を更新することはできない したがって、全ての情報をEmit時にパラメーターとして渡す必要がある しかしながら、コンポーネントが変化できないということを意味するわけではない すべてのメッセージを選択するチェックボックスを追加して、すべてのメッセージを選択できるようにしてみる。 上記のコードだと、チェックボックスをクリックしても視覚的には切り替わらない。(cheched = false)としているので。 なので、状態を更新して、チェックボックスをemitする必要がある どうするか? チェックするかどうかのローカルな状態を持たせる。 そして、CheckBox()のパラメータonCheckChangeにユーザがチェックしたときのコールバックを設定する。 このようにすることで、チェックボックスの状態であるselectAllがクリック時に更新され、チェックボックスへ視覚的な状態が反映される。 しかしこれだと、UIにロジックがあって気持ち悪い 下記のように、MessageList()のパラメータとして、ステートと更新のためのラムダを渡す。 Composeはどういうアーキテクチャが適しているか? 基本的には、Composeはどのようなアプリケーション・アーキテクチャにも対応できる。 特に一方向性のデータ・フローとの相性が良く、ViewModelが画面の状態のストリームを公開しているとき。 各コンポーネントはパラメーターとして状態を受け取り、データが更新された場合にのみUIを更新する。 1つのLiveDataを使用することで、状態を一元化でき、画面全体の状態についての理解が簡単になりエラーを減らせる。 宣言的についてのまとめ Composeを使用すると Single Source Of Truth(信頼できる唯一の情報源) の原則が守れる。 慣習的なアプローチでは、Fragment・Activityで保持している状態とViewが保持している状態の2つがあり、バグの原因となる可能性があった。 しかし、Composeを使用すると状態を一元管理することができる。 そして「状態に変化があったときに、自動でUIが変更される」という性質により、バグが生まれにくくなる。 UIツールについて ComposeはUIコンポーネントの豊富なツールキットを提供している。 機能やメリット Material Design ComponentとMaterial Themingのサポート Material Design Component Material Theming シンプルだがパワフルなレイアウトシステムを提供 例えば、RowというComposableは、LinearLayoutのorientationをhorizontalに指定したレイアウトとほぼ同等。 しかし、Viewシステムが異なり、ネストされたレイアウトをパフォーマンスの高いものにしてくれるメリットがある。 より複雑なレイアウトを表現するために、ConstraintLayoutも提供されている。 ただし、カスタムレイアウトを使う方が簡単。 アニメーションシステム UIに動きをつけることが、より使いやすく、非常にパワフルになっている。 MotionLayoutをComposeに導入する作業も行っている テスト Composeは、テストを容易にするために専用のテストシステムを提供する。 そして、Composablesを個別にテストするための簡単なAPIを提供する。 アニメーションのテストも書くことができる。 Kotlinで書かれている Kotlinの優れた言語機能のおかげで、シンプルで直感的なAPIとなっている。 例えばCoroutineを使用することによって、シンプルな非同期APIを作成できるようにしている。 Coroutineを使用して、タッチ検出がブロックされないように、新しいコルーチンで押された位置にアニメーションさせている。 具体例で確認していく! 下記レポジトリの中のJetchatというアプリで説明。 https://github.com/android/compose-samples レイアウトの説明 上記のレイアウトを作るには下記のことを行っている message(=表示するテキスト)、isFromMe(=自分からのメッセージがどうかのフラグ)をパラメータに持つComposableを作成 メッセージ全体を囲むCard Composableを作成 isFromMeに応じて、Themeから色を指定 実際にテキストを表示するためにText Composableを作成 Modifierパラメータ用いてpaddingを設定 開発・検証方法 @Previewアノテーションを用いてプレビュー用のComposableを作成する。 それをAndroid Studio上で確認することが可能 この後、細かい実装方法が紹介されているので割愛。 述べられている内容 ComposableのパラメータにModifierを渡して、再利用可能に Modifierでは、最大幅やテキストのAlignmentなどを指定 LazyColumnを使用してRecyclerViewのような効率的なスクロールの実装 など 興味ある方は、10:33〜12:59 推しポイントまとめ 宣言的なUIによって、Composeを使用するとSingle Source Of Truth(信頼できる唯一の情報源)の原則が守れる。 UIツールによって、レイアウトやアニメーションの実装が簡単になる。 -> 簡単に、はやく実装することができる まだまだ推しポイントはある 既存のViewシステムと共存できる Interoperability APIと呼ばれるものが用意されている : <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"> : <androidx.compose.ui.platform.ComposeView android:id="@+id/compose_view" android:layout_width="match_parent" android:layout_height="match_parent" /> : </LinearLayout> class ExampleFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { // Inflate the layout for this fragment return inflater.inflate( R.layout.fragment_example, container, false ).apply { findViewById<ComposeView>(R.id.compose_view).setContent { // In Compose world MaterialTheme { Text("Hello Compose!") } } } } } コードの引用: https://developer.android.google.cn/jetpack/compose/interop?hl=ja#interop-apis 他の主要なライブラリとの統合を提供 資料等 Composeの学習系 goo.gle/compose-pathway goo.gle/compose-samples goo.gle/compose-docs フィードバック等 goo.gle/compose-slack goo.gle/compose-feedback
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Material ComponentでToolbarのmenuにBadgeを表示させる

material-components 1.3.0 から Toolbar の menu に Badge を簡単に表示できるようになりました。 実装 val badge = BadgeDrawable.create(requireContext()) BadgeUtils.attachBadgeDrawable(badge, toolbar, R.id.action_info) material-components にある BadgeUtils を使います。 (BadgeUtils は Experimental なので今後変更される可能性があります) attachBadgeDrawable で Toolbar と表示させたい menu の id を渡すことで Badge を表示させることができます。 これまで頑張っていた Badge の表示がとても簡単になって最高ですね。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む