20191101のAndroidに関する記事は10件です。

面倒くさがりのための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.kt
class 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をセットする

mainActivity
  override 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です

〜完〜

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[ Android ] 画面回転に対応したレイアウト変更

本記事では画面回転によってレイアウトを変更する実装方法について述べる。

前準備

まず端末の
設定」→「ディスプレイ」→「画面の自動回転」をONにして頂きたい。
これに気づかず、実行してもうまくいかなかった。
準備ができたら早速実装である。

実装

 とはいうものの、かなり簡単である。
「res」にlayout-landディレクトリを作り、
その下に横画面用レイアウトファイルを作る

だけである。
landは「landscape」の略で、
要するに横画面という意味である。
縦画面用ディレクトリはデフォルトで入っているlayoutである。

・ディレクトリ構造図
res
- layout    -activity_main.xml(縦画面用レイアウトファイル)
- layout-land -activity_main.xml(横画面用レイアウトファイル)

これ以外は何もする必要はない。
(マニフェストなどもいじらない)

実行して、縦横を変えてみると、それに応じた画面が表示される。
以上。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【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メソッドの詳しい解説はこちらを参照してみてください!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[ 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ファイルから指定出来たりもするので、
参考にして頂けたらと思う。
 以上。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Android] Chip使用時にInvocationTargetExceptionが発生する

概要

 Androidアプリ開発時にChipを利用しようとしたら、InvocationTargetExceptionが発生。私が解決した方法を記述します。

※注意 私が解決できた方法であり、必ず解決するわけではないと思うので、「もしかしたら解決するかも?」程度にお試しください...

解決方法

android:textAppearanceを設定したらエラーを解消できました。
xml

xml.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

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Kotlinでアプリを作ってみる(補足編)

前回「Kotlinでアプリを作ってみる」の補足編。

ConstraintLayoutでボタン等追加した時にxmlで出るエラーの解決法について書きます。
ConstraintLayoutってあまり馴染みがなかったのは私だけでしょうか。最近よく出てくる…

AndroidsStudio(Windows)ショートカットキー

エラーの文言をコピーする方法:
エラーにカーソルを当てた状態で、最下部に表示されるツールバーを右クリックして
コピーできる。前から知ってたらよかった...超便利です!!

2019-11-01.png
2019-11-01 (1).png

ConstraintLayoutのエラー文言は以下

2019-11-01 (5).png

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」をクリック
2019-11-01 (3).png
2019-11-01 (4).png

レイアウト追加時に自動でConstraintsを設定するには

上下左右のガイドに従うのが良いらしいです。
私みたいにコピペでレイアウト追加しないほうが良いみたいですね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Kotlinでアプリを作ってみる(Button,Intent,Log:補足編)

前回「Kotlinでアプリを作ってみる」の補足編。

ConstraintLayoutでボタン等追加した時にxmlで出るエラーの解決法について書きます。
ConstraintLayoutってあまり馴染みがなかったのは私だけでしょうか。最近よく出てくる…

AndroidsStudio(Windows)ショートカットキー

エラーの文言をコピーする方法:
エラーにカーソルを当てた状態で、最下部に表示されるツールバーを右クリックして
コピーできる。前から知ってたらよかった...超便利です!!

2019-11-01.png
2019-11-01 (1).png

ConstraintLayoutのエラー文言は以下

2019-11-01 (5).png

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」をクリック
2019-11-01 (3).png
2019-11-01 (4).png

レイアウト追加時に自動でConstraintsを設定するには

上下左右のガイドに従うのが良いらしいです。
私みたいにコピペでレイアウト追加しないほうが良いみたいですね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【ケース別】XMLのonClickでViewModel上の関数を呼び出す

○ 目次 

  • 1. 引数なし関数の呼び出し方
  • 2. 引数あり(View型以外)関数の呼び出し方
  • 3. 引数あり(View型のみ)関数の呼び出し方
  • 4. まとめ

1. 引数なし関数の呼び出し方

ViewModel

kotlin.viewModel.kt
fun 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.kt
fun 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.kt
fun 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}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【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.java
public 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
            }
        }
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む