美文网首页
Android - 一个 item 布局带你领略 Constra

Android - 一个 item 布局带你领略 Constra

作者: 拾识物者 | 来源:发表于2019-04-09 14:45 被阅读0次

本文是 ConstraintLayout 小课堂系列第 1 讲,课程目录:

  1. 一个 item 布局带你领略 ConstraintLayout 的魅力
  2. ConstraintLayout Chain 链布局能干啥

布局要求

先上最终效果图:

  1. 这是一个 Item 布局,分为两行,第一行显示可变长度的文字,第二行显示固定长度的文字,底部还有一个粗线条条。
  2. 绿色背景的文字语义上是一个标签,可以不显示,也就是设置 visibility=gone,这时右侧的长文字要占据整个宽度。
  3. 长文字与标签的间距是 10dp,而标签距离 parent 的间距是 16dp,隐藏掉标签后长文字要左移占据标签的位置,距离 parent 要保持 16dp 的间距。
  4. 上下两行的高度是固定的 40dp,行内文字垂直居中对齐。

实现思路

首先要找到布局的起点,然后创建其他 View 与起点的关系,一点一点将所有 View 放在正确的位置。

整个布局被分成上下两行,并且两行都是固定高度,内部的 View 在行内居中。可以用两个 ConstraintLayout 的 Guideline 来固定在行的中间位置,通过居中对齐的方式将 View 与 Guideline 对齐。

详解

如何居中布局

ConstraintLayout 并不是靠一个单独的属性设置居中,而是用两侧的约束像弹簧一样将 View 拉起来浮在中间。

垂直居中需要将 layout_height 设置为 wrap_content,然后上下两个边界设置为同一个对象:Bottom_toBottomOfTop_toTopOf。同理水平居中需要设置 layout_widthStart_toStartOfEnd_toEndOf

<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal" 👉 水平线还是垂直线
    app:layout_constraintGuide_begin="20dp" /> 👉 begin 表示距 parent top 多长
<TextView
    android:id="@+id/title"
    android:layout_height="wrap_content" 👉 重点,居中必须设置为 wrap_content
    app:layout_constraintBottom_toBottomOf="@+id/guideline" 👉 两边都要设置才能居中
    app:layout_constraintTop_toTopOf="@+id/guideline" 👉 两边都要设置才能居中
    ... />

如何用约束设置尺寸

layout_wdithlayout_height 设置为 0dp 表示匹配约束的含义。下面是长文字设置为匹配剩余宽度的代码:

<TextView
    android:id="@+id/title"
    android:layout_width="0dp" 👉 重点,匹配约束必须“放弃宽度”,设置为 0dp
    android:layout_marginStart="10dp"
    android:layout_marginEnd="10dp"
    android:ellipsize="end" 👉 末尾显示 ... 
    android:lines="1" 👉 只显示一行,防止撑大高度
    android:text="Update 3rd libs, and submit app for review."
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toEndOf="@+id/tag" />

居中与匹配约束两种布局,一个是保持 View 原有尺寸放置在中间,一个是拉伸 View 直到符合约束。其实约束相关的属性设置是一样的,不一样的是尺寸属性,layout_widthlayout_height,设置的值是 wrap_content 还是 0dp

Guideline 是一条水平线或者垂直线,可设置距离 ConstraintLayout 边缘的大小,在约束布局中可以像普通 View 一样用来定义关系。本例中用来当做垂直居中对齐的锚点。

如何对齐文字的 Baseline

垂直对齐除了 top 和 bottom 以外,还有 baseline,只对含有文字的 View 生效,比如 TextView,表示两个 TextView 的文字基准对齐,获得更美观的排版效果。

<TextView
        android:id="@+id/tag"
        android:text="iOS app"
        app:layout_constraintBaseline_toBaselineOf="@+id/title" 👉 baseline 对齐
        ... />

如何处理 GONE 了的 View

神奇的 ConstraintLayout 完全可以自动处理 visibility=gone 的 View。处理的规则是:

  • 这个 View 被缩小为一个尺寸为 0×0 的点。
  • 这个 View 的 margins 值都会变成 0。
  • 与其他 View 之间的约束仍然生效。
<TextView
    android:id="@+id/tag"
    android:visibility="gone" 👉 消失了
    android:layout_marginStart="16dp" 
    ... />
<TextView
    android:id="@+id/title"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="10dp"
    app:layout_constraintStart_toEndOf="@+id/tag" 👉 tag消失了,我贴上来
     />

按照规则,TextView(tag) 的宽度变为 0,并且 margin 变为 0,于是 TextView(title) 被拉伸到了左边与 parent 左对齐,这时候与 parent 的左边距是它自己的 layout_marginStart="10dp"

结果与设计不符了,这时候就要使用一组神奇的属性:goneMargin:layout_goneMarginStartlayout_goneMarginBottom 等等。表示如果我通过约束连接了一个 gone View,我这个方向上的 margin 由 goneMargin 属性替代。

因此这里添加一下 goneMargin 属性就达到了想要的效果:

<TextView
    android:id="@+id/title"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="10dp"
    app:layout_constraintStart_toEndOf="@+id/tag"
    👇 constraintStart 指向的 View gone 了,于是 goneMarginStart 说了算了
    app:layout_goneMarginStart="16dp" 
     />

本节课程内容小节

  • 如何居中布局
  • 如何用约束设置尺寸
  • 如何对齐文字的 Baseline
  • 如何处理 GONE 了的 View

全部代码

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">

    <View
        android:id="@+id/first_line"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:background="#0099aa"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:layout_editor_absoluteX="0dp"
        tools:layout_editor_absoluteY="0dp" />

    <View
        android:id="@+id/second_line"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:background="#992277"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/first_line"
        tools:layout_editor_absoluteX="0dp"
        tools:layout_editor_absoluteY="0dp" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_begin="20dp" />

    <TextView
        android:id="@+id/tag"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:background="#009000"
        android:padding="6dp"
        android:text="iOS app"
        android:textColor="@android:color/white"
        android:textSize="14sp"
        android:visibility="gone"
        app:layout_constraintBaseline_toBaselineOf="@+id/title"
        app:layout_constraintStart_toStartOf="parent" />

    <TextView
        android:id="@+id/title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginEnd="10dp"
        android:ellipsize="end"
        android:lines="1"
        android:text="Update 3rd libs, and submit app for review."
        android:textSize="17sp"
        app:layout_constraintBottom_toBottomOf="@+id/guideline"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/tag"
        app:layout_constraintTop_toTopOf="@+id/guideline"
        app:layout_goneMarginStart="16dp" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_begin="60dp" />

    <TextView
        android:id="@+id/startTime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="27dp"
        android:text="13:10"
        android:textSize="18sp"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guideline2"
        app:layout_constraintBottom_toBottomOf="@+id/guideline2" />

    <TextView
        android:id="@+id/connector"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:text="-"
        android:textSize="18sp"
        android:textStyle="bold"
        app:layout_constraintStart_toEndOf="@+id/startTime"
        app:layout_constraintTop_toTopOf="@+id/startTime" />

    <TextView
        android:id="@+id/separator"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="145dp"
        android:text="|"
        android:textSize="18sp"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/startTime" />

    <TextView
        android:id="@+id/endTime"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:text="16:15"
        android:textSize="18sp"
        android:textStyle="bold"
        app:layout_constraintStart_toEndOf="@+id/connector"
        app:layout_constraintTop_toTopOf="@+id/startTime" />

    <TextView
        android:id="@+id/interval"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:text="03:05"
        android:textSize="18sp"
        android:textStyle="bold"
        app:layout_constraintStart_toEndOf="@+id/separator"
        app:layout_constraintTop_toTopOf="@+id/startTime" />

    <View
        android:id="@+id/colorBar"
        android:layout_width="100dp"
        android:layout_height="6dp"
        android:layout_marginTop="14dp"
        android:background="#009900"
        app:layout_constraintLeft_toLeftOf="@+id/interval"
        app:layout_constraintTop_toBottomOf="@+id/guideline2" />

</androidx.constraintlayout.widget.ConstraintLayout>

(ole)

相关文章

网友评论

      本文标题:Android - 一个 item 布局带你领略 Constra

      本文链接:https://www.haomeiwen.com/subject/frzmiqtx.html