ConstraintLayout进阶

[toc]

以前使用ConstraintLayout,只会使用layout_constraintXxx_toXxxOf的属性,虽然知道Guideline, bias,但很少使用。工作中的一个需求,无法通过简单的约束实现,就决定看一下官方文档,更深入的掌握ConstraintLayout。

特殊属性

  1. layout_goneMarginxxx :当前控件参照的视图gone时生效。 app:layout_goneMarginLeft="180dp"

  2. 水平偏移 layout_constraintHorizontal_bias

    • 同时设置左右约束时,向某侧偏移 (默认:居中)。
    • 值在 0~1 之间
    • 在约束链(chain)中可能失效
    • app:layout_constraintHorizontal_bias="0.2"
  3. 限制宽度 app:layout_constrainedWidth="true|false"

    • wrap_content模式有效
    • 默认为false。
    • 值为true,且左右约束都设定时:
      • 内容宽度超过左右约束,则以约束为准;
      • 内容宽度小于左右约束,则使用内容宽度。
  4. 最大宽度 layout_constraintWidth_max

    • MATCH_CONSTRAINT (0dp) 模式有效
    • 值为准确尺寸 或 wrap
    • 示例 app:layout_constraintWidth_max="200dp"
    • 另外 android: maxWidth / maxHeight : 只在 wrap_content 时生效。
  5. 最小宽度 layout_constraintWidth_min

    • MATCH_CONSTRAINT (0dp) 模式有效
    • 值为准确尺寸 或 wrap
    • 值大于约束宽度时仍有效,会超出右侧约束。
    • 示例 app:layout_constraintWidth_min="wrap"
    • 另外 android:minWidth / minHeight : 只在 wrap_content 时生效。
  6. 宽度百分比 layout_constraintWidth_percent

    • 生效条件:

      • android:layout_width="0dp"
      • app:layout_constraintWidth_default="percent"
    • 宽度占父控件的百分比

    • 值 0 ~ 1

    • 示例

      <Button
          android:id="@+id/btn5"
          android:text="ABCDEFGABCDEFGABCDEFGABCDEFGABCDEFG"
          android:layout_width="0dp"
          android:layout_height="wrap_content"
          app:layout_constraintTop_toTopOf="parent"
          app:layout_constraintLeft_toLeftOf="@id/tv4"
          app:layout_constraintRight_toRightOf="@id/tv7"
          app:layout_constraintWidth_default="percent"
          app:layout_constraintWidth_percent="0.5"
          />
      
  7. 宽高比例 layout_constraintDimensionRatio

    • 生效条件:宽和高至少一个为 MATCH_CONSTRAINT (0dp) 模式
    • 设置宽高比例
    • 例 W:H = 4:1 app:layout_constraintDimensionRatio="4:1"
    • 优先级高于约束尺寸:比例计算得宽度大于左右约束空间时,等距离超出左右约束。
    • 宽和高都是 0dp 时
      • 应确保某一维度得约束是完全的,即同时设定左右约束,或同时设定上下约束。
      • 文档中有指定变化维度的方法 "H, 4:1" 或 "W, 4:1" ,经过试验,某些情况下会出现比例反转。
  8. View.GONE : 当控件被设置为GONE时,本身的约束属性(layout_constraintXxx_toXxxOf)仍然生效,但宽、高、外边距(margin)被置 0 。在布局中仍定位一个点,使依赖它的其他控件能够布局,这些控件或需设置layout_goneMarginxxx属性。

Chain(链)

  1. 通过“双向链接”连在一起的一组元素。元素之间双向连接、链两端单向连接。

  2. 链头(chain head) : 水平链最左一个元素,竖直链最顶一个元素。某些属性只有在链头元素设置才有效。

  3. 链样式: layout_constraintHorizontal_chainStylelayout_constraintVertical_chainStyle 决定剩余空间的分布。

    • 样式值:

      • spread (伸展)(默认样式)
      • spread_inside (内部伸展)
      • packed(收缩)
    • 只能在链头元素设置该属性

      img
  4. 水平权重: layout_constraintHorizontal_weight ,竖直权重: layout_constraintVertical_weight

    • MATCH_CONSTRAINT (0dp) 模式有效
    • 分配顺序:优先为wrap_content控件分配空间,剩余空间按权重分配。如果剩余空间为0,则指定权重的控件尺寸为0。
    • 默认权重为0。即两个控件尺寸都为0dp,A控件指定权重,B控件不设置该属性,则B控件实际尺寸为0 。
    • 外边距叠加:A控件layout_marginRight="20dp",B控件layout_marginLeft="10dp",则A和B的间距为30dp。
    • 示例:
    <?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"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        <Button
            android:id="@+id/ch1"
            android:text="111 "
            android:layout_marginRight="20dp"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toLeftOf="@id/ch2"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintHorizontal_weight="2"
            />
        <Button
            android:id="@+id/ch2"
            android:text="222 222"
            android:layout_marginLeft="10dp"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintLeft_toRightOf="@id/ch1"
            app:layout_constraintRight_toLeftOf="@id/ch3"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintHorizontal_weight="1"
            />
        <Button
            android:id="@+id/ch3"
            android:text="333 3333333333"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintLeft_toRightOf="@id/ch2"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            />
    </android.support.constraint.ConstraintLayout>
    
image-20210315105953111

辅助对象

Barrier (边界)

作用:自动跟踪一组视图某个方向的最值,本身不显示。其他控件使用barrier约束位置,可以达到同时参照多个控件的效果。

属性:

  • barrierAllowsGoneWidgets ,是否考虑可见性为gone的控件,值为 truefalse ,默认为true。
  • barrierDirection 设定跟踪哪个方向的边界,值为 left top reght bottom start end
  • constraint_referenced_ids 参照的控件,多个控件 id 逗号隔开。
<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <TextView
        android:id="@+id/text1"
        android:text="text1"
        android:background="#a0d0f0"
        android:singleLine="true"
        android:layout_marginTop="60dp"
        android:layout_marginLeft="30dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        />
    <TextView
        android:id="@+id/text2"
        android:text="text2text2"
        android:background="#a0d0f0"
        android:singleLine="true"
        android:layout_marginTop="60dp"
        android:layout_marginLeft="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@id/text1"
        />
    <TextView
        android:id="@+id/text3"
        android:text="text3text3"
        android:background="#a0d0f0"
        android:singleLine="true"
        android:layout_marginTop="90dp"
        android:layout_marginLeft="30dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        />

    <android.support.constraint.Barrier
        android:id="@+id/barrier1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="right"
        app:constraint_referenced_ids="text1,text2, text3"
        />
    <Button
        android:id="@+id/btn1"
        android:text="Button1"
        android:layout_marginTop="60dp"
        android:layout_marginLeft="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@id/barrier1"
        />

</android.support.constraint.ConstraintLayout>

观察button1位置变化

image-20210315133614740
image-20210315133805223

Guideline (参考线)

作用:为其他控件提供定位,本身不显示。

尺寸:水平Guideline高度为0,宽度适配父控件;竖直Guideline宽度为0,高度适配父控件。Guideline的尺寸是固定的,不能通过layout_width / layout_height改变。

重要属性:

  • orientation 方向,horizontal / vertical 。水平Guideline只能提供上下定位,竖直Guideline只能提供左右定位。

  • 定位,以下三个属性设置一个即可:

    1. layout_constraintGuide_percent ,通过百分比定位自身,值为小数 0 ~ 1 。

    2. layout_constraintGuide_begin ,与父控件左端或顶端的距离。

    3. layout_constraintGuide_end ,与父控件右端或底端的距离。

Placeholder (占位符)

作用:通过约束属性设置一个位置,可以动态将其他控件移动到这个位置,移动后控件的点击事件等原有属性保留。

定位:定位方式和普通控件相同,通过layout_constraintXxx_toXxxOf 和 margin 定位。

示例:

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/btn1"
        android:text="btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginTop="30dp"
        />
    <android.support.constraint.Placeholder
        android:id="@+id/ph1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        />
</android.support.constraint.ConstraintLayout>
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_example)

        btn1.setOnClickListener {
            if(ph1.content != btn1){
                ph1.setContentId(btn1.id)
            } else{
                ph1.setContentId(ph1.id)
            }

        }
    }
Gif_20210315164053

Group (组)

作用:控制一组控件的可见性(visibility)。多个Group可以引用同一个控件,按xml文件中的顺序,最后一个Group的可见性最终决定控件的可见性。

属性:constraint_referenced_ids 成员id,多个控件的id用逗号隔开

示例:

     <androidx.constraintlayout.widget.Group
              android:id="@+id/group"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:visibility="visible"
              app:constraint_referenced_ids="button4,button9" />

参考

官方文档

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容