- 投稿日:2019-11-01T19:11:57+09:00
面倒くさがりのためのListView+LiveData
Androidのリスト表示って面倒くさい
何がめんどくさいかって言われると
・ViewHolderとか面倒くさい
・レイアウト作るのも面倒くさい
・clickListenerとかも面倒くさいArrayAdapterは汎用性がない
こんなデータモデルのリストがあるとします。
data class ItemEntity( var id: Long, var type: Int, var name: String ) val itemList = MutableLiveData<MutableList<ItemEntity>>()これをArrayAdapterに喰わせるためにはname取り出してlistにして
listViewにclickListener設定して、positionからid取り出して。。。とかちょっとナンセンスそこで2stepで実装できるListView(CustomArrayAdapter)の提案です。
Step 1 ArrayAdapterを継承したクラスを作る
ItemListAdapter.ktclass ItemListAdapter(context: Context, val itemList: MutableList<ItemEntity>, val onclick: (AreaSearchEntity) -> Unit) :ArrayAdapter<String>(context, android.R.layout.simple_list_item_1) { override fun getCount(): Int { return itemList.size } override fun getItem(position: Int): String? { return itemList[position].name } override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { convertView?.setOnClickListener { onclick(itemList[position]) } convertView?.apply { //rippleエフェクト val out = TypedValue() context.theme.resolveAttribute(android.R.attr.selectableItemBackground, out, true) setBackgroundResource(out.resourceId) } return super.getView(position, convertView, parent) } }デザインとか変えたいならandroid.R.layout.simple_list_item_1を独自のlayoutに変更しましょう
getViewでclickListenerとrippleのエフェクトを設定しています。
画像つけたり、レイアウトなんかしたい時はここでStep 2 データリストをobserveしてadapterをセットする
mainActivityoverride fun onResume() { itemList.observe(this, Observer { if(it.isNotEmpty()) { binding.itemList.adapter = ItemListAdapter(this, it) { item -> //ラムダでClickされた対象のitemをそのまま使える hoge(item.id) } } }) }上記のitemListをActivityやFramgentのいい感じのタイミングでobserveしましょう
あとはAPI叩いて帰ってきたlistをitemListにpostValueすればOKです〜完〜
- 投稿日:2019-11-01T15:32:56+09:00
[ Android ] 画面回転に対応したレイアウト変更
本記事では画面回転によってレイアウトを変更する実装方法について述べる。
前準備
まず端末の
「設定」→「ディスプレイ」→「画面の自動回転」をONにして頂きたい。
これに気づかず、実行してもうまくいかなかった。
準備ができたら早速実装である。実装
とはいうものの、かなり簡単である。
「res」にlayout-landディレクトリを作り、
その下に横画面用レイアウトファイルを作る
だけである。
landは「landscape」の略で、
要するに横画面という意味である。
縦画面用ディレクトリはデフォルトで入っているlayoutである。・ディレクトリ構造図
res
- layout -activity_main.xml(縦画面用レイアウトファイル)
- layout-land -activity_main.xml(横画面用レイアウトファイル)これ以外は何もする必要はない。
(マニフェストなどもいじらない)実行して、縦横を変えてみると、それに応じた画面が表示される。
以上。
- 投稿日:2019-11-01T15:29:46+09:00
【java】if文でString型の条件文が無視される
javaでif(string == "test_string")を使っているあなた.
String string = "test_string"; if(string=="test_string"){ System.out.println("SUCCESS"); }このようなString型の条件文にうまく入れないことがあります.
そんなあなたに朗報です.
String string = "test_string"; if(string.equals("test_string")){ System.out.println("SUCCESS"); }こちらを使えば入れます.
equalsメソッドの詳しい解説はこちらを参照してみてください!
- 投稿日:2019-11-01T15:08:29+09:00
[ Android ] レイアウト調整
本記事ではAndroidレイアウトを
実装によって調整する方法を記す。
主にTextViewについて述べる。位置
まずは基本中の基本である。以下のようなコードを追加する。
レイアウト内での位置を決めることができる。
・layout_marginStart:左端からx dpの位置
・layout_marginTop :上端からx dpの位置<TextView android:layout_marginStart="2dp" android:layout_marginTop="230dp" />幅・高さ
以下のようなコードを追加する。
・layout_width :横幅を決定
・layout_height:高さを決定<TextView android:layout_width="406dp" android:layout_height="255dp" />文字のセンタリング(中央寄せ)
以下のようなコードを追加する。
<TextView android:gravity="center_horizontal" />ここに"left"を指定すると左寄せ、
"center_vertical"を指定することもできる。枠の最大幅の指定
以下のようなコードを追加する。
最大幅は40 dpで4行まで表示できる。
文字が最大幅を超えると自動的に改行される<TextView android:maxWidth =" 40dp " android:lines="4" />文字列の改行
指定した位置で改行したい場合は
表示文字列の改行したい部分で\nを入れるだけである。<TextView android:text="Text\nView" />一行表示
TextViewの最大幅を超える文字列の場合、「…」と表示したい場合がある。
そんな時は以下のようなコードを書く。<TextView android:ellipsize="end" android:singleLine="true" />ellipsizeがendの時は文字列の後ろに「…」が表示される。
ellipsizeにはいくつか指定できる。
以下がそのオプションである。・none :表示なし
・start :…xxxxx
・middle :xx…xxx
・end :xxxxx…以下のサイトがとても参考になった。
https://qiita.com/tamappe/items/b90770064007842c06d2まとめ
今回はTextViewについて記したが、ImageViewやButtonにも使えるものがあるので
ぜひ試していただきたい。
また、本記事では述べていないが、javaファイルから指定出来たりもするので、
参考にして頂けたらと思う。
以上。
- 投稿日:2019-11-01T12:08:07+09:00
[Android] Chip使用時にInvocationTargetExceptionが発生する
概要
Androidアプリ開発時にChipを利用しようとしたら、
InvocationTargetExceptionが発生。私が解決した方法を記述します。
※注意 私が解決できた方法であり、必ず解決するわけではないと思うので、「もしかしたら解決するかも?」程度にお試しください...解決方法
android:textAppearanceを設定したらエラーを解消できました。
xmlxml.fragment.xml<com.google.android.material.chip.ChipGroup android:id="@+id/chooseService_chipGroup" android:layout_width="wrap_content" android:layout_height="wrap_content"> <com.google.android.material.chip.Chip android:id="@+id/chip1" style="@style/Widget.MaterialComponents.Chip.Filter" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium"/> <com.google.android.material.chip.Chip android:id="@+id/chip2" style="@style/Widget.MaterialComponents.Chip.Filter" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium"/> <com.google.android.material.chip.Chip android:id="@+id/chip3" style="@style/Widget.MaterialComponents.Chip.Filter" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium"/> </com.google.android.material.chip.ChipGroup>まとめ
今回はxml上で静的に
TextAppearanceを設定しましたが、動的に行う場合はChip.setTextAppearanceで行うことができます。
InvocationTargetExceptionはコンストラクタなどで発生する例外なので、xmlの要素に設定した値が間違っているか、不足している場合に呼び出されます。そのため、もう一度設定した値が間違っていないかを確かめてみてください。参考文献
AndroidDevelopers Chip
https://developer.android.com/reference/com/google/android/material/chip/Chip
- 投稿日:2019-11-01T11:41:30+09:00
Kotlinでアプリを作ってみる(補足編)
前回「Kotlinでアプリを作ってみる」の補足編。
ConstraintLayoutでボタン等追加した時にxmlで出るエラーの解決法について書きます。
ConstraintLayoutってあまり馴染みがなかったのは私だけでしょうか。最近よく出てくる…AndroidsStudio(Windows)ショートカットキー
エラーの文言をコピーする方法:
エラーにカーソルを当てた状態で、最下部に表示されるツールバーを右クリックして
コピーできる。前から知ってたらよかった...超便利です!!ConstraintLayoutのエラー文言は以下
This view is not constrained. It only has designtime positions, so it will jump to (0,0) at runtime unless you add the constraints
このビューには制約がありません。設計時の位置しかないため、制約を追加しない限り、実行時に(0,0)にジャンプします
解決策
対象オブジェクトを選択して、「Infer Constraints」をクリック
レイアウト追加時に自動でConstraintsを設定するには
上下左右のガイドに従うのが良いらしいです。
私みたいにコピペでレイアウト追加しないほうが良いみたいですね。
- 投稿日:2019-11-01T11:41:30+09:00
Kotlinでアプリを作ってみる(Button,Intent,Log:補足編)
前回「Kotlinでアプリを作ってみる」の補足編。
ConstraintLayoutでボタン等追加した時にxmlで出るエラーの解決法について書きます。
ConstraintLayoutってあまり馴染みがなかったのは私だけでしょうか。最近よく出てくる…AndroidsStudio(Windows)ショートカットキー
エラーの文言をコピーする方法:
エラーにカーソルを当てた状態で、最下部に表示されるツールバーを右クリックして
コピーできる。前から知ってたらよかった...超便利です!!ConstraintLayoutのエラー文言は以下
This view is not constrained. It only has designtime positions, so it will jump to (0,0) at runtime unless you add the constraints
このビューには制約がありません。設計時の位置しかないため、制約を追加しない限り、実行時に(0,0)にジャンプします
解決策
対象オブジェクトを選択して、「Infer Constraints」をクリック
レイアウト追加時に自動でConstraintsを設定するには
上下左右のガイドに従うのが良いらしいです。
私みたいにコピペでレイアウト追加しないほうが良いみたいですね。
- 投稿日:2019-11-01T11:17:33+09:00
【ケース別】XMLのonClickでViewModel上の関数を呼び出す
○ 目次
- 1. 引数なし関数の呼び出し方
- 2. 引数あり(View型以外)関数の呼び出し方
- 3. 引数あり(View型のみ)関数の呼び出し方
- 4. まとめ
1. 引数なし関数の呼び出し方
ViewModel
kotlin.viewModel.ktfun onButtonClicked(){ //省略 }XML
xml.fragment_main.xml<Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Test" android:onClick="@{() -> viewModel.onButtonClicked()}"/>ViewModel側では普通のpublicな関数を用意するだけです。
xml側ではandroid:onClickに"@{() -> viewModel.関数名()}"といった形で設定します。2. 引数あり(View型以外)関数の呼び出し方
ViewModel
kotlin.viewModel.ktfun onButtonClicked(key:String){ //省略 }XML
xml.fragment_main.xml<Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Test" android:onClick="@{() -> viewModel.onButtonClicked('key')}"/>ViewModelでは任意の型の引数を取る関数を用意します。(引数は複数でも可)
xmlでは引数あり関数の呼び出し方と同様にしてandroid:onClickに記述します。先ほどと違う点については、関数内に引数を取るところです。
上の例では直接('key')と値を設定していますが、実際は<data>の<variable>にデータクラスなどを設定しておいて、それを呼び出す形になると思います。3. 引数あり(View型のみ)関数の呼び出し方
ViewModel
kotlin.viewModel.ktfun onRadioButtonClicked(view:View){ when(view.id){ //省略 } }XML
xml.fragment_main.xml<RadioButton android:id="@+id/radioButton1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="category1" android:onClick="@{viewModel.onRadioButtonClicked}"/>viewModel側で2の説明と変わったところは関数の引数が
view:Viewとなったところです。今回の例はこのケースのみ使用することができます。このようにすることで、onClickを呼び出したViewを取得することができます。
xml側の変更点は、android:onClick内の記述が@{viewModel.onRadioButtonClicked}となったところです。viewそのものを引数に取るので明示的に書かなくていいみたいです。
今回の方法は、クリックイベントの後にそのViewのプロパティを変更するときや、RadioButtonなど複数のViewから選択されたViewを取得する際に便利そうです。4.まとめ
ViewModelでは任意の引数を持つ関数を書いて、引数に応じてXMLの
android:onClickの記述方法を変えることで実現できます。
- 1. 引数なし ->
@{()-> viewModel.onclick()}- 2. 引数あり(view型以外) ->
@{()-> viewModel.onClick('key')}- 3. 引数あり(View型) ->
@{viewModel.onClick}
- 投稿日:2019-11-01T09:00:56+09:00
【Android】音量変更(=音量ボタン押下)の検出方法
昔からあるレガシーな方法ですが、ググって出てくる情報が少し実用性には欠けるため、書いておきます。
手法
音量変更もしくは音量ボタンが押された事を検出するIntentとして、AudioManager.VOLUME_CHANGED_ACTION (android.media.VOLUME_CHANGED_ACTION)があります。これをBroadcastReceiverで受ければ良いだけです。
ここまではググってすぐに出てくる情報ですが、AudioManager.VOLUME_CHANGED_ACTIONは以下の点に注意する必要があります。
- 一度の音量変更操作で複数のイベントが通知される
- AudioManager.STREAM_MUSICなどSTREAM毎に通知され、しかも音量変わって無くても通知される
- 画面ON中の初回ボタン操作時は音量UI表示され、実際には音量が変わらないためにイベント通知されない
- 画面OFF中は音楽アプリ等で音楽再生していないと、ボタン押してもイベント通知されない
- ボリュームが変わらないため
ソースコード
AndroidManifest.xml<receiver android:name=".VolumeChangedActionReceiver"> <intent-filter> <actionandroid:name="android.media.VOLUME_CHANGED_ACTION" /> </intent-filter> </receiver>VolumeChangedActionReceiver.javapublic static class VolumeChangedActionReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("android.media.VOLUME_CHANGED_ACTION")) { int newVolume = intent.getIntExtra("android.media.EXTRA_VOLUME_STREAM_VALUE", 0); int oldVolume = intent.getIntExtra("android.media.EXTRA_PREV_VOLUME_STREAM_VALUE", 0); int streamType = intent.getIntExtra("android.media.EXTRA_VOLUME_STREAM_TYPE", 0); if (streamType == AudioManager.STREAM_MUSIC) { // TODO: write your code } } } }
- 投稿日:2019-11-01T01:51:51+09:00
Flutterでandroidビルドしたらgradleで落ちた(Flutter勉強1日目)
Flutterの勉強はじめてみました。
ほぼアプリ開発は未経験ですがつまづいたところをシェア。環境
- Mac
- Android Studio 3.5.1
- Flutter 1.9.1
現象
Flutterで
$ flutter run -d allするとandroid側のみエラーとなる。エラーログ
$ flutter run -d all ~省略~ FAILURE: Build failed with an exception. * What went wrong: A problem occurred configuring root project 'android'. > Could not resolve all artifacts for configuration ':classpath'. > Could not download builder-test-api.jar (com.android.tools.build:builder-test-api:3.2.1) > Could not get resource 'https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-test-api/3.2.1/builder-test-api- 3.2.1.jar'. > Could not GET 'https://dl.google.com/dl/android/maven2/com/android/tools/build/builder-test-api/3.2.1/builder-test-a pi-3.2.1.jar'. > Connect to dl.google.com:443 [dl.google.com/216.58.197.206] failed: Bad file descriptor (connect failed) > Could not download layoutlib-api.jar (com.android.tools.layoutlib:layoutlib-api:26.2.1) > Could not get resource ~省略~ * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. * Get more help at https://help.gradle.org BUILD FAILED in 5s Command: /Users/yuta/dev/my_app/android/gradlew app:properties Please review your Gradle project setup in the android/ folder.修正内容
- android側のディレクトリで利用するGradleのバージョンを使っているAndroidプラグインの環境と合わせる
# ファイルパス /android/gradle/wrapper/gradle-wrapper.properties #Fri Jun 23 08:50:38 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists # 4.10.2を5.1.1に変える distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip




