Ответ 1
ОБНОВЛЕНИЕ ИЮЛЬ 2018:
Если вы используете ConstraintLayout 1.1.0
, правильное свойство - app:layout_constrainedWidth="true"
вместо старого app:layout_constraintWidth_default="wrap"
(и аналог высоты)
ОБНОВЛЕНИЕ НОЯБРЯ 2017
Я использую Constraint Layouts 1.0.2, и я нашел менее вложенное решение, используя app:layout_constraintWidth_default="wrap"
(свойство, которое было введено в 1.0.0, но бета-версия, которую использовал этот пост, не имело).
Вместо FrameLayout
который содержит LinearLayout
, теперь вы можете удалить все это и сделать это следующим образом:
<android.support.constraint.ConstraintLayout
android:id="@+id/new_way_container"
android:layout_height="wrap_content"
android:layout_width="0dp" // THIS GUY USES ALL THE WIDTH.
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:ellipsize="end"
android:id="@+id/some_text"
android:layout_height="wrap_content"
android:layout_width="0dp" //NO WRAP CONTENT, USE CONSTRAINTS
android:lines="1"
android:maxLines="1"
app:layout_constraintEnd_toStartOf="@+id/disclosure_arrow"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintHorizontal_chainStyle="packed" //CHAIN IT for biasing.
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="wrap" /> //THIS IS THE KEY THAT WILL CAUSE THIS TO WORK
<ImageView
android:id="@+id/disclosure_arrow"
android:layout_height="wrap_content"
android:layout_width="10dp"
app:layout_constraintBottom_toTopOf="@id/some_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/some_text"
app:layout_constraintTop_toBottomOf="@id/some_text"
app:srcCompat="@drawable/your_vector_image" />
</android.support.constraint.ConstraintLayout>
Это эффективно делает именно то, что я хочу, без хаков или рекомендаций или жестко закодированных размеров.
TextView будет использовать размер, предоставленный Ограничениями (что при нормальных обстоятельствах будет означать, что он либо будет неправильным, либо будет выходить за пределы "родительского"), но благодаря новому атрибуту эти ограничения могут быть согнуты/нарушены, если содержимое меньше/больше
Я должен сказать, что это работает намного лучше чем Приоритеты iOS. (По крайней мере, мне намного легче понять это). Недурно для Google на этом :)
СТАРЫЙ ОТВЕТ (если он вам все еще нужен).
Основываясь на ответе Николаса Роарда, я собирался создать собственный контейнер, который в основном вычислял бы доступное пространство, и программно устанавливал maxWidth в TextView. Вместо того, чтобы добавить в проект другой класс, unit тест, возможный набор ошибок и т.д., Я попробовал несколько менее эффективный способ вложения нескольких макетов; учитывая, что мы вкладывали макеты с эпохи рассвета и что это не будет отображаться ни в одном прокручиваемом списке, ни слишком много (или вообще не двигались), а также что я использую ConstraintLayouts для выравнивания большей части иерархии (как никогда раньше) !), тогда я не думаю, что небольшое вложение, пока это не будет лучше поддержано, это плохо.
Итак, в основном я использовал FrameLayout, который по своему дизайну оптимизирован (или думал), чтобы иметь одного ребенка (хотя он может содержать больше). Это FrameLayout, к которому применяются правила ConstraintLayout:
<FrameLayout
android:id="@+id/hostTextWithCaretContainer"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent">
<!-- MY CONTENT GOES HERE -->
</FrameLayout>
Так что в моем реальном приложении этот FrameLayout находится внутри другого ConstraintLayout, у которого есть значок слева и некоторые другие вещи, но ради этого примера представьте, что вам нужно "закрепить" левую/правую часть этого FrameLayout в любом месте, где вы находитесь. хочу занять. В этом примере вы можете видеть, что я использую parent
во всех ограничениях, но могут быть другие виджеты слева и справа от этого FrameLayout; благодаря магии ConstraintLayout это займет все доступное пространство.
Теперь вот вторая часть уловки... так как ConstraintLayout гарантирует, что FrameLayout будет использовать "все пространство", которое у нас есть, и никогда больше (или меньше), теперь я могу использовать LinearLayout внутри… вот так…
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/textView"
android:layout_height="wrap_content"
android:layout_width="0dp"
tools:text="Some Text"
android:text="Some Text"
android:textAlignment="viewStart"
android:layout_gravity="center_vertical"
android:gravity="start"
android:ellipsize="end"
android:maxLines="1"
android:layout_weight="1"/>
<ImageView
android:id="@+id/caret"
android:layout_width="8dp"
android:layout_height="8dp"
app:srcCompat="@drawable/ic_selection"
android:contentDescription=""
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp" />
</LinearLayout>
Проницательные читатели заметят, что у LinearLayout есть wrap_content
, что очень важно для того, чтобы дочерний TextView мог иметь ширину 0dp и weight
1, что означает, что он займет все доступное свободное пространство после того, как все другие виджеты вычислили свою ширину,
В данном конкретном случае, а другой ребенок (ImageView) caret
не имеет указанный веса и фиксированную ширину, поэтому TextView не придется делить/разделить свободное пространство с кем - либо, и он может принять все это (но только свободное пространство, помните, его ширина составляет 0dp).
Этот менее эффективный подход позволяет добиться именно того, чего я хотел, хотя и с меньшим количеством ConstraintLayout Magic, если хотите.
С другой стороны, мне не нужно было создавать пользовательское представление, выполнять математику и выполнять requestLayout()
после того, как все мои вычисления были выполнены; этот менее эффективный подход будет/должен масштабироваться, и пока ConstraintLayout не предложит правильную альтернативу, этого может быть достаточно, как есть.
Привет инженерам Google, которые ответили в социальных сетях и в итоге нашли время подумать об этом.Возможно, в будущем, когда они будут писать задачи и сюжеты о ConstraintLayout 1.1, они помнят об этом и придумают хорошее решение.