注意! この記事はQiitaにて公開されていた内容をimportしたものです。
これらの内容は場合によっては陳腐化していて役に立たなくなっていたり、有害であったり、現在の著者の主張と異なることがあります。
皆様の判断の上でご利用いただけますと幸いです(度を超してヤバいものは著者に連絡して頂ければ対応します m(_ _)m)


はじめに

Android Support Library rev.26 より Percent Support Library がdeprecatedになるため、ConstraintLayoutへの移行を行う必要があります(ただしrev.26は現在のところalpha版のため、deprecated自体が取りやめになる可能性はあるかもしれません)。

一方でPercent Support LibraryからConstraint Layoutへの変換は、グラフィカルエディタ(layout xmlを開いた画面のDesign タブ)のComponent Tree を右クリックして表示されるConvert *** to ConstraintLayout ではうまく変換できない(できたらラッキーだけどたぶん難しい)為、適切にViewの振る舞いを理解して書き直してあげる必要があります。 あと上記記事で具体的な移行方法が示されていないのもあるのですが、まぁそれはそれで。

というわけで、Percent Support LibraryをConstraintLayoutにマイグレーションする手順(の覚え書き)です。

なお、本資料で紹介するAPIは constraint-layout ver.1.0.2 準拠です。

ここで説明しないこと

ConstraintLayoutの解説そのものは省いています。あくまでPercent Support Libraryからの移行に関するポイントのみに絞っています。けれども完璧を目指したり、やや複雑なことをしているなら、ConstraintLayoutの全容を把握する必要はありそうです。

ConstraintLayoutのことをもっと知りたい方は、まずはConstraintLayoutのクラス・リファレンスを確認してください。だいたい全てそこに書かれています。日本語記事をお望みなら、Qiita内を検索してみるか、僕が最近購入した書籍ではTechBoosterさんの「Colorful Android」第2章が参考になりました。

マイグレーション・ガイド

0. appbuild.gradle の書き換え

build.gradleに記述する前に、SDK ManagerよりConstraint Layout関連ファイルを取得しておくこと。 (ちなみにSupport LibraryのバージョンとConstraintLayoutのバージョンは同じものではないので、定数定義してる場合は気をつけて)

compile "com.android.support:percent:${SUPPORT_PACKAGE_VERSION}"

compile "com.android.support.constraint:constraint-layout:${CONSTRAINT_LAYOUT_VERSION}"

1. 見た目が一致するように書き換える

とはいえ不慣れな状態からいきなりガッと書き換えるのは難しいので、どこかにダミーのlayout xmlを置き、そこでConstraintLayoutを試しながら作業すると理解がよいかと思います。

重要: ConstraintLayoutにおける layout_width, layout_height について

ConstraintLayout内ではmatch_parent は使えないので移行時には書き換える必要があります。

例えば layout_width="match_parent" 相当のものは以下のように記述できます:

android:layout_width="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"

ちなみに 0dp はConstraintLayoutでは MATCH_CONSTRAINT であると記されています。 詳しくはConstraintLayoutクラス・リファレンスの「Widgets dimension constraints」をご覧下さい。

A. アスペクト比

Percent Support Library導入で一番多い使い方ではないでしょうか。 動画プレイヤーやサムネイルなどで16:9比率でViewサイズを設定したい場合など。

Percent Support Libraryの子要素で以下のような定義をしていたとする:

android:layout_width="0dp"
android:layout_height="0dp"
app:layout_aspectRatio="178%"

これをConstraintLayoutの子要素で定義し直すと以下:

android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="16:9"

app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"

"16:9" と記述した箇所の先頭に、"H,16:9" とか "W,16:9" と記述することもできます。 H,Wのいづれも記述しない場合、親View(ConstraintLayoutそのもの)からはみ出さず、それでいてアスペクト比を維持した幅高さにしてくれます。 Hを先頭につけると、 高さ(height)を設定比率に添う形にし、幅(width)を要素がとることができる最大幅まで広げます。 Wを先頭につけると、幅(width)を設定比率に添う形にし、高さ(height)を要素がとることができる最大幅まで広げます。

B. パーセント指定の幅高さ

これもPercent Support Libraryの使われ方として多いのではないでしょうか。 例えば横画面時に6:4の比率でViewを配置したい場合など。

おいそこの古参、「LinearLayout+weight指定でおk」とかうるさいぞ

Percent Support Libraryにて以下のような定義をしていたとする:

    <android.support.percent.PercentRelativeLayout
        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">
        <TextView
            android:id="@+id/textView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@android:color/holo_red_light"
            android:gravity="center"
            android:text="Hello World!"
            
            app:layout_widthPercent="60%"
            />
        
        <TextView
            android:id="@+id/textView2"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@android:color/holo_blue_light"
            android:gravity="center"
            android:text="Sayonara World!"
            
            android:layout_toRightOf="@id/textView"
            app:layout_widthPercent="40%"
            />
    </android.support.percent.PercentRelativeLayout>

これをConstraintLayoutの子要素で定義し直すと以下:

    <android.support.constraint.ConstraintLayout 
        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">
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@android:color/holo_red_light"
            android:gravity="center"
            android:text="Hello World!"
        
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toLeftOf="@+id/guideline"
            app:layout_constraintTop_toTopOf="parent"
            />
        
        <TextView
            android:id="@+id/textView2"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@android:color/holo_blue_light"
            android:gravity="center"
            android:text="Sayonara World!"
        
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toRightOf="@+id/guideline"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            />
    
        <android.support.constraint.Guideline
            android:id="@+id/guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.6"/>
    
    </android.support.constraint.ConstraintLayout>

キーポイントは Guideline で、これ自体はViewとして何らかの表示をするものではありません。ConstraintLayoutにおいて文字通りガイドライン線をつくり、ガイドライン線に沿ってViewを配置できるようになります。 グラフィカルエディタからはConstraintLayout上で右クリックし、メニュー内の該当項目を選ぶことでGuidelineを作成できます。 orientationでvertical(縦線)、horizontal(横線)指定をします。 layout_constraintGuideはViewのstartもしくはendからの長さでも指定できます(それぞれプロパティあり)。

個人的な意見として、これまでのweight指定や子要素へのpercent指定よりかは、Guidelineで制約を制御できるのは画期的で、仕様変更時(例えば6:4を7:3にしてほしいとか)のヒューマンエラーも減らせるし良さそうに見えますが、欠点は慣れ親しんだテクニックの方が何も見ないでも書けるから、わざわざConstraintLayout使うまでもないって事だな!

ところで、6:4とかではなく等間隔に3つ以上のViewを配置したい場合は、Chainを検討してください。そっちのほうがGuidelineでやるよりシンプルです。 詳しくはConstraintLayoutのクラス・リファレンスの「Chains」の項目を参照。 (でもそれならネスト深くなってもLinearLayout+weightのほうが楽よなぁ)

まとめ

ConstraintLayoutを使うかどうかはともかく、PercentSupportLibraryの移行がんばりましょう。 ただなんでか知らないけど個人的なConstraintLayoutへの信用が高くないのでなぁ

Appendix. 参考文献