Android
AndroidDay 18

PercentLayoutがDeprecatedになったのでConstraintLayoutで比率指定をする

Android SDK 26が出まして、PercentLayoutが非推奨になるとの発表がありました。
以前の記事でPercentRelativeLayoutの使いどころメモなどで便利に使っていたので、その代替を探さなければなりません。

条件は前回と同じでカード全体は画面幅、span数によって幅が変わる。
右側のImageViewの幅はカードの半分で、アスペクト比は固定。
左側の日付の位置はカードの下側に沿う形で、右側のImageViewの高さに依存する。
というようなViewの作成にConstraintLayoutを利用することができます。

build.gradleに次のライブラリを追加します。

build.gradle
implementation 'com.android.support.constraint:constraint-layout:1.0.2'

ConstraintLayoutはSupportLibraryの仲間として扱われていますが、バージョニングについては異なるルールで運用されているようです。
https://dl.google.com/dl/android/maven2/com/android/support/constraint/group-index.xml

今回はConstraintLayoutをルートとしてレイアウトを作成します。

layout.xml
<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
    android:background="#fff">

    <android.support.constraint.Guideline
        android:id="@+id/vertical_center_guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintGuide_percent="0.5"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#999"
        app:layout_constraintDimensionRatio="h,8:5"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@id/vertical_center_guideline" />

    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="タイトル"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@id/vertical_center_guideline"/>

    <TextView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="YYYY年MM月dd日"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintBottom_toBottomOf="@id/image_view"
        app:layout_constraintEnd_toStartOf="@id/vertical_center_guideline"/>

</android.support.constraint.ConstraintLayout>

ConstraintLayoutに対する割合を指定したい場合Guidelineを利用します。
orientationでGuidelineの配置方向を指定し、layout_constraintGuide_percentで親レイアウトに対する配置位置の割合をfloatで指定します。

ImageViewの幅はGuidelineの右側にしたいので、layout_constraintStart_toStartOfにGuidelineのid、layout_constraintEnd_toEndOfparentを指定します。
レイアウトの大きさを比率で指定したい場合、layout_constraintDimensionRatioを利用します。
ImageViewの幅に対して高さを決定したい場合はh,8:5というように高さ(h)か幅(w)のどちらを計算したいかと幅:高さの比率で記述します。

TextViewの幅はGuildlineの左側に制限したいので、TextViewのlayout_constraintEnd_toStartOfでGuidelineのidを指定します。
日付のTextViewはImageViewの底辺に沿う位置にしたいのでlayout_constraintBottom_toBottomOfでImageViewのidを指定します。

LayoutEditorでは次のように表示されます。
layout_editor

PercentRelativeLayoutと同様の階層の深さで、レイアウト時点でサイズ計算が行われるので表示時の再描画なども起きません。
DeprecatedになってしまったPercentRelativeLayoutを利用している場合は無条件にConstraintLayoutに書き換えることをおすすめします。