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での外観であり、私が期待しているものです。
<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と同じように見えるはずですが、異なります。
例3-ConstraintLayoutバージョン1.1.0-beta4と開始マージンの使用
これと同じレイアウトを取り、8dp
の開始マージンを右側のテキストビュー(tvRight
)に追加すると、中央と右側のテキストビューの間だけでなく、左側と左側の間にもマージンが再表示されます中央のテキストビューはマージンを変更していませんが。
これは、突然設定された以前に設定されたマージンだけではありません。右端のテキストビューの開始マージンを「48 dp」に設定すると、左側と中央のテキストビューの間に48dp
マージンのように見えるものが表示されます。
<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
チェーンでマージンはどのように処理されますか?チェーンマージンの処理方法に変更はありますか、それとも何か不足していますか?私はこのすべてを説明する説明またはいくつかのドキュメントへの参照を探しています。
この正確な質問に対する信頼できる回答を提供するドキュメントは見つかりません。ただし、 [ConstraintLayout
のAPIドキュメント にマージンに関する少しの議論があります:
サイドマージンが設定されている場合、それらは対応する制約に適用されます(存在する場合)
チェーンの特定のインスタンスでは、各ビュー間に双方向の制約があります。つまり、ビューAの終点がビューBの始点に制約されるだけでなく、ビューBの始点もビューAの終点に制約されます。
投稿されたレイアウトでは、ビューAには終了制約と終了マージンがありますが、ビューBには開始制約があり、開始マージンはありません。私の知る限り、これはレイアウトに競合するルールがあることを意味します(ビューAはビューBから8 dp離れたところにありたいが、ビューBはビューAから0 dp離れたいところにあります)。おそらく、異なるバージョンのConstraintLayoutライブラリは、(a)これが競合としてカウントされるかどうかを判断し、(b)競合を解決するための異なる戦略を持っています。
実験により、さまざまなバージョンのConstraintLayoutライブラリでチェーンで動作するマージンを見つける方法を次に示します。
チェーン内の各ビューのサイドマージンは、チェーン内の他のビューに依存または影響しません。これには(少なくとも)動作に2つの目に見える影響があります。まず、1つのビューにマージンを追加すると、そのビューのマージンに関係なく、その量だけ他のビューが押し出されます。次に、1つのビューにマージンを追加しても、チェーンのさらに下のビューのマージンには影響しません(たとえば、最初のビューに8 dpのエンドマージンを設定しても、2番目と3番目のビューの間に8 dp相当のスペースが表示されることはありません)。
チェーン内の各ビューのサイドマージンは、チェーン内の他のビューに依存し、影響を与えます。この場合も、動作に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:
v1.1.0-beta4:
これは、ライブラリのバージョン間の2つの違いを示しています。繰り返しますが、私はこれをすべて説明する公式のドキュメントを完全に見つけることはできませんでしたが、実験に基づいただけで本当のようです。
ベンP.の答えを拡張して、ConstraintLayout
チェーンのマージンに関して以下を決定しました。この情報はConstraintLayout
バージョン1.1.0-beta4に適用されます。
チェーン内では、すべての開始マージン(Android:layout_marginStart
)が尊重されます。これは、ビュー間の間隔が、指定された開始マージン以上になることを意味します。ただし、以下で説明するように、間隔は大きくなる場合があります。
終了マージン(Android:layout_marginEnd
)は関連性がなく、無視されているようです。これは、チェーンの最後にあるビューの最後のマージンには適用されません。チェーンを作成するためにビューが相互にリンクされている内側のマージンにのみ適用されます。
チェーンが制約内で中央に配置されている場合、チェーンは、チェーンの頭の開始マージンとチェーンの尾の終了マージンの中央に配置されます。
以下の例では、ビュー「A」、「D」、「G」は親の開始に制限されています。ビュー "C"、 "F"、および "I"は親の端に制限されています。
packed
チェーンスタイルが「パック」の場合、すべてのビューは、指定された開始マージンで区切られて、エンドツーエンドで配置されます。ビュー間の間隔は、開始マージンの定義方法によって異なります。次の画像では、ビューの幅はmatch_constraints
で、マージンは示されているように設定されています。
ビューの幅がmatch_constraints
以外に設定されている場合でも、ビューは指定されたマージンでパックされますが、チェーンはチェーンのヘッドの開始マージンとチェーンのテールの終了マージンの中央に配置されます。
Android Studioデザイナーはこれと同じ解釈を持っているので、エンドビューに添付されるエンドマージンを考慮する代わりに、私はこの解釈に至りました:
spread
「スプレッド」チェーンスタイルでは、すべてのビューが開始拘束と終了拘束の間に分配され、各ビューの前後のスペースは同じであり、定義された最大の開始マージンに等しくなります。各ビューの幅がmatch_constraints
の場合、すべてのビューはデフォルトで同じ幅になります。
spread_inside
チェーンのspread_inside
スタイルは、チェーンの最初のビューを取得し、開始マージンを守りながら開始制約にアンカーします。エンドビューは、エンドマージンを維持しながら、エンドコンストレイントにアンカーされます。内部ビューは、spread
チェーンのように、ビュー間に等間隔で配置されます。
以下は、さまざまなマージンが設定された同じレイアウトです。ビュー「F」と「I」の開始マージンは8dp
に設定されていますが、ギャップは16dp
に拡大しています。ビュー「G」、「H」、および「I」は、幅が同じではないように見えますが、すべて同じ幅です。
このレイアウトのXMLは、この投稿の最後にあります。
重要ですが、それほど重要ではありません。ビューの幅がmatch_constraints
で、すべてのマージンがゼロの場合、さまざまなチェーンタイプは区別できません。
上記の情報は、垂直チェーンにも適用されます。 Android:layout_marginTop
をAndroid:layout_marginStart
に、Android:layout_marginBottom
をAndroid: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>