class: center, middle, hero, chapter-1 #
サポート ライブラリ
Droid Kaigi 2016
--- class: normal, chapter-1 # 自己紹介 .card[ 荒木佑一 [@yuichi_araki](https://twitter.com/yuichi_araki) Developer Programs Engineer - サポート ライブラリ (主に design ライブラリ) - Google I/O アプリ - Google Santa Tracker アプリ - [d.android.com/samples](http://d.android.com/samples) のサンプルいろいろ ] --- class: center, middle, hero, chapter-2 #
サポート ライブラリ
の
ススメ
??? - 分かっている人にはおさらい --- class: normal, chapter-2 # ご意見・ご要望 .card[ ## b.android.com - Template は "Support Library bug" を選択 - スクリーンショットお願いします ] ??? - サポート ライブラリ チームは割と頑張っています - バグ報告でなくても、新機能要望でも "Support Library bug" でいい - スクリーンショット、できれば動画 - Android Studio で簡単に撮影できる --- class: normal, chapter-2 # 背景 .card[ プラットフォームの新バージョンがリリースされる - 新しい機能 - バグフィックス 古い API レベルも存在し続ける どうやって互換性を保つか ] ??? - 最近で言えば - Lollipop でマテリアル デザイン - Marshmallow で新しい権限モデル - これ自体はいいこと - いわゆるフラグメンテーション --- class: normal, chapter-2 # サポート ライブラリとは .card[ Android アプリに組み込むライブラリ Android プラットフォーム本体と並行して開発される - プラットフォーム本体の機能のバックポート - プラットフォーム本体には存在しない追加の機能 ] ??? - Web の世界では "shim" や "polyfill" と呼ばれるもの - 当初は API レベル間の互換性のためのライブラリだったが、今はいろいろ --- class: normal, chapter-2 # サポート ライブラリ 一覧 .card[ - インフラ互換性: support-v4, support-v13, support-annotations - UI 互換性: appcompat-v7, preferences-v7, preferences-v14, gridlayout-v7 - UI ライブラリ: recyclerview-v7, design, percent, cardview-v7 - その他: palette-v7, customtabs, renderscript-v8, mediarouter-v7, leanback-v17, recommendation, preference-leanback-v17 - 特殊: Testing Support Library (Espresso 含む), Data Binding, MultiDex ] ??? - 20 個ぐらい - 「特殊」は他のサポート ライブラリとバージョンが別 --- class: faq, chapter-2 # Q. 後ろについている -v7 とかは何 support-v4, appcompat-v7 --- class: faq, chapter-2 # Q. 後ろについている -v7 とかは何 support-v4, appcompat-v7 # A. そのライブラリがサポートする最小 API レベル ライブラリ自体のバージョンではない ??? - 最近のライブラリには付けないようになった --- class: normal, chapter-2 # 依存関係 .card[ .large[] ] ??? - 一部省略 - support-v4 がすべての基礎 - cardview-v7 が仲間外れ --- class: normal, chapter-2 # 導入方法 .card[ app/build.gradle ```groovy dependencies { compile 'com.android.support:design:23.1.1' } ``` ] --- class: normal, chapter-2 # 複数のサポート ライブラリ .card[ app/build.gradle ```groovy ext { supportLibVersion = '23.1.1' } dependencies { compile "com.android.support:design:${supportLibVersion}" compile "com.android.support:cardview-v7:${supportLibVersion}" } ``` ] --- class: normal, chapter-2 # support-v4 .card[ ## プラットフォーム基本機能のバックポート - 置き換え
Fragment, Loader など
- なんとか Compat 系
ViewCompat, NotificationCompat など ## 一部追加機能 ViewPager, DrawerLayout, ViewDragHelper, FileProvider など ] ??? - 一番最初のサポートライブラリ "The support library" - Gradle や AAR がなかった時代に作られたのでリソースを含まない - 互換性以外の機能も入っていてちょっとややこしい - 「置き換え」はほぼフレームワークの機能そのまま - 「なんとか Compat」は static メソッドがたくさん - ゲームを除くほぼすべてのアプリが使うのでは - Lollipop や Marshmallow で一部の Deprecated メソッドが SDK から削除された - Jellybean で新しい API が導入されて古い機能は Deprecated になった - Marshmallow で削除された - ICS もサポートしたい場合、support-v4 を使う以外にない (自前で if 文分岐しようとしてもビルドできない) - なので必須ライブラリ --- class: faq, chapter-2 # Q. どっちの Fragment を使えばいいの - android.app.Fragment - android.support.v4.app.Fragment ??? - 一つ目はプラットフォームの Fragment、二つ目は support-v4 の Fragment --- class: faq, chapter-2 # Q. どっちの Fragment を使えばいいの - android.app.Fragment - android.support.v4.app.Fragment # A. android.support.v4.app.Fragment ??? - minSdkVersion が 11 以降のアプリなら android.app.Fragment でも良さそうに思うが、他のサポートライブラリが support-v4 の Fragment を前提としていることがある - 特に理由がなければ support-v4 の Fragment を使おう --- class: normal, chapter-2 # appcompat-v7 .card[  KitKat 以前のプラットフォームでもマテリアル デザインを実現 バックポート専門: プラットフォームにない機能は入れない
] ??? - 以前は Holo のバックポートだった (ActionBarCompat) - 最小 SDK バージョンが ICS 以降なら必要ないのでは? という意見もあった - 現在はマテリアル デザインのバックポート - 特に理由がなければ使うはず --- class: faq, chapter-2 # Q. 「AppCompat なんとか」な View を使うべき? - [AppCompatTextView](http://developer.android.com/intl/ja/reference/android/support/v7/widget/AppCompatTextView.html) - [AppCompatButton](http://developer.android.com/intl/ja/reference/android/support/v7/widget/AppCompatButton.html) - [AppCompatCheckBox](http://developer.android.com/intl/ja/reference/android/support/v7/widget/AppCompatCheckBox.html) - [AppCompatRadioButton](http://developer.android.com/intl/ja/reference/android/support/v7/widget/AppCompatRadioButton.html) ??? - 最近のバージョンで追加された - 外観の調整と Drawable の Tint 機能のバックポートが含まれる --- class: faq, chapter-2 # Q. 「AppCompat なんとか」な View を使うべき? - [AppCompatTextView](http://developer.android.com/intl/ja/reference/android/support/v7/widget/AppCompatTextView.html) - [AppCompatButton](http://developer.android.com/intl/ja/reference/android/support/v7/widget/AppCompatButton.html) - [AppCompatCheckBox](http://developer.android.com/intl/ja/reference/android/support/v7/widget/AppCompatCheckBox.html) - [AppCompatRadioButton](http://developer.android.com/intl/ja/reference/android/support/v7/widget/AppCompatRadioButton.html) # A. 使わないでいい ただし、カスタム View を使うときの継承元としては使う ??? - 通常通りレイアウト XML から inflate していれば appcompat が自動的に差し替える - 念のため、AppCompatActivity や AppCompatDialog は使うことに変わりはない --- class: normal, chapter-2 # gridlayout-v7 .card[ API レベル 14 で追加された GridLayout のバックポート 格子状に View を配置するレイアウト ] ??? - 最小 SDK バージョンが Gingerbread とかのアプリで格子状に配置したい人に - GridLayout に限ったことではないが、既存レイアウトを使うと難しい特殊なレイアウトを実現したい場合、ViewGroup を自作するのも手 --- class: normal, chapter-2 # recyclerview-v7 .card[ ListView や GridView を置き換える Nested Scroll にも対応 ] ??? --- class: faq, chapter-2 # Q. ListView から RecyclerView に移行すべき? --- class: faq, chapter-2 # Q. ListView から RecyclerView に移行すべき? # A. いま動いているなら別にいいのでは 新規に作るなら RecyclerView の方が便利 ??? - モダンな API、Nested Scroll など --- class: normal, chapter-2 # cardview-v7 .card[ カード ] ??? - 一貫性のあるコンテンツはただのリストやタイル グリッドでいい --- class: faq, chapter-2 # Q. CardView のマージンが API レベルによって違う ??? - API レベル 21 より前は CardView の周囲に余分な空白が入る --- class: faq, chapter-2 # Q. CardView のマージンが API レベルによって違う # A. - values と values-v21 で margin/padding を分ける - app:cardUseCompatPadding="true" ??? - elevation 属性のある Lollipop 以降ではシステムが影を出している、それ以前では CardView 自身が影を出している - app:cardUseCompatPadding="true" すると Lollipop 以降にもマージンを入れる --- class: normal, chapter-2 # percent .card[ パーセント指定で View をレイアウトできる PercentFrameLayout, PercentRelativeLayout - layout_width/heightPercent - layout_marginStart/End/Top/BottomPercent - layout_aspectRatio ] ??? - 主に Wear 用 - 単に割合を指定したいなら LinearLayout の layout_weight で可能 - aspectRatio は幅÷高さ。width か height どっちかを指定してもう一方を計算させることができる --- class: normal, chapter-2 # preference-v7/v14 .card[ 設定画面 PreferenceFragmentCompat API レベル 11 で導入された PreferenceFragment のバックポート ] ??? - v7 は support-v4 の Fragment を継承、v14 はシステムの Fragment を継承 - v14 を使うことはあまりないはず --- class: normal, chapter-2 # palette-v7 .card[ 画像から UI コンポーネントの配色に使える色を抽出する [github.com/romainguy/google-io-2014](https://github.com/romainguy/google-io-2014) ] ??? - 最新版でパフォーマンスが 6 倍良くなった --- class: normal, chapter-2 # customtabs .card[  アプリ内ブラウザ - Chrome のログイン状態を保持 - メニュー項目のカスタマイズ
] ??? - WebView で自前で作るのに比べて - ログイン状態が引き継がれる - Intent で Chrome などのブラウザに飛ばすのに比べて - メニュー項目のカスタマイズなどが可能 --- class: normal, chapter-2 # その他 .card[ ## mediarouter-v7 Google Cast 対応 ## leanback-v17, preference-leanback-v17, recommendation Android TV 対応 ## renderscript-v8 RenderScript (API レベル 11 以降) のバックポート ] --- class: faq, chapter-2 # Q. サポート ライブラリをバージョンアップしたら動かなくなった --- class: faq, chapter-2 # Q. サポート ライブラリをバージョンアップしたら動かなくなった # A. compileSdkVersion とサポート ライブラリのバージョンが揃っているか確認 ```groovy android { compileSdkVersion `23` // ... } dependencies { compile 'com.android.support:design:`23`.1.1' // ... } ``` それでもダメなら b.android.com ??? - 例は design だが、design 以外も同様 --- class: center, middle, hero, chapter-3 # Design Support Library ??? --- class: normal, chapter-3 # Design Support Library .card[  マテリアル デザインで使われるコンポーネント群 API レベル 7 からサポート appcompat-v7 の使用が前提 [github.com/chrisbanes/cheesesquare](https://github.com/chrisbanes/cheesesquare) ] ??? - ちょうど去年の DroidKaigi の時期に開発していた - Google I/O 2015 で発表 --- class: normal, chapter-3 # NavigationView .card[  ナビゲーション ドロワーの中のメニューをリソースで作ることができる ```xml <a.s.d.w.NavigationView android:id="@+id/nav_view" android:layout_height="match_parent" android:layout_width="wrap_content" android:layout_gravity="start" android:fitsSystemWindows="true" app:headerLayout="@layout/nav_header" `app:menu="@menu/drawer_view"`/> ```
] ??? - セクション分け、セクションのサブタイトルなどに対応 - app:actionLayout 属性でカスタム要素を追加できる - 例: Gmail の未読数、Google Play Music の「ダウンロード済み」のスイッチなど --- class: normal, chapter-3 # NavigationView のメニュー .card[ ```xml <menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:checkableBehavior="single"> <item android:id="@+id/nav_home" android:icon="@drawable/ic_dashboard" android:title="Home" app:actionLayout="@layout/action_layout.xml" /> <!-- ... --> </group> <item android:title="Sub items"< <menu> <item android:icon="@drawable/ic_dashboard" android:title="Sub item 1" /> ``` ] ??? - グループ分け - サブヘッダー - actionLayout --- class: normal, chapter-3 # TabLayout .card[  ViewPager (support-v4) と連携するタブ ```java tabLayout.`setupWithViewPager(viewPager)`; ``` ] ??? - 昔は ActionBar のナビゲーションモードでタブを作っていた - API レベル 21 で deprecated になった --- class: normal, chapter-3 # TextInputLayout .card[  EditText に機能追加
ヒント、エラー、カウンター ```xml <a.s.d.w.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content" app:counterEnabled="true" app:counterMaxLength="30"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/description"/> </a.s.d.w.TextInputLayout> ``` ] ??? - ヒントは EditText のヒントからアニメーションでフロート表示になる - counterMaxLength は EditText の maxLength と違って、最大文字数を超えて入力できる --- class: normal, chapter-3 # FloatingActionButton .card[  FAB 影付きの丸い ImageButton ```xml <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:fabSize="normal" android:src="@drawable/ic_done" /> ``` ] ??? - API レベルの違いによる影の扱いは CardView と同じ --- class: normal, chapter-3 # Snackbar .card[  Toast の進化版 アクションを設定できる ```java Snackbar.make(view, "Here's a Snackbar", Snackbar.LENGTH_LONG) .setAction("Action", new View.OnClickListener() { @Override public void onClick(View v) { // ... } }) .show(); ``` ] ??? - 使い方は大体 Toast と同じ - show を忘れると出ないので注意 - 一つ目の引数は Context でなく View - 親を辿っていって CoordinatorLayout があればそこに Snackbar の View を出す - なければ適当に出す - setAction でアクションを設定できる --- class: normal, chapter-3 # CoordinatorLayout .card[ 超すごい FrameLayout - 子要素の Behavior を取り持つ - ある要素を別の要素に anchor する - keyline に並べる ] --- class: normal, chapter-3 # AppBarLayout .card[  スクロールに従って Toolbar を隠す ```xml <a.s.d.w.CoordinatorLayout> <a.s.d.w.AppBarLayout> <a.s.v7.w.Toolbar app:layout_scrollFlags ="scroll|enterAlways|snap"/> <a.s.d.w.TabLayout/> </a.s.d.w.AppBarLayout> </a.s.d.w.CoordinatorLayout> ``` ] --- class: normal, chapter-3 # CollapsingToolbarLayout .card[  Toolbar に動きを加える ```xml <a.s.d.w.CoordinatorLayout> <a.s.d.w.AppBarLayout> <a.s.d.w.CollapsingToolbarLayout app:layout_scrollFlags ="scroll|exitUntilCollapsed"> <ImageView app:layout_collapseMode="parallax"/> <a.s.v7.w.Toolbar app:layout_collapseMode="pin"/> </a.s.d.w.CollapsingToolbarLayout> </a.s.d.w.AppBarLayout> </a.s.d.w.CoordinatorLayout> ``` ] ??? - cheesesquare のようにタイトル文字を動かしたい場合、CollapsingToolbarLayout に setTitle しないといけないので注意 --- class: center, middle, hero, chapter-4 # Design ライブラリの新機能 --- class: normal, chapter-4 # BottomSheetBehavior .card[  マテリアル デザインの [ボトム シート](https://www.google.com/design/spec/components/bottom-sheets.html) コンポーネントの実装 - Persistent - Hideable - Modal
] ??? - BottomSheet というクラスはない - CoordinatorLayout の Behavior - 使い方が大きく分けて 3 パターン --- class: normal, chapter-4 # 実用例 .card[  [Google サンタ トラッカー 2015](https://play.google.com/store/apps/details?id=com.google.android.apps.santatracker) Persistent なボトムシート CoordinatorLayout の anchor 機能で FAB をボトムシートの上端に留める ボトム シートが引き上げられたときは FAB を隠す
] --- class: normal, chapter-4 # Persistent な BottomSheetBehavior .card[ ```xml <android.support.design.widget.CoordinatorLayout> <!-- 他の View --> <FrameLayout android:id="@+id/bottom_sheet" android:layout_width="match_parent" android:layout_height="match_parent" android:background="?android:attr/windowBackground" `app:layout_behavior="@string/bottom_sheet_behavior"` `app:behavior_peekHeight="@dimen/bottom_sheet_peek_height"`> <!-- ボトム シートの中身 --> </FrameLayout> </android.support.design.widget.CoordinatorLayout> ``` ] ??? - どんな View でもボトム シートにできる - ボトムシート内のスクロールする部分は NestedScrollView か RecyclerView - NestedScrollingChild を継承したもの --- class: normal, chapter-4 # Hideable な BottomSheetBehavior .card[ ```xml <android.support.design.widget.CoordinatorLayout> <!-- 他の View --> <FrameLayout android:id="@+id/bottom_sheet" android:layout_width="match_parent" android:layout_height="match_parent" android:background="?android:attr/windowBackground" app:layout_behavior="@string/bottom_sheet_behavior" app:behavior_peekHeight="@dimen/bottom_sheet_peek_height" `app:behavior_hideable="true"`> <!-- ボトム シートの中身 --> </FrameLayout> </android.support.design.widget.CoordinatorLayout> ``` ] --- class: normal, chapter-4 # BottomSheetBehavior のコールバック .card[ 状態が変わった時とスライドした時 ```java BottomSheetBehavior behavior = BottomSheetBehavior.from( (FrameLayout) findViewById(R.id.bottom_sheet)); behavior.setBottomSheetCallback( new BottomSheetBehavior.BottomSheetCallback() { @Override public void onStateChanged(@NonNull View bottomSheet, @BottomSheetBehavior.State int newState) { // ... } @Override public void onSlide(@NonNull View bottomSheet, float slideOffset) { // ... } }); ``` ] --- class: normal, chapter-4 # Modal な BottomSheetBehavior .card[ ## BottomSheetDialogFragment 通常の (AppCompat)DialogFragment と使い方は同じ ただしスクロール部分は NestedScrollView / RecyclerView を使う ] --- class: center, middle, hero, chapter-5 # Support Library Internals --- class: center, middle, hero, chapter-5 # サポート ライブラリを作る --- class: normal, chapter-5 # サポート ライブラリを作る .card[ CL を送りたい方へ ## AOSP Contributing ## [source.android.com/source/contributing.html](https://source.android.com/source/contributing.html) ] ??? - GitHub のはミラーなのでプルリクを出してもマージできない --- class: normal, chapter-5 # 所在 .card[ ```sh $ repo init -u \ https://android.googlesource.com/platform/manifest $ repo sync frameworks/support ``` 依存しているもの ```sh $ repo sync external/proguard $ repo sync external/doclava $ repo sync external/antlr $ repo sync prebuilts/gradle-plugin $ repo sync prebuilts/tools $ repo sync prebuilts/maven_repo/android $ repo sync prebuilts/sdk $ repo sync tools/external/gradle $ repo sync development $ repo sync build ``` ] --- class: normal, chapter-5 # ビルド .card[ ``` $ cd frameworks/support $ ./gradlew assembleDebug ``` `../../out` に AAR ができるはず ] ??? - サポート ライブラリを含む SDK 全体をビルドする方法もある - ディレクトリ構造が違うので Android Studio は使えない、InelliJ を使っている - 簡単な CL を出すだけなら - エディターで頑張る - 編集したいクラスだけ Android Studio に持ってきて編集してコピーして戻すのが簡単では --- class: normal, chapter-5 # ディレクトリ構造 .card[ ``` design ├── api (API 一覧) ├── base ├── eclair-mr1 ├── honeycomb ├── honeycomb-mr1 ├── ics ├── lollipop ├── src ├── res (リソース) └── res-public (リソース) ``` ] ??? - 例は design - 何も書いていないのはソースディレクトリ - 通常の Android Studio で作るアプリだと app/src/main/java に相当 - この下にパッケージが入って Java ファイルが入る --- class: center, middle, hero, chapter-5 # CoordinatorLayout.Behavior --- class: normal, chapter-5 # CoordinatorLayout .card[ ## CoordinatorLayout.Behavior - 子 View の挙動 - 複数の子 View 間の挙動の関係 ## すること - レイアウト - タッチ イベント処理 - 他 View との関係 ] ??? - design サポート ライブラリの肝となる ViewGroup - FAB, Snackbar や BottomSheet の機能の基礎 - Behavior を自作することができる --- class: normal, chapter-5 # ViewGroup のレイアウト .card[ ## レイアウトとは ViewGroup が子 View の大きさを測って配置する - onMeasure - 子 View の大きさを測る - 自分の大きさを決める - onLayout - 子 View を配置する ## LayoutParams その時のパラメーター ] --- class: normal, chapter-5 # CoordinatorLayout の LayoutParams .card[ - Behavior - Anchor - anchorId - anchorGravity - Keyline ] --- class: normal, chapter-5 # CoordinatorLayout の onMeasure/onLayout .card[ それぞれの個ビューについて - Behavior があれば Behavior に処理を移譲
Behavior は処理したかどうかを返す - Anchor があれば Anchor に従って処理 - Keyline があれば Keyline に従って処理 - なければ FrameLayout と同じように処理 ] --- class: normal, chapter-5 # Behavior でのレイアウト .card[ - onMeasureChild - onLayoutChild ] ??? - オーバーライドしなければデフォルト実装が false を返す --- class: normal, chapter-5 # Behavior でのタッチ イベント処理 .card[ ## 通常のタッチ イベント処理 - onTouchEvent, onInterceptTouchEvent ## ネスト スクロール系 - onStartNestedScroll, onNestedScrollAccepted - onNestedPreScroll, onNestedScroll - onStopNestedScroll - onNestedPreFling, onNestedFling ] --- class: normal, chapter-5 # Behavior と他の View との関係 .card[ ## 依存するかどうかを申告する - boolean layoutDependsOn(parent, child, dependency) ## 依存するものに変更があったとき - onDependentViewChanged, onDependentViewRemoved ] ??? - 例: FAB の Behavior は Snackbar なら layoutDependsOn で true を返す - 依存するものがレイアウトされた時、ポジションが変わった時 --- class: normal, chapter-5 # 作った Behavior を使う .card[ ```xml <android.support.design.widget.CoordinatorLayout> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" `app:layout_behavior="com.example.MyBehavior"`/> </android.support.design.widget.CoordinatorLayout> ``` ] --- class: normal, chapter-5 # カスタム View のデフォルト Behavior .card[ ```java @CoordinatorLayout.DefaultBehavior( FloatingActionButton.Behavior.class)` public class FloatingActionButton extends VisibilityAwareImageButton { // ... } ``` ] --- class: center, middle, hero, chapter-6 #
サポート ライブラリについての
ご意見・ご要望
## b.android.com