web-dev-qa-db-ja.com

ConstraintLayout 1.1.0(ベータ)でチェーンのマージンがどのように機能するか

ConstraintLayoutバージョン1.1.0-beta4に変更してから、いくつかのレイアウトが爆発しました。変更を加える前に、ConstraintLayoutチェーンでマージンがどのように機能するかを理解したいと思います。以下では、ConstraintLayoutバージョン1.0.2のレイアウトをバージョン1.1.0-beta4と比較していますが、この問題は1.1.0-beta2で最初に発生したと思います。

私の目標は、第1と第2のテキストビューと第2と第3のテキストビューの間にギャップがあるテキストビューを画面全体に広げることです。背景はこれらのマージンに表示されます。これを行うには、水平チェーンを作成し、左のテキストビューから中央のテキストビューまでの端の余白と、中央のテキストビューから右のテキストビューまでの端の余白を指定します。水平チェーンスタイルはspread_insideです。

例1-ConstraintLayoutバージョン1.0.2を使用する

これはバージョン1.0.2での外観であり、私が期待しているものです。

enter image description here

<Android.support.constraint.ConstraintLayout 
    Android:layout_width="match_parent"
    Android:layout_height="50dp"
    Android:background="@Android:color/holo_blue_light">

    <TextView
        Android:id="@+id/tvLeft"
        Android:layout_width="0dp"
        Android:layout_height="35dp"
        Android:layout_marginEnd="8dp"
        Android:background="@Android:color/white"
        Android:gravity="center"
        Android:text="Text1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/tvCenter"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="HardcodedText" />

    <TextView
        Android:id="@+id/tvCenter"
        Android:layout_width="0dp"
        Android:layout_height="35dp"
        Android:layout_marginEnd="8dp"
        Android:background="@Android:color/white"
        Android:gravity="center"
        Android:text="Text2"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/tvRight"
        app:layout_constraintStart_toEndOf="@+id/tvLeft"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="HardcodedText" />

    <TextView
        Android:id="@+id/tvRight"
        Android:layout_width="0dp"
        Android:layout_height="35dp"
        Android:background="@Android:color/white"
        Android:gravity="center"
        Android:text="Text3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/tvCenter"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="HardcodedText" />

</Android.support.constraint.ConstraintLayout>

例2-ConstraintLayoutバージョン1.1.0-beta4の使用

これと同じレイアウトは、ConstraintLayoutのバージョン1.1.0-beta4では次のようになります。マージンが消えていることに注意してください。これは例1と同じように見えるはずですが、異なります。

enter image description here

例3-ConstraintLayoutバージョン1.1.0-beta4と開始マージンの使用

これと同じレイアウトを取り、8dpの開始マージンを右側のテキストビュー(tvRight)に追加すると、中央と右側のテキストビューの間だけでなく、左側と左側の間にもマージンが再表示されます中央のテキストビューはマージンを変更していませんが。

[image]

これは、突然設定された以前に設定されたマージンだけではありません。右端のテキストビューの開始マージンを「48 dp」に設定すると、左側と中央のテキストビューの間に48dpマージンのように見えるものが表示されます。

enter image description here

<Android.support.constraint.ConstraintLayout 
    Android:layout_width="match_parent"
    Android:layout_height="50dp"
    Android:background="@Android:color/holo_blue_light">

<!-- TextViews tvLeft & tvRight not shown but are the same as above.-->

<TextView
    Android:id="@+id/tvRight"
    Android:layout_width="0dp"
    Android:layout_height="35dp"
    Android:layout_marginStart="48dp"
    Android:background="@Android:color/white"
    Android:gravity="center"
    Android:text="Text3"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toEndOf="@+id/tvCenter"
    app:layout_constraintTop_toTopOf="parent"
    tools:ignore="HardcodedText" />

</Android.support.constraint.ConstraintLayout>  

したがって、私の質問は、「なぜこれらの結果が表示されるのですか?」 ConstraintLayoutチェーン、特にspread_insideチェーンでマージンはどのように処理されますか?チェーンマージンの処理方法に変更はありますか、それとも何か不足していますか?私はこのすべてを説明する説明またはいくつかのドキュメントへの参照を探しています。

12
Cheticamp

この正確な質問に対する信頼できる回答を提供するドキュメントは見つかりません。ただし、 [ConstraintLayoutのAPIドキュメント にマージンに関する少しの議論があります:

サイドマージンが設定されている場合、それらは対応する制約に適用されます(存在する場合)

チェーンの特定のインスタンスでは、各ビュー間に双方向の制約があります。つまり、ビューAの終点がビューBの始点に制約されるだけでなく、ビューBの始点もビューAの終点に制約されます。

投稿されたレイアウトでは、ビューAには終了制約と終了マージンがありますが、ビューBには開始制約があり、開始マージンはありません。私の知る限り、これはレイアウトに競合するルールがあることを意味します(ビューAはビューBから8 dp離れたところにありたいが、ビューBはビューAから0 dp離れたいところにあります)。おそらく、異なるバージョンのConstraintLayoutライブラリは、(a)これが競合としてカウントされるかどうかを判断し、(b)競合を解決するための異なる戦略を持っています。

実験により、さまざまなバージョンのConstraintLayoutライブラリでチェーンで動作するマージンを見つける方法を次に示します。

バージョン1.0.2

チェーン内の各ビューのサイドマージンは、チェーン内の他のビューに依存または影響しません。これには(少なくとも)動作に2つの目に見える影響があります。まず、1つのビューにマージンを追加すると、そのビューのマージンに関係なく、その量だけ他のビューが押し出されます。次に、1つのビューにマージンを追加しても、チェーンのさらに下のビューのマージンには影響しません(たとえば、最初のビューに8 dpのエンドマージンを設定しても、2番目と3番目のビューの間に8 dp相当のスペースが表示されることはありません)。

バージョン1.1.0-beta4

チェーン内の各ビューのサイドマージンは、チェーン内の他のビューに依存し、影響を与えます。この場合も、動作に2つの目に見える影響があります。まず、1つのビューにマージンを追加しても、同じ量のマージンがない限り、他のビューは押し出されません*。次に、チェーンの1番目と2番目のビューの間にマージンを追加すると、チェーンの2番目と3番目のビューの間隔にも影響します**。

*:1.1.0-beta4では、開始マージンだけでビューをプッシュすることができますが、終了マージンだけでは効果がないようです。とにかく、私はマージンを一致させることをお勧めします。

**:Isuspectこれは、チェーンが「スペース」を均等に割り当てようとしているためです。ビューAとBの間のマージンによりギャップが生じます。チェーンが一定の間隔を強制したいので、ビューBとCの間に同様のギャップが追加されます。

例:

下がったところに、元のレイアウトと同じですが、余白が少し変更されています。他のすべての属性は変更しません。

<Android.support.constraint.ConstraintLayout>

    <TextView
        Android:layout_marginEnd="8dp"/>

    <TextView
        Android:layout_marginStart="8dp"/>

    <TextView/>

</Android.support.constraint.ConstraintLayout>

v1.0.2:

enter image description here

v1.1.0-beta4:

enter image description here

これは、ライブラリのバージョン間の2つの違いを示しています。繰り返しますが、私はこれをすべて説明する公式のドキュメントを完全に見つけることはできませんでしたが、実験に基づいただけで本当のようです。

8
Ben P.

ベンP.の答えを拡張して、ConstraintLayoutチェーンのマージンに関して以下を決定しました。この情報はConstraintLayoutバージョン1.1.0-beta4に適用されます。

一般的な観察

  1. チェーン内では、すべての開始マージン(Android:layout_marginStart)が尊重されます。これは、ビュー間の間隔が、指定された開始マージン以上になることを意味します。ただし、以下で説明するように、間隔は大きくなる場合があります。

  2. 終了マージン(Android:layout_marginEnd)は関連性がなく、無視されているようです。これは、チェーンの最後にあるビューの最後のマージンには適用されません。チェーンを作成するためにビューが相互にリンクされている内側のマージンにのみ適用されます。

  3. チェーンが制約内で中央に配置されている場合、チェーンは、チェーンの頭の開始マージンとチェーンの尾の終了マージンの中央に配置されます。

以下の例では、ビュー「A」、「D」、「G」は親の開始に制限されています。ビュー "C"、 "F"、および "I"は親の端に制限されています。

チェーンスタイル:packed

チェーンスタイルが「パック」の場合、すべてのビューは、指定された開始マージンで区切られて、エンドツーエンドで配置されます。ビュー間の間隔は、開始マージンの定義方法によって異なります。次の画像では、ビューの幅はmatch_constraintsで、マージンは示されているように設定されています。

enter image description here

ビューの幅がmatch_constraints以外に設定されている場合でも、ビューは指定されたマージンでパックされますが、チェーンはチェーンのヘッドの開始マージンとチェーンのテールの終了マージンの中央に配置されます。

enter image description here

Android Studioデザイナーはこれと同じ解釈を持っているので、エンドビューに添付されるエンドマージンを考慮する代わりに、私はこの解釈に至りました:

enter image description here

チェーンスタイル:spread

「スプレッド」チェーンスタイルでは、すべてのビューが開始拘束と終了拘束の間に分配され、各ビューの前後のスペースは同じであり、定義された最大の開始マージンに等しくなります。各ビューの幅がmatch_constraintsの場合、すべてのビューはデフォルトで同じ幅になります。

チェーンスタイル:spread_inside

チェーンのspread_insideスタイルは、チェーンの最初のビューを取得し、開始マージンを守りながら開始制約にアンカーします。エンドビューは、エンドマージンを維持しながら、エンドコンストレイントにアンカーされます。内部ビューは、spreadチェーンのように、ビュー間に等間隔で配置されます。

enter image description here


以下は、さまざまなマージンが設定された同じレイアウトです。ビュー「F」と「I」の開始マージンは8dpに設定されていますが、ギャップは16dpに拡大しています。ビュー「G」、「H」、および「I」は、幅が同じではないように見えますが、すべて同じ幅です。

このレイアウトのXMLは、この投稿の最後にあります。

enter image description here

重要ですが、それほど重要ではありません。ビューの幅がmatch_constraintsで、すべてのマージンがゼロの場合、さまざまなチェーンタイプは区別できません。

enter image description here

上記の情報は、垂直チェーンにも適用されます。 Android:layout_marginTopAndroid:layout_marginStartに、Android:layout_marginBottomAndroid:layout_marginEndに置き換えます。

レイアウト

<Android.support.constraint.ConstraintLayout 
    Android:id="@+id/constraintLayout"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="@Android:color/holo_blue_light">

    <TextView
        Android:id="@+id/heading1"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="16dp"
        Android:text="packed, match_constraints"
        Android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        Android:textSize="16sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="HardcodedText" />

    <TextView
        Android:id="@+id/textA"
        Android:layout_width="0dp"
        Android:layout_height="35dp"
        Android:layout_marginTop="8dp"
        Android:background="@Android:color/white"
        Android:gravity="center"
        Android:text="A"
        Android:textColor="@Android:color/black"
        app:layout_constraintEnd_toStartOf="@+id/textB"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/heading1"
        tools:ignore="HardcodedText" />

    <View
        Android:layout_width="8dp"
        Android:layout_height="35dp"
        Android:background="#ff00cc"
        app:layout_constraintEnd_toStartOf="@id/textB"
        app:layout_constraintTop_toTopOf="@id/textB" />

    <TextView
        Android:id="@+id/textB"
        Android:layout_width="0dp"
        Android:layout_height="35dp"
        Android:layout_marginStart="8dp"
        Android:background="@Android:color/darker_gray"
        Android:gravity="center"
        Android:text="B"
        Android:textColor="@Android:color/white"
        app:layout_constraintEnd_toStartOf="@+id/textC"
        app:layout_constraintStart_toEndOf="@+id/textA"
        app:layout_constraintTop_toTopOf="@+id/textA"
        tools:ignore="HardcodedText" />

    <View
        Android:id="@+id/view16dpOnC"
        Android:layout_width="16dp"
        Android:layout_height="35dp"
        Android:background="#fffb00"
        app:layout_constraintEnd_toStartOf="@id/textC"
        app:layout_constraintTop_toTopOf="@+id/textC" />

    <TextView
        Android:id="@+id/textC"
        Android:layout_width="0dp"
        Android:layout_height="35dp"
        Android:layout_marginStart="16dp"
        Android:background="@Android:color/white"
        Android:gravity="center"
        Android:text="C"
        Android:textColor="@Android:color/black"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/textB"
        app:layout_constraintTop_toTopOf="@+id/textA"
        tools:ignore="HardcodedText" />

    <TextView
        Android:id="@+id/heading2"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="8dp"
        Android:text="spread, match_constraints"
        Android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        Android:textSize="16sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/textA"
        tools:ignore="HardcodedText" />

    <View
        Android:layout_width="16dp"
        Android:layout_height="35dp"
        Android:background="#00ff19"
        app:layout_constraintEnd_toStartOf="@id/textD"
        app:layout_constraintTop_toTopOf="@id/textD" />

    <TextView
        Android:id="@+id/textD"
        Android:layout_width="0dp"
        Android:layout_height="35dp"
        Android:layout_marginTop="8dp"
        Android:background="@Android:color/white"
        Android:gravity="center"
        Android:text="D"
        Android:textColor="@Android:color/black"
        app:layout_constraintEnd_toStartOf="@+id/textE"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/heading2"
        tools:ignore="HardcodedText" />

    <View
        Android:layout_width="16dp"
        Android:layout_height="35dp"
        Android:background="#fffb00"
        app:layout_constraintEnd_toStartOf="@id/textE"
        app:layout_constraintTop_toTopOf="@id/textE" />

    <TextView
        Android:id="@+id/textE"
        Android:layout_width="0dp"
        Android:layout_height="35dp"
        Android:layout_marginStart="16dp"
        Android:background="@Android:color/darker_gray"
        Android:gravity="center"
        Android:text="E"
        Android:textColor="@Android:color/white"
        app:layout_constraintEnd_toStartOf="@+id/textF"
        app:layout_constraintStart_toEndOf="@+id/textD"
        app:layout_constraintTop_toTopOf="@+id/textD"
        tools:ignore="HardcodedText" />

    <View
        Android:layout_width="8dp"
        Android:layout_height="35dp"
        Android:background="#003cff"
        app:layout_constraintStart_toEndOf="@id/textE"
        app:layout_constraintTop_toTopOf="@+id/textE" />

    <View
        Android:layout_width="8dp"
        Android:layout_height="35dp"
        Android:background="#ff00cc"
        app:layout_constraintEnd_toStartOf="@id/textF"
        app:layout_constraintTop_toTopOf="@id/textF" />

    <TextView
        Android:id="@+id/textF"
        Android:layout_width="0dp"
        Android:layout_height="35dp"
        Android:layout_marginStart="8dp"
        Android:background="@Android:color/white"
        Android:gravity="center"
        Android:text="F"
        Android:textColor="@Android:color/black"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/textE"
        app:layout_constraintTop_toTopOf="@+id/textD"
        tools:ignore="HardcodedText" />

    <View
        Android:layout_width="16dp"
        Android:layout_height="35dp"
        Android:background="#00ff19"
        app:layout_constraintStart_toEndOf="@id/textF"
        app:layout_constraintTop_toTopOf="@id/textF" />

    <TextView
        Android:id="@+id/heading3"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginTop="8dp"
        Android:text="spread_inside, match_constraints"
        Android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        Android:textSize="16sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/textD"
        tools:ignore="HardcodedText" />

    <View
        Android:layout_width="8dp"
        Android:layout_height="35dp"
        Android:background="#003cff"
        app:layout_constraintEnd_toStartOf="@id/textG"
        app:layout_constraintTop_toTopOf="@+id/textG" />

    <TextView
        Android:id="@+id/textG"
        Android:layout_width="0dp"
        Android:layout_height="35dp"
        Android:layout_marginStart="8dp"
        Android:layout_marginTop="8dp"
        Android:background="@Android:color/white"
        Android:gravity="center"
        Android:text="G"
        Android:textColor="@Android:color/black"
        app:layout_constraintEnd_toStartOf="@+id/textH"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/heading3"
        tools:ignore="HardcodedText" />

    <View
        Android:layout_width="16dp"
        Android:layout_height="35dp"
        Android:background="#fffb00"
        app:layout_constraintEnd_toStartOf="@id/textH"
        app:layout_constraintTop_toTopOf="@id/textH" />

    <TextView
        Android:id="@+id/textH"
        Android:layout_width="0dp"
        Android:layout_height="35dp"
        Android:layout_marginStart="16dp"
        Android:background="@Android:color/darker_gray"
        Android:gravity="center"
        Android:text="H"
        Android:textColor="@Android:color/white"
        app:layout_constraintEnd_toStartOf="@+id/textI"
        app:layout_constraintStart_toEndOf="@+id/textG"
        app:layout_constraintTop_toTopOf="@+id/textG"
        tools:ignore="HardcodedText" />

    <View
        Android:layout_width="8dp"
        Android:layout_height="35dp"
        Android:background="#003cff"
        app:layout_constraintStart_toEndOf="@id/textH"
        app:layout_constraintTop_toTopOf="@id/textH" />

    <View
        Android:layout_width="8dp"
        Android:layout_height="35dp"
        Android:background="#ff00cc"
        app:layout_constraintEnd_toStartOf="@id/textI"
        app:layout_constraintTop_toTopOf="@id/textI" />

    <TextView
        Android:id="@+id/textI"
        Android:layout_width="0dp"
        Android:layout_height="35dp"
        Android:layout_marginStart="8dp"
        Android:background="@Android:color/white"
        Android:gravity="center"
        Android:text="I"
        Android:textColor="@Android:color/black"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/textH"
        app:layout_constraintTop_toTopOf="@+id/textG"
        tools:ignore="HardcodedText" />

    <View
        Android:layout_width="8dp"
        Android:layout_height="35dp"
        Android:background="#ff00cc"
        Android:visibility="gone"
        app:layout_constraintEnd_toStartOf="@id/textC"
        app:layout_constraintTop_toTopOf="@id/textC" />

    <View
        Android:id="@+id/view8dp"
        Android:layout_width="8dp"
        Android:layout_height="35dp"
        Android:layout_marginStart="24dp"
        Android:background="#ff00cc"
        app:layout_constraintBottom_toTopOf="@id/view8dpGap"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textG"
        app:layout_constraintVertical_bias="0.100000024"
        app:layout_constraintVertical_chainStyle="packed" />

    <TextView
        Android:id="@+id/text8dp"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginStart="16dp"
        Android:text="8dp start margin"
        app:layout_constraintBottom_toBottomOf="@+id/view8dp"
        app:layout_constraintStart_toEndOf="@id/view8dp"
        app:layout_constraintTop_toTopOf="@+id/view8dp"
        tools:ignore="HardcodedText" />

    <View
        Android:id="@+id/view8dpGap"
        Android:layout_width="8dp"
        Android:layout_height="35dp"
        Android:layout_marginStart="24dp"
        Android:layout_marginTop="8dp"
        Android:background="#003cff"
        app:layout_constraintBottom_toTopOf="@+id/view16dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/view8dp" />

    <TextView
        Android:id="@+id/textView"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginStart="16dp"
        Android:text="8dp gap not defined by start margin"
        app:layout_constraintBottom_toBottomOf="@+id/view8dpGap"
        app:layout_constraintStart_toEndOf="@+id/view8dpGap"
        app:layout_constraintTop_toTopOf="@+id/view8dpGap"
        tools:ignore="HardcodedText" />

    <View
        Android:id="@+id/view16dp"
        Android:layout_width="17dp"
        Android:layout_height="35dp"
        Android:layout_marginStart="24dp"
        Android:layout_marginTop="8dp"
        Android:background="#fffb00"
        app:layout_constraintBottom_toTopOf="@+id/view16dpGap"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/view8dpGap" />

    <TextView
        Android:id="@+id/text16dp"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginStart="8dp"
        Android:text="16dp start margin"
        app:layout_constraintBottom_toBottomOf="@+id/view16dp"
        app:layout_constraintStart_toEndOf="@+id/view16dp"
        app:layout_constraintTop_toTopOf="@+id/view16dp"
        tools:ignore="HardcodedText" />

    <View
        Android:id="@+id/view16dpGap"
        Android:layout_width="17dp"
        Android:layout_height="35dp"
        Android:layout_marginStart="24dp"
        Android:layout_marginTop="8dp"
        Android:background="#00ff19"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/view16dp" />

    <TextView
        Android:id="@+id/text16dpGap"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_marginStart="8dp"
        Android:text="16dp gap not defined by start margin"
        app:layout_constraintBottom_toBottomOf="@+id/view16dpGap"
        app:layout_constraintStart_toEndOf="@+id/view16dpGap"
        app:layout_constraintTop_toTopOf="@+id/view16dpGap"
        tools:ignore="HardcodedText" />

</Android.support.constraint.ConstraintLayout>
4
Cheticamp