在Android开发中,经常需要与布局打交道,最近在开发中遇到一个问题,水平方向有多个控件,从左到右依次为ImageView
(图标)、TextView
(歌曲名)、ImageView
(VIP标签)、TextView
(作者)、ImageView
(播放状态)。并且歌名和歌手字段单行显示,最终的实现效果如下:
如果用LinearLayout
或者RelativeLayout
来布局,那么效果可能是这样:
出现VIP标签或者动画图标被挤出屏幕外面的问题。如果还是坚持要LinearLayout
或者RelativeLayout
来布局,也可以实现,但需要写很多代码。为了减少不必要的工作量,用约束布局来实现这种需求是最好的。
我们只需要用约束布局的几个属性就能轻松搞定
1、layout_constraintHorizontal_bias
bias属性调整定位,使其偏向一侧
2、layout_constraintHorizontal_chainStyle
在链的第一个元素上设置该属性时,链的行为将根据指定的样式进行更改(默认值为spread)
spread
—元素将展开(默认样式)
spread_inside
—链的端点不会展开
packed
—链条的各部分将被包装在一起。子元素的水平或垂直偏移属性将影响压缩元素的位置
3、layout_constrainedWidth
强约束
4、androidx.constraintlayout.widget.Barrier
可理解为一种屏障
,即不让控件越过这个屏障。
可以使用的属性有:
barrierDirection
:用于设置 Barrier 的位置,属性值有:bottom、top、start、end、left、right
constraint_referenced_ids
:用于设置 Barrier 所引用的控件的 ID,可同时设置多个
barrierAllowsGoneWidgets
:默认为 true,当 Barrier 所引用的控件为 gone 时,则 Barrier 的创建行为是在以 gone 的控件已解析的位置上进行创建。如果设置为 false,则不会将 gone 的控件考虑在内。
注:如果只有设置barrierDirection
属性,则表示该Barrier相对于父控件的位置,如果同时设置了barrierDirection
和constraint_referenced_ids
属性,则表示该Barrier相对于指定控件的位置。
上代码:
<?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"
android:layout_width="match_parent"
android:layout_height="120dp"
android:background="@color/colorPrimaryDark">
<ImageView
android:id="@+id/icon_music"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@mipmap/music"
android:layout_marginLeft="10dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="All I Want for Christmas Is You"
android:textSize="28sp"
android:maxLines="1"
android:ellipsize="end"
android:textColor="#ffffff"
android:layout_marginLeft="10dp"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="@id/img_vip"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="@id/icon_music"
app:layout_constraintStart_toEndOf="@id/icon_music"/>
<ImageView
android:id="@+id/img_vip"
android:layout_width="52dp"
android:layout_height="52dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:src="@mipmap/icon_vip_tag"
app:layout_constraintStart_toEndOf="@id/tv_name"
app:layout_constraintEnd_toStartOf="@id/barrier"
app:layout_constraintTop_toTopOf="@id/tv_name"
app:layout_constraintBottom_toBottomOf="@id/tv_name"/>
<TextView
android:id="@+id/tv_author"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Mariah Carey"
android:textColor="@color/text_accent"
android:textSize="24sp"
android:maxLines="1"
android:ellipsize="end"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="@id/barrier"
app:layout_constraintStart_toStartOf="@id/tv_name"
app:layout_constraintTop_toBottomOf="@id/tv_name" />
<ImageView
android:id="@+id/img_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_playing"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="left"
app:constraint_referenced_ids="img_play"/>
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:background="#805a5a5a"
android:layout_marginTop="15dp"
app:layout_constraintStart_toStartOf="@id/tv_name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
上述示例中需要的关键代码如下
tv_name:
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="@id/img_vip"
img_vip:
app:layout_constraintEnd_toStartOf="@id/barrier"
tv_author:
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="@id/barrier"
Barrier:
app:barrierDirection="left"
app:constraint_referenced_ids="img_play"
表示在img_play
控件的左边设置屏障
可根据文字长度自适应,最终的列表效果如下: