Navigation(AAC)+BottomNavigationViewでItemとFragmentを簡単に紐づける

Navigationコンポーネントを利用することで、単純なボタンから始まり、アプリバー、ナビゲーションドロワーなどからの画面遷移を簡単に実装することができます。
今回は、Navigationコンポーネントを利用し、BottomNavigationViewのそれぞれのアイテムとFragmentを紐づけていい感じに表示しよう、というのが目的です。

AFragmentのボタンをクリックするとBFragmentへ遷移する~みたいなのは今回の実装に含みません。
実装する場合は、下記のリンクがとても参考になるので一読推奨。

Usage

1.ライブラリのダウンロード

Navigationコンポーネントを利用するために必要なライブラリをdependenciesに追記。
・build.gradle

    implementation "android.arch.navigation:navigation-fragment:1.0.0"
    implementation "android.arch.navigation:navigation-ui:1.0.0"
    implementation "android.arch.navigation:navigation-fragment-ktx:1.0.0"
    implementation "android.arch.navigation:navigation-ui-ktx:1.0.0"

2.BottomNavigationViewと紐づけるFragmentの作成

実際、後述するナビゲーショングラフの作成の時にFragmentの作成もまとめてできますが、如何せんテンプレートコードでFragmentが実装されるため不要なコードもくっついてきます。
ので、事前に自身が必要なFragmentクラスとレイアウト用のXMLを定義しておきましょう。

今回使うFragment

  • HomeFragment
  • ScheduleFragment
  • LikeFragment
  • OtherFragment

3.ナビゲーショングラフの作成

ナビゲーショングラフは、アプリの画面ごと遷移関係を定義するためのファイルとなります。
まずは、res配下にnavigationディレクトリを作成し、そこにXMLを作成します。(名前は任意)

・res/navigation/app_navigation.xml

<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/app_navigation.xml"
            app:startDestination="@id/homeFragment">

    <fragment android:id="@+id/homeFragment"
              android:name="com.example.hamp.HomeFragment"
              android:label="fragment_home"
              tools:layout="@layout/fragment_home"/>

    <fragment android:id="@+id/scheduleFragment"
              android:name="com.example.hamp.ScheduleFragment"
              android:label="fragment_schedule"
              tools:layout="@layout/fragment_schedule"/>

    <fragment android:id="@+id/likeFragment"
              android:name="com.example.hamp.LikeFragment"
              android:label="fragment_like"
              tools:layout="@layout/fragment_like"/>

    <fragment android:id="@+id/otherFragment"
              android:name="com.example.hamp.OtherFragment"
              android:label="fragment_other"
              tools:layout="@layout/fragment_other"/>
</navigation>

・Designタブで見たときの状態 f:id:hamup:20190609230451p:plain

4.BottomNavigationViewのmenu resource内のItemたちのId変更

BottomNavigationViewのアイテムとFragmentを紐づけるためには、ナビゲーショングラフのXMLで定義したFragmentのidと、menu resourceで定義しているアイテムのidを同一にしておく必要があります。
同一にしておくことでよしなに紐づけてくれます。

・res/menu/bottom_navigation_item.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
            android:id="@+id/homeFragment"
            android:icon="@drawable/baseline_home_white_24dp"
            android:title="Home"/>
    <item
            android:id="@+id/scheduleFragment"
            android:icon="@drawable/baseline_calendar_today_white_24dp"
            android:title="Schedule"/>

    <item
            android:id="@+id/likeFragment"
            android:icon="@drawable/baseline_favorite_white_24dp"
            android:title="Like"/>

    <item
            android:id="@+id/otherFragment"
            android:icon="@drawable/baseline_more_horiz_white_24dp"
            android:title="Other"/>

</menu>

4.NavHostFragmentをレイアウトファイルに定義する

レイアウトファイルにNavHostFragmentを追加します。
先程定義したナビゲーショングラフを実際にレイアウトとして利用するために、属性app:navGraphに設定します。

・res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<tools:FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent" xmlns:tools="http://schemas.android.com/tools"
        >

    <fragment
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:navGraph="@navigation/app_navigation"
            app:defaultNavHost="true"
            android:id="@+id/navHostFragment"/>

    <android.support.design.widget.BottomNavigationView
            android:id="@+id/bottom_navigation"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:background="@color/colorPrimary"
            app:itemIconTint="@drawable/bottom_navigation_colors"
            app:itemTextColor="@drawable/bottom_navigation_colors"
            app:menu="@menu/bottom_navigation_item" />

</tools:FrameLayout>

5.実行画面

4まで終われば完成です。実行してみると下記の様に選択するItemごとにFragmentが切り替わっているのが分かります。 f:id:hamup:20190609230454g:plain

参考サイト

BottomNavigationViewの実装について

BottomNavigationViewの実装についてメモ書き。
レイアウトファイルへの定義だけで実装が済んでしまうので思ったよりも簡単でした。
なお、公式ページのUsageに則りつつ最小限の実装しかしていませんのであしからず。

Usage

1.ライブラリのダウンロード

BottomNavigationViewを利用するために必要なライブラリをdependenciesに追記。

build.gradle

implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:design:28.0.0'

2.Viewに表示させるアイテム用のmenu resourceを作成する

まずは、表示させたいアイテムをmenu resourceに定義していきます。
尚、表示できるアイテムは最大で5つとなっています。

下記はアイテム4つ分のサンプルコード。
アイコンについては公式が出しているIcons - Material Designから素材を探すと◎。

・res/menu/bottom_navigation_item.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
            android:id="@+id/nav_home"
            android:icon="@drawable/baseline_home_white_24dp"
            android:title="Home"/>
    <item
            android:id="@+id/nav_schedule"
            android:icon="@drawable/baseline_calendar_today_white_24dp"
            android:title="Schedule"/>

    <item
            android:id="@+id/nav_favorite"
            android:icon="@drawable/baseline_favorite_white_24dp"
            android:title="Like"/>

    <item
            android:id="@+id/nav_other"
            android:icon="@drawable/baseline_more_horiz_white_24dp"
            android:title="Other"/>

</menu>

3.BottomNavigationViewの作成+menu resourceを紐づける

レイアウトのxml(下記例はMainActivity用)に、BottomNavigationViewのウィジェットを追加します。
各属性の内容は下記のようになっています。

属性 内容
android:background BottomNavigationViewの背景色を変更する。
app:itemIconTint itemのアイコンカラーを変更する。
app:itemTextColor itemのテキストカラーを変更する。
app:menu menu resourceを設定する。

・res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <!-- Main content -->

    <android.support.design.widget.BottomNavigationView
            android:id="@+id/bottom_navigation"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:background="@color/colorPrimary"
            app:itemIconTint="@color/white"
            app:itemTextColor="@color/white"
            app:menu="@menu/bottom_navigation_item" />

</FrameLayout>

4.Selectorの設定

app:itemIconTintおよびapp:itemTextColorについて、単純に色を設定できるだけでなく、Selectorを書くことでアイテムの状態変化に応じて色を設定することができます。
これで、選択されているアイテムはホワイト、それ以外はグレーアウトにする、みたいなことができます。

・res/drawable/bottom_navigation_colors.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">

  <!-- 選択されているとき -->
  <item
      android:state_checked="true"
      android:color="@color/colorPrimary" />

  <!-- 選択されていないとき -->
  <item
      android:state_checked="false"
      android:color="@color/grey" />
 </selector>

・res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <!-- Main content -->

    <android.support.design.widget.BottomNavigationView
            android:id="@+id/bottom_navigation"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:background="@color/colorPrimary"
            app:itemIconTint="@drawable/bottom_navigation_colors"
            app:itemTextColor="@drawable/bottom_navigation_colors"
            app:menu="@menu/bottom_navigation_item" />

</FrameLayout>

5.実行画面

実際に実行してみると下記の様な感じになります。 リソースファイルだけでここまで実装できるのは本当にすごいですね...!

f:id:hamup:20190609194632g:plain

まとめ

あとは、選択されたアイテムごとにそれぞれのレイアウトを紐づけることができればシュッとしたいい感じのアプリになりそうです。
なんとなく大変そうなイメージですが、AACNavigationコンポーネントを利用することレイアウトとの紐づけや画面遷移の設定について簡単に実装することができます。

実際の方法についてを下記に追記しました。
hamup.hatenablog.com

参考サイト

Youtube APIを利用してアイドル部のデータを取得する_Part1

Youtubeが公開しているAPI
YouTube Data API の概要  |  YouTube Data API (v3)  |  Google Developers

これを使ってアイドル部メンバーのチャンネル情報を取得、AndroidのRecyclerViewを使って表示しよう!というのが趣旨。
今回はYoutube APIを利用するまでの手順を解説したいと思います。

APIを利用するための準備

YoutubeAPIは、APIキーの情報も乗せてリクエスト送信する必要があります。 そのため、事前にAPIキーの取得をしきましょう。

  • Google Cloud Platformを開く。
  • プロジェクトを選択する。(ない場合は新規に作成する)
  • 左のサイドバーから[ライブラリ]を選択する。
  • 検索バーに[Youtube]を入れると選択肢に[YouTube Data API v3]が表示されるので選択する。
  • [有効にする]を選択する。
  • 選択後、遷移した画面の[認証情報を作成]を選択する。
  • 下記のようにユースケースに合わせて選択し、[必要な認証情報]を選択する。 f:id:hamup:20190519172457p:plain

  • 最後にAPIキーが発行されるので確認して完了。 f:id:hamup:20190519172954p:plain

承認の認証情報を取得する  |  YouTube Data API (v3)  |  Google Developers

実際に使ってみる

APIキーを発行したので、実際叩けるようになったのか確認。
例として、たまちゃん(夜桜たま)のチャンネル情報を取得してます。

チャンネルの情報を取得するためには、チャンネル固有のIDを指定する必要があるのでそちらを先に調べておきます。
チャンネルIDは、チャンネルのTOPページのURLのchannel以降の文字列となります。
f:id:hamup:20190519172515p:plain

あとはSerach(検索)用のAPIにたまちゃんのチャンネルIDを指定するだけ。
これでチャンネルの動画情報を取得することができます。
Search: list  |  YouTube Data API (v3)  |  Google Developers

リクエス

下記のHTTPリクエストを発行。

https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCOefINa2_BmpuX4BbHjdk9A&key=APIキー

ただ、これだけのパラメータ指定だと、実際データを扱う際に色々不便なところが多いです。
例えばデフォルトだと5件の動画情報しか取れない、日付順に並んでいない、最大50件までしか取得できない...etc
公式のリファレンスを見るとわかりますが、パラメータ指定してあげれば上の問題は解決します。(余力があったら実際のリクエストも追記します。)

取得データ

いい感じに取得できていますね。
あとはAndroid側でAPI叩けるようにして画面に表示するだけです。

{
    "kind": "youtube#searchListResponse",
    "etag": "\"XpPGQXPnxQJhLgs6enD_n8JR4Qk/bW-2tqqtTLESSvKwL9a7Ny7ASYg\"",
    "nextPageToken": "CAUQAA",
    "regionCode": "JP",
    "pageInfo": {
        "totalResults": 180,
        "resultsPerPage": 5
    },
    "items": [
        {
            "kind": "youtube#searchResult",
            "etag": "\"XpPGQXPnxQJhLgs6enD_n8JR4Qk/Q5mCuMbj3r1Z-e6gxhSOKYMGE4E\"",
            "id": {
                "kind": "youtube#video",
                "videoId": "Gn-wIcBio6E"
            },
            "snippet": {
                "publishedAt": "2019-03-03T13:57:49.000Z",
                "channelId": "UCOefINa2_BmpuX4BbHjdk9A",
                "title": "【音MAD】タマガツモル feat.ばあちゃる【アイドル部】",
                "description": "お誕生日、たくさんお祝いしてくださってありがとうございました…! これからも楽しいことをいっぱい共有していけるように頑張ります(*´°`*)...",
                "thumbnails": {
                    "default": {
                        "url": "https://i.ytimg.com/vi/Gn-wIcBio6E/default.jpg",
                        "width": 120,
                        "height": 90
                    },
                    "medium": {
                        "url": "https://i.ytimg.com/vi/Gn-wIcBio6E/mqdefault.jpg",
                        "width": 320,
                        "height": 180
                    },
                    "high": {
                        "url": "https://i.ytimg.com/vi/Gn-wIcBio6E/hqdefault.jpg",
                        "width": 480,
                        "height": 360
                    }
                },
                "channelTitle": "夜桜たま",
                "liveBroadcastContent": "none"
            }
        },
        {
            "kind": "youtube#searchResult",
            "etag": "\"XpPGQXPnxQJhLgs6enD_n8JR4Qk/vC6W6LRgL53y_4p15XXD7d_9yL8\"",
            "id": {
                "kind": "youtube#video",
                "videoId": "K3c0DjYEo48"
            },
            "snippet": {
                "publishedAt": "2018-10-04T13:30:00.000Z",
                "channelId": "UCOefINa2_BmpuX4BbHjdk9A",
                "title": "【怒ってる?】ツンデレの黄金比は9:1【さくたま流】",
                "description": "「ツンデレ」と言われる女流プロはたくさんいらっしゃいますが、普段はふわふわ卓上ではきりり。 そのギャップにこっちはめろめろ(∩ˊ꒳​ˋ...",
                "thumbnails": {
                    "default": {
                        "url": "https://i.ytimg.com/vi/K3c0DjYEo48/default.jpg",
                        "width": 120,
                        "height": 90
                    },
                    "medium": {
                        "url": "https://i.ytimg.com/vi/K3c0DjYEo48/mqdefault.jpg",
                        "width": 320,
                        "height": 180
                    },
                    "high": {
                        "url": "https://i.ytimg.com/vi/K3c0DjYEo48/hqdefault.jpg",
                        "width": 480,
                        "height": 360
                    }
                },
                "channelTitle": "夜桜たま",
                "liveBroadcastContent": "none"
            }
        },
        {
            "kind": "youtube#searchResult",
            "etag": "\"XpPGQXPnxQJhLgs6enD_n8JR4Qk/2s-dBLSzy51UCdWXhwsUgy0irQs\"",
            "id": {
                "kind": "youtube#video",
                "videoId": "WjhFJZ726eE"
            },
            "snippet": {
                "publishedAt": "2018-09-14T13:00:09.000Z",
                "channelId": "UCOefINa2_BmpuX4BbHjdk9A",
                "title": "【自己紹介】はじめまして!夜桜たまです!",
                "description": "3度の飯より麻雀が好き! 立派な電脳雀士になりたいVTuberです(∩ˊ꒳​ˋ∩)・* ✿Twitter https://twitter.com/YozakuraTama ✿公式サイト https://vrlive.party/...",
                "thumbnails": {
                    "default": {
                        "url": "https://i.ytimg.com/vi/WjhFJZ726eE/default.jpg",
                        "width": 120,
                        "height": 90
                    },
                    "medium": {
                        "url": "https://i.ytimg.com/vi/WjhFJZ726eE/mqdefault.jpg",
                        "width": 320,
                        "height": 180
                    },
                    "high": {
                        "url": "https://i.ytimg.com/vi/WjhFJZ726eE/hqdefault.jpg",
                        "width": 480,
                        "height": 360
                    }
                },
                "channelTitle": "夜桜たま",
                "liveBroadcastContent": "none"
            }
        },
        {
            "kind": "youtube#searchResult",
            "etag": "\"XpPGQXPnxQJhLgs6enD_n8JR4Qk/Hx25AZuuVuhx47dRMwGMFKs1IhM\"",
            "id": {
                "kind": "youtube#video",
                "videoId": "EYdnZW0Xlho"
            },
            "snippet": {
                "publishedAt": "2018-07-20T15:15:01.000Z",
                "channelId": "UCOefINa2_BmpuX4BbHjdk9A",
                "title": "【PUBG】戦闘訓練する【アイドル部】",
                "description": "皆さん、こんばんは! 私立ばあちゃる学園のアイドル部、そして麻雀部の部長を兼任しております。 夜桜たまです。 今日は立派なアイドルにな...",
                "thumbnails": {
                    "default": {
                        "url": "https://i.ytimg.com/vi/EYdnZW0Xlho/default.jpg",
                        "width": 120,
                        "height": 90
                    },
                    "medium": {
                        "url": "https://i.ytimg.com/vi/EYdnZW0Xlho/mqdefault.jpg",
                        "width": 320,
                        "height": 180
                    },
                    "high": {
                        "url": "https://i.ytimg.com/vi/EYdnZW0Xlho/hqdefault.jpg",
                        "width": 480,
                        "height": 360
                    }
                },
                "channelTitle": "夜桜たま",
                "liveBroadcastContent": "none"
            }
        },
        {
            "kind": "youtube#searchResult",
            "etag": "\"XpPGQXPnxQJhLgs6enD_n8JR4Qk/WszUy5cPkZWZ_qWKqM-U2wBipKE\"",
            "id": {
                "kind": "youtube#video",
                "videoId": "c_P3_Zs6Ib4"
            },
            "snippet": {
                "publishedAt": "2018-09-07T12:33:25.000Z",
                "channelId": "UCOefINa2_BmpuX4BbHjdk9A",
                "title": "Prologue_夜桜たま",
                "description": "夜桜たまTwitter:https://twitter.com/YozakuraTama .LIVE公式サイト:https://vrlive.party/member/",
                "thumbnails": {
                    "default": {
                        "url": "https://i.ytimg.com/vi/c_P3_Zs6Ib4/default.jpg",
                        "width": 120,
                        "height": 90
                    },
                    "medium": {
                        "url": "https://i.ytimg.com/vi/c_P3_Zs6Ib4/mqdefault.jpg",
                        "width": 320,
                        "height": 180
                    },
                    "high": {
                        "url": "https://i.ytimg.com/vi/c_P3_Zs6Ib4/hqdefault.jpg",
                        "width": 480,
                        "height": 360
                    }
                },
                "channelTitle": "夜桜たま",
                "liveBroadcastContent": "none"
            }
        }
    ]
}

まとめ

今回はAPIでのチャンネル情報取得について書きました。
次の記事では実際にAndroidでのAPIの叩き方、画面表示の仕方、の2つについて解説したいと思います。

話変わりますが、今日は「アイドル部1周年ライブ はんぱないパッション」の当日です。みんなさん!ライブ楽しもうね!!

RecyclerViewで登場するキーワードについてのまとめ

あるデータセットをリスト形式で表示する場合、RecyclerViewウィジェットを使用して実装していく。 実装する上でいくつかのキーワードが登場するが、それぞれがどんな役割を果たしているのか頭の中でもやっとしている状態だったので、整理するためにも今回の記事に纏めたいと思う。

解説

Adapter

AndroidでいうAdapterはViewとデータセットを紐づける役割を持つ。 RecyclerView.Adapterを利用することで、表示するレイアウト(View)とデータセットを紐づける事ができる。 下記、公式引用。
Adapters provide a binding from an app-specific data set to views that are displayed within a RecyclerView.

LayoutInflater

LayoutInflaterを利用することで、XMLファイルに対応するViewオブジェクトをインスタンス化することができる。 よく、インフレートするという文章を見るが、前述したようにViewオブジェクトのインスタンス化という理解でいいのかなーと思う。

一例であるが下記の様にしてViewオブジェクトの生成を行うことができる。

val layoutInflater = LayoutInflater.from(context)
val view = layoutInflater.inflate(R.layout.sample_row, parent, false)

尚、Inflateには、一般的な意味として、膨らませるというような意味がある。

ViewHolder

RecyclerViewでのViewHolderの役割を一言で表すと「1行分のViewに対する参照を保持するもの」と言える。
Adapterは、画面に表示する行数分のViewHolderを作成し、行ごとに応じたデータをViewHolderに設定し、その情報をRecyclerViewに格納する。

RecyclerView.ViewHolder ⇒ 親Viewの参照を保持
RecyclerView.ViewHolderを継承した自作ViewHolder ⇒ 子Viewの参照を保持

RecyclerView.Adapterの基本的な実装

前述までの話を踏まえたうえで、RecyclerView.Adapterの実装のサンプルコードを下記に示す。

  • アダプター(SampleListAdapter.kt)
class SampleListAdapter(private val myDataset: MutableList<MyData>):
    RecyclerView.Adapter<SampleListAdapter.MyViewHolder>() {

    /* 基底クラスの初期化には親Viewへの参照を渡す */
    class MyViewHolder(view: View): RecyclerView.ViewHolder(view) {
    /* 子Viewへの参照を保持する */
        val imageView = view.findViewById(R.id.sample_imageView) as ImageView
        val textView = view.findViewById(R.id.sample_title_textView) as TextView
    }

    /* XMLレイアウトに応じたViewオブジェクトの作成とViewHolderの作成 */
    override fun onCreateViewHolder(parent: ViewGroup, position: Int): MyViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        val view = layoutInflater.inflate(R.layout.sample_item_row, parent, false)

        return MyViewHolder(view)
    }

    /* 作成したViewHolder内のViewに対して更新を行う */
    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        Picasso.get().load(url).into(holder.imageView)
        holder.textView.text = myDataset[position].text
    }

    override fun getItemCount(): Int = myDataset.size
}

フラグメント(SampleListFragment.kt)

class SampleListFragment: Fragment() {

    private lateinit var recyclerView: RecyclerView
    val dummyDataset: MutableList<MyData> = mutableListOf()

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.sample_list_fragment, container, false)

        recyclerView = view.findViewById(R.id.recyclerview)
        val layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
        recyclerView.layoutManager = layoutManager

        dummyData()
        val adapter = SampleListAdapter(dummyDataset)
        /* 作成したAdapterをRecyclerView.Adapterに接続 */
        recyclerView.adapter = adapter

        return view
    }
    
    fun dummyData() {
        val dummyData1 = ChannelList("https://i.ytimg.com/vi/cw256acegBA/hqdefault.jpg", "dummyText1")
        val dummyData2 = ChannelList("https://i.ytimg.com/vi/cw256acegBA/hqdefault.jpg", "dummyText2")
        val dummyData3 = ChannelList("https://i.ytimg.com/vi/cw256acegBA/hqdefault.jpg", "dummyText3")
        dummyDataset.add(dummyData1)
        dummyDataset.add(dummyData2)
        dummyDataset.add(dummyData3)

    }
}

まとめ

ざっと書いただけなので余り綺麗にまとまっていないが頭の中がだいぶ整理できた気がする。
RecyclerViewってListViewに比べると自分でいろいろ実装しないといけないところが増えているので、上記で書いたこと以外にも押さえておくべきところが沢山ある。
そこについては実装する機会があるときにまた纏めたいと思う。

参考サイト

画像ライブラリ Picassoの基本的な使い方

Picassoとは

square社が作成した、Android向けの画像ダウンロード・キャッシュライブラリ。
当ライブラリを利用することで、インターネットからの画像ダウンロードなどが簡単に実装できる。
例えば、APIを叩いて返却されたJSONが持っている画像URLの情報を渡すだけで、
画像ダウンロードからImageViewへのデータセットまで行ってくれる。

ライブラリのダウンロード

gradleのdependenciesに下記を追記する。

dependencies {
  /* 現在の最新 */
  implementation 'com.squareup.picasso:picasso:2.71828'
}

Usage

最も単純な使い方。URL先の画像をimageViewにセットできる。

Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(imageView);

画像のリサイズなども行える。

Picasso.get()
  .load(url)
  .resize(50, 50)
  .centerCrop()
  .into(imageView)

Tips

  • 取得先のURLがhttpの場合、取得に失敗する。
    対処法:httpをhttpsに変換する。
    下記はreplaceメソッドでhttpをhttpsに置き換えている。
Picasso.get().load(photos[position].image_url.replace("http", "https"))
    .into(viewHolder.photoImageView)

 

参考サイト

Vagrant+VirtualBoxでWindowsに仮想マシンを構築するためのメモ

Windows上でVagrantを使用して仮想マシンを立ち上げるための手順についてメモ書き。

Vagrantとは

VirtualBoxVMWareなどの仮想化ソフトのフロントエンドとして動作するコマンドラインツール。 簡単なコマンドで、Box(イメージ)と構成情報を記載した設定ファイル(Vagrantfile)をもとに仮想マシンの構築や設定を行うことができる。
Vagrant自身には仮想化機能はないので注意。

Vagrantを利用することで、同じ環境を何回でも作成することができる。
会社でもVagrantを利用した仮想マシンの環境構築を導入しているが、 3桁を超える人数で開発しているので、こういったツールは非常に便利だと感じる。

1.VirtualBoxのインストール

下記からWindows用のインストーラーをダウンロードして、インストールする。 Downloads – Oracle VM VirtualBox

2.Vagrantのインストール

下記からWindows用のインストーラーをダウンロードして、インストールする。
インストール後は再起動を求められるので再起動すること。
Download - Vagrant by HashiCorp

3.GitBashのインストール

下記からWindows用のインストーラーをダウンロードして、インストールする。 Git for Windows

4.Vagrant Boxesの選択

  • 下記からインストールしたいBoxを検索する。
    検索結果からBox名をクリックすると、プロバイダに応じた実行コマンドが記載されているため実行する。 Discover Vagrant Boxes - Vagrant Cloud

  • 作業用のディレクトリを作成する。

$mkdir /c/Users/hamp/HAMUP_WORKS/Vagrant
  • プロバイダに応じた実行コマンドを実行する。(bento/ubuntu-16.04の場合) 実行したディレクトリにVagrantfileが作成される。
vagrant init bento/ubuntu-16.04 \
  --box-version 201812.27.0
vagrant up

5.Vagrantfileの編集

下記行のコメントアウトを外す。

# config.vm.network "private_network", ip: "192.168.33.10"

6.Vagrant Up

Vagrantfileに応じた仮想マシンを起動する。(初回はBoxのダウンロードが入るので時間がかかる。)

$vagrant up

起動が完了したら、あとはカレントディレクトリで$vagrant sshと打つか、
Teraterm等でログインしてやりたい作業をやるのみ。
vagrant/vagrant(初期ユーザ/パスワード)

次回起動は$vagrant upと打つか、VirtualBoxから行う。

ネットワーク周りの設定について

仮想マシンの使い方に応じてネットワークの設定についても考慮する必要がある。
今回は、ホストから仮想マシンにアクセスできれば十分なのでホストオンリーアダプターを選択。

  • NAT
  • ホストオンリーアダプター
  • 内部ネットワーク
  • ブリッジアダプター
  • ポートフォワーディング

参考サイト