【個人メモ】Androidアプリ開発をするときに個人的に役立った記事一覧と実装メモ


# はじめに
この記事は、個人的にAndroidアプリ開発をした際に役立った記事についてまとめた**個人的なメモ**です。
ですので、その点を踏まえて閲覧していただきますようお願いいたします。

## Fragmentが重なる
- [フラグメントコンテンツがツールバーと下部ナビゲーションビューに重なる](https://www.fixes.pub/program/104400.html)
    - Fragmentの対象となるLayoutを、widthとheightを0dpにし、constraintBottom_toTopOfやconstraintTop_toBottomOfの設定を行う
- [AppBarLayoutを使う時にlayout_behaviorをFragmentに持たせるとviewが重ねて表示される](https://muumuutech.hatenablog.com/entry/2019/02/24/200204)
    - Containerに対し、app:layout_behaviorの設定を行う

## BottomNavigationViewがキーボードの上に表示されてしまう
- [adjustResizeセットでキーボードの下にあるBottomNavigationViewを非表示にする方法](https://www.it-swarm.jp.net/ja/android/adjustresize%E3%82%BB%E3%83%83%E3%83%88%E3%81%A7%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E3%81%AE%E4%B8%8B%E3%81%AB%E3%81%82%E3%82%8Bbottomnavigationview%E3%82%92%E9%9D%9E%E8%A1%A8%E7%A4%BA%E3%81%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/830298488/)
    - BottomNavigationViewを表示しているActivityに対し、マニフェストにてandroid:windowSoftInputMode="adjustPan"の設定を行う

## キーボードを隠したい
- [【InputMethodManager】Kotlinでキーボードを閉じる方法](http://memento-mori-blog.com/kotlin-input-method-manager/)
    - InputMethodManagerを用いて行う

## 隠れるHeader
### 要点
- 以下のコードのように、CoordinatorLayout内にHeaderとなるAppBarLayoutとコンテンツを作成
- AppBarLayout内にCollapsingToolbarLayoutを作成、この中にHeaderに表示したいコンテンツとToolbarを作成
- CollapsingToolbarLayoutのlayout_scrollFlagsによってスクロール時のHeaderの動作が変化する
- Toolbarのlayout_collapseModeによって、Toolbarを上部に表示したままにできる

```xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context=".~~Activity">
    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/app_bar_height"
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme.AppBarOverlay">
        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:toolbarId="@+id/toolbar">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax"
                app:srcCompat="@drawable/ic_baseline_chat_24"/>
            <de.hdodenhof.circleimageview.CircleImageView
                android:id="@+id/fab"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_anchor="@id/app_bar"
                android:src="@mipmap/icon_180"
                android:layout_marginTop="100dp"
                android:layout_marginLeft="10dp"/>

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin">
                <TextView
                    android:id="@+id/titleText"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textSize="18sp"
                    android:textStyle="bold"
                    android:textColor="@color/white"
                    android:text="Title"/>
            </androidx.appcompat.widget.Toolbar>
        </com.google.android.material.appbar.CollapsingToolbarLayout>
    </com.google.android.material.appbar.AppBarLayout>
    <include layout="@layout/content_scrolling" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
```

### 参考サイト
- [スクロールに合わせてToolbarにタイトルを表示する](https://qiita.com/iwata-n/items/3c65f334b0e60865cb12)
- [いろいろなCoordinatorLayoutパターン](https://qiita.com/YS-BETA/items/190527ffff55356ffb9e)
- [CoordinatorLayoutで作るマテリアルデザインとカスタム方法の基礎](https://medium.com/eureka-engineering/coordinatorlayout%E3%81%A7%E4%BD%9C%E3%82%8B%E3%83%9E%E3%83%86%E3%83%AA%E3%82%A2%E3%83%AB%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%81%A8%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E6%96%B9%E6%B3%95%E3%81%AE%E5%9F%BA%E7%A4%8E-3b037b3ad93d)
- [NestedScrollViewの仕組み](https://qiita.com/takahirom/items/2978ede8e7d40b888832#%E5%89%8D%E6%8F%90)
- [CoordinatorLayoutでヘッダー隠す時の知見を得た話](https://qiita.com/tacksman/items/f19891506e55668ffc06#%E3%83%98%E3%83%83%E3%83%80%E3%83%BC%E3%82%92%E9%9A%A0%E3%81%99%E3%81%9F%E3%82%81%E3%81%AB)
- [AndroidのCoordinatorLayoutを使いこなして、モダンなスクロールを実装しよう](https://techblog.yahoo.co.jp/android/androidcoordinatorlayout/)

## 角丸の画像を表示したい
- [ImageViewを角丸にする方法](https://qiita.com/YusukeSuzuki1213/items/b073bf15b1a2b1fd3e66)
    - 以下の画像のような表示ができる    
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161666/697a7d0f-fa5c-b0ef-e7b4-2cb409be4f8d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161666/cd04f351-1637-97b9-29b9-8d2c76011117.png)


## よくあるSNSのTLみたいな画像表示をしたい
### やりたいこと
よくあるSNSの画像表示みたく、画像数によって以下の画像のように表示の仕方を変える
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161666/40d3107c-aadc-b8d2-0401-df81b7233b6c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161666/59eca71d-c947-387c-a2e1-4637b828f1b3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161666/860c72bd-d7f9-193a-2491-d9d04c379601.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161666/044b277d-a6fd-5913-243a-6053b272e57d.png)

### 流れ
- 画像を表示するためのRecyclerViewを用意する
- RecyclerViewのAdapterを作成
- GridLayoutManagerの設定
- GridLayoutManagerにspanSizeLookupの設定
- RecyclerViewのlayoutManagerに設定したGridLayoutManagerを設定

### 要点
- GridLayoutManagerで指定するSpanCountとgetSpanSizeの返り値によって一行に表示する数が変わる
    - 一行に表示する数 = spanCount / SpanSize
        - 1つ表示: 1 = 4 / 4
        - 2つ表示: 2 = 4 / 2

### レイアウト
RecyclerViewの親は、お好みでConstraintLayoutなどを用いる

```xml
<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/gridImgView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>
```

### 処理
```kotlin
gridImgView.setHasFixedSize(true)
// GridLayoutMangerの設定
val layout = GridLayoutManager(context, 4, LinearLayoutManager.VERTICAL, false)
// spanSizeLookupの設定
layout.spanSizeLookup = object : SpanSizeLookup() {
  override fun getSpanSize(p: Int): Int {
    return when (images.size) {
      1 -> 4
      2, 3, 4 -> 2
      else -> 1
    }
  }
}

holder.gridImgView.layoutManager = layout
// ImgAdapterの設定(中ではonBindViewHolder内で、画像の表示できるようにしてるだけ)
holder.gridImgView.adapter = ImgAdapter(context, this, images)
```


### 参考サイト
- [Recyclerviewの中身の分け方をカスタマイズ](https://qiita.com/hisakioomae/items/29e74eb4227bbb03645c)
- [12_GridLayoutManager setSpanSizeLookup()方法](https://www.jianshu.com/p/29465cce1131)

## includeしたレイアウトの中のViewを触りたい
### やりたいこと
以下のitemViewをrootレイアウトでincludeした際に、itemViewのCardViewやImageViewを触りたい。

### 要点
rootレイアウトのitemViewからfindViewByIdを行い、ImageViewを取得する。
CardViewは、includeで指定したidを用いればよい。
**(itemViewレイアウトで指定したCardViewは、itemViewからfindViewByIdをを行っても取得できない)**

### レイアウト
root

```xml
<include
    android:id="@+id/includeView"
    layout="@layout/itemView" />
```

itemView

```xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/cardView"
    android:layout_width="match_parent"
    android:layout_height="150dp"
    android:layout_margin="1dp"
    app:cardBackgroundColor="@color/colorAccent"
    app:cardCornerRadius="10dp"
    app:cardElevation="0dp">

    <ImageView
        android:id="@+id/imageItem"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:adjustViewBounds="true"
        android:contentDescription="@string/ImgDesc"
        android:scaleType="centerCrop" />
</androidx.cardview.widget.CardView>
```

### ソースコード
```kotlin
val img = itemView.findViewById<ImageView>(R.id.imageItem)
```

### 参考サイト
- [Reference View From Included Layout](https://stackoverflow.com/questions/44395565/reference-view-from-included-layout/44396138)

## ListAdapter not updating item in RecyclerView
### 要点
- viewModel側でlistを更新した際に、observerで`submitList`を行うとRecyclerViewの描画が更新されない場合がある。
    - androidx.recyclerview.widgetのAsyncListDifferクラス内に実装されているsubmitListでは以下のような実装を行っているため
- `submitList`を呼び出した後に`notifyDataSetChanged`を呼びだしたり、listの更新処理を工夫する必要がある。

```java
if (newList == mList) {
    // nothing to do (Note - still had to inc generation, since may have ongoing work)
    if (commitCallback != null) {
        commitCallback.run();
    }
    return;
}
```
### 参考サイト
- [ListAdapter not updating item in RecyclerView](https://stackoverflow.com/questions/49726385/listadapter-not-updating-item-in-recyclerview)


## Gradle Play Publisher
どうやらクローズドテストを公開(審査中)とするまで使えない様子。


## よくある通話アプリの着信通知処理の実装
### 参考サイト
- [Android FCM(GCM) バックグラウンドでonMessageReceivedを通らない時は](https://qiita.com/etet-etet/items/bdd1c03d671a78a33e1d#payload%E3%81%AE%E5%86%85%E5%AE%B9%E3%81%8Cdata%E3%81%AE%E5%A0%B4%E5%90%88)
- [Androidで着信通知を実装してみよう](https://tech-blog.optim.co.jp/entry/2020/12/25/100000)
- [ICHI.PRO
FCM通知を使用してすべてのAndroidOSバージョンの着信ビデオ通話を管理する方法](https://ichi.pro/fcm-tsuchi-o-shiyoshite-subete-no-androidos-ba-jon-no-chakushin-bideo-tsuwa-o-kanrisuru-hoho-115143558285803)
- [ロック画面での可視性を設定する](https://developer.android.com/training/notify-user/build-notification#lockscreenNotification)

## ImageViewのTintColorの変更
### 参考サイト
- [Android ImageViewのTintColorを変更する](https://qoopmk.hatenablog.jp/entry/2019/11/05/080000)

## 定期実行処理
### 参考サイト
- [AndroidでTimerを使わずHandlerだけでお手軽に定期実行してあげる](https://qiita.com/aftercider/items/81edf35993c2df3de353)
- [定期実行処理をKotlinで行いたい](https://teratail.com/questions/191585)

## ImageSlider
### 参考サイト
- [Image Slider | View Pager 2 and Picasso | Android Tutorials | Android.](https://www.youtube.com/watch?v=m7jpntLqm3M)

## NavigationBarの色とアイコンの色の変更
### 参考サイト
- [Android: Change status bar text color with WHITE/BLACK](https://imstudio.medium.com/android-change-status-bar-text-color-659680fce49b#:~:text=It's%20not%20possible%20to%20change,the%20status%20bar's%20background%20color.)
- [AndroidのNavigation Barの色とアイコンの色を変える](https://www.yslibrary.net/2018/05/06/navigationbar-color/)

## IllegalStateException: Fragment no longer exists forの対処
### 参考サイト
- [java.lang.IllegalStateException: Fragment no longer exists for key f0: index 1](https://stackoverflow.com/questions/45734711/java-lang-illegalstateexception-fragment-no-longer-exists-for-key-f0-index-1)

## タグ文字のクリック処理の実装
### 参考サイト
- [Android リアルタイム入力でハッシュタグ形式に文字装飾するTIPS](https://qiita.com/nosaka/items/aeb3ae8c0a3a187dd7a4)
- [テキスト中のタグで画面遷移する実装に使える「ClickableSpan」のデザインを調整する](https://qiita.com/sussan0416/items/5153e6a21ad30dc9e3cd)

## Splash画面
### 参考サイト
- [Navigation Architecture Component - Splash screen](https://stackoverflow.com/questions/51189835/navigation-architecture-component-splash-screen)
- [Android bitmap image size in XML](https://stackoverflow.com/questions/23079355/android-bitmap-image-size-in-xml)

## Retrofit2のEOFException: End of input at line 1 column 1に対するNullOnEmptyConverterFactoryによる対処
### 参考サイト
- [Retrofit2 error java.io.EOFException: End of input at line 1 column 1](https://stackoverflow.com/questions/35744795/retrofit2-error-java-io-eofexception-end-of-input-at-line-1-column-1)

## Androidのエミュレーターから自身のPC(localhost)へ接続
### 参考サイト
- [Androidのエミュレーターから自身のPC(localhost)へ接続](https://araramistudio.jimdo.com/2018/01/11/android%E3%81%AE%E3%82%A8%E3%83%9F%E3%83%A5%E3%83%AC%E3%83%BC%E3%82%BF%E3%83%BC%E3%81%8B%E3%82%89%E8%87%AA%E8%BA%AB%E3%81%AEpc-localhost-%E3%81%B8%E6%8E%A5%E7%B6%9A/)
- [Android Emulator のネットワークを設定する](https://developer.android.com/studio/run/emulator-networking.html)

## OkHttpClientのUserAgentの設定
### 参考サイト
- [How to specify a default user agent for okhttp 2.x requests](https://stackoverflow.com/questions/26509107/how-to-specify-a-default-user-agent-for-okhttp-2-x-requests)

## BLE
### 参考サイト
- [Android Bluetooth Low Energy](https://qiita.com/sacred-sanctuary/items/b710d9bf37d0cd362648)
- [Bluetooth Low Energy の概要](https://developer.android.com/guide/topics/connectivity/bluetooth-le?hl=ja)
- [BLE通信ソフトを作る ( Android Studio 2.3.3 + RN4020 )](https://www.hiramine.com/programming/blecommunicator/index.html)
- [【連載】Bluetooth LE (5) Android 4.3 で Bluetooth LE 機器を使う](https://blog.fenrir-inc.com/jp/2013/10/bluetooth-le-android.html)
- [[Kotlin] substring 文字列を切り出す](https://itsakura.com/kotlin-substring)
- [How to get binary representation of Int in Kotlin
](https://stackoverflow.com/questions/50173028/how-to-get-binary-representation-of-int-in-kotlin)