Edited at

ConstraintLayoutでwrap_contentしつつmatch_constraintする

ConstraintLayoutでwrap_contentしつつmatch_constraintする方法が分からなくて困っていたのでメモ。

ConstraintLayout 1.1.2 時点での書き方です。


wrap_contentしつつmatch_constraintが必要なパターン

これが必要なのは、画面がDialogFragment※で、ConstraintLayoutの中にScrollViewがあり、その中に巨大なViewがあるパターンです。

通常はScrollViewをmatch_constraintして解決すると思いますが、画面がダイアログの場合にmatch_constraintすると表示されません。

※今回はAppCompatDialogFragmentのonCreateDialogでinflate、setViewしています。


<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".BlankFragment">

<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="タイトル"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<ScrollView
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView">

<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
</ScrollView>

</android.support.constraint.ConstraintLayout>

Android StudioのPreviewだと正常ですが、実際動かすとタイトルだけになります。

Screen Shot 2018-08-28 at 0.33.17.png

Screenshot_1535383924.png


解決策

ScrollViewにwrap_contentを指定しつつ、layout_constrainedHeight="true"を付けます。


<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".BlankFragment">

<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="タイトル"
android:textAppearance="@style/TextAppearance.AppCompat.Headline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<ScrollView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
app:layout_constrainedHeight="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView">

<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n Hello World!\n"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
</ScrollView>

</android.support.constraint.ConstraintLayout>

期待通りに表示されます。

Screenshot_1535384127.png


古い書き方

以前はScrollViewをmatch_constraintしつつ、layout_constraintHeight_defaultでwrapを指定する方法でした。

こちらはdeprecatedになっています。


横方向に適用したい

横方向に適用する場合は、heightをwidthに書き換えてください。


参考

android - Wrap_content view inside a ConstraintLayout stretches outside the screen - Stack Overflow

https://stackoverflow.com/a/40881429