首页 > 解决方案 > Android ConstraintLayout我如何重用布局并仍然约束布局

问题描述

当我想将通用布局代码重构为单独的 xml 文件时,我正在努力让 ConstraintLayout 为我工作。我可以使用RelativeLayouts 轻松做到这一点,但我相信RelativeLayouts 已被弃用,我们现在应该使用ConstraintLayous。

我有一个屏幕应用程序,其纵向和横向布局不同,如下图所示。

在此处输入图像描述

我有 2 个同名的布局文件(“my_layout.xml”),一个在“layout”文件夹中,一个在“layout-land”中。目前我已经复制了两个布局文件中的所有 xml 并调整了约束,以便在横向版本中视图水平放置。

肖像版

<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">

    <!-- OTHER VIEWS 1 -->
    <View
        android:id="@+id/OtherViews1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <!-- OTHER VIEWS 2 -->
    <View
        android:id="@+id/OtherViews2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottom="@+id/OtherViews1"
        app:layout_constraintBottom_toTopOf="@+id/scrollbar" />


    <!-- SCROLL BAR VIEWS -->
    <TextView
        android:id="@+id/slow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        ...
        app:layout_constraintTop_toTopOf="@+id/scrollbar"
        app:layout_constraintBottom_toBottomOf="@+id/scrollbar"
        app:layout_constraintStart_toStartOf="parent"/>
    <androidx.appcompat.widget.AppCompatSeekBar
        android:id="@+id/scrollbar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        ...
        app:layout_constraintBottom_toTopOf="@+id/OtherViews3"
        app:layout_constraintStart_toEndOf="@+id/slow"
        app:layout_constraintEnd_toStartOf="@+id/fast"/>
    <TextView
        android:id="@+id/fast"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        ...
        app:layout_constraintTop_toTopOf="@+id/scrollbar"
        app:layout_constraintBottom_toBottomOf="@+id/scrollbar"
        app:layout_constraintStartEnd_toEndOf="parent" />


    <!-- OTHER VIEWS 3 -->
    <View
        android:id="@+id/OtherViews3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>


</androidx.constraintlayout.widget.ConstraintLayout>    

横向版

<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">

    <!-- OTHER VIEWS 1 -->
    <View
        android:id="@+id/OtherViews1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <!-- OTHER VIEWS 2 -->
    <View
        android:id="@+id/OtherViews2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottom="@+id/OtherViews1"
        app:layout_constraintBottom_toBottomOf="parent" />


    <!-- SCROLL BAR VIEWS -->
    <TextView
        android:id="@+id/slow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        ...
        app:layout_constraintStart_toEndOf="@+id/OtherViews2"
        app:layout_constraintTop_toTopOf="@+id/scrollbar"
        app:layout_constraintBottom_toBottomOf="@+id/scrollbar"
        app:layout_constraintStart_toStartOf="parent"/>
    <androidx.appcompat.widget.AppCompatSeekBar
        android:id="@+id/scrollbar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        ...
        app:layout_constraintBottom_toTopOf="@+id/OtherViews3"
        app:layout_constraintStart_toEndOf="@+id/slow"
        app:layout_constraintEnd_toStartOf="@+id/fast"/>
    <TextView
        android:id="@+id/fast"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        ...
        app:layout_constraintTop_toTopOf="@+id/scrollbar"
        app:layout_constraintBottom_toBottomOf="@+id/scrollbar"
        app:layout_constraintStartEnd_toEndOf="parent" />


    <!-- OTHER VIEWS 3 -->
    <View
        android:id="@+id/OtherViews3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content
        app:layout_constraintStart_toEndOf="@+id/OtherViews2""
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>


</androidx.constraintlayout.widget.ConstraintLayout>    

“Slow”文本框、滚动条和“Fast”文本框的 xml 在两个文件中重复。我想将这 3 个元素的布局移动到一个单独的文件中,并在两个“my_layout.xml”文件中引用它,以便它更可重用并且在布局文件之间没有重复。我想保持我的层次结构平坦(否则我只会使用RelativeLayouts)。我不知道如何为滚动条 UI 指定新的可重用 xml 布局文件的约束。

纵向版重用滚动条布局

<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">

    <!-- OTHER VIEWS 1 -->
    <View
        android:id="@+id/OtherViews1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <!-- OTHER VIEWS 2 -->
    <View
        android:id="@+id/OtherViews2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottom="@+id/OtherViews1"
        app:layout_constraintBottom_toTopOf="@+id/scrollbar" />

    <include
        layout="@layout/scrollbar
        app:layout_constraintBottom_toTopOf="@+id/OtherViews3"
        app:layout_constraintStart_toStartOf="parent"       />


    <!-- OTHER VIEWS 3 -->
    <View
        android:id="@+id/OtherViews3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"/>


</androidx.constraintlayout.widget.ConstraintLayout>    

可重复使用的滚动条布局

<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="wrap_content"
    android:layout_height="wrap_content">


    <!-- SCROLL BAR VIEWS -->
    <TextView
        android:id="@+id/slow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        ...
        app:layout_constraintTop_toTopOf="@+id/scrollbar"
        app:layout_constraintBottom_toBottomOf="@+id/scrollbar"
        app:layout_constraintStart_toStartOf="parent"/>         ****************** 
    <androidx.appcompat.widget.AppCompatSeekBar
        android:id="@+id/scrollbar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        ...
        app:layout_constraintBottom_toTopOf="@+id/OtherViews3" ****************** 
        app:layout_constraintStart_toEndOf="@+id/slow"
        app:layout_constraintEnd_toStartOf="@+id/fast"/>
    <TextView
        android:id="@+id/fast"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        ...
        app:layout_constraintTop_toTopOf="@+id/scrollbar"
        app:layout_constraintBottom_toBottomOf="@+id/scrollbar"
        app:layout_constraintStartEnd_toEndOf="parent" />       ****************** 

</androidx.constraintlayout.widget.ConstraintLayout>    

我不知道该为标有 **** 的行添加什么。如果我指定“慢”文本框从父级的开头开始,那将不适用于横向版本。我希望此滚动条布局仅指示慢速在左侧,滚动条在中间(占用所有剩余空间),快速文本框在右侧。 我如何使用约束布局来做到这一点? 另外我如何垂直居中所有3个视图?

相对布局要容易得多,正如我所说的慢文本框对齐ParentLeft,快速文本框对齐ParentRight,滚动条位于慢文本框的右侧和快速文本框的左侧。最后我想说所有 3 个视图都在父级中垂直居中。

标签: androidandroid-constraintlayout

解决方案


包含布局中的视图不能引用包含它的布局文件中的视图。您仍然可以通过不同的方法使用包含的布局。

查看包含的布局,其中包含快/慢文本和作为自封闭实体的搜索栏 - 类似于以下内容:

滚动条.xml

<androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/slow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Slow"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.appcompat.widget.AppCompatSeekBar
        android:id="@+id/scrollbar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="@+id/slow"
        app:layout_constraintEnd_toStartOf="@+id/fast"
        app:layout_constraintStart_toEndOf="@+id/slow"
        app:layout_constraintTop_toTopOf="@+id/slow" />

    <TextView
        android:id="@+id/fast"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Fast"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

您现在可以在纵向和横向布局中包含此布局:

activity_main.xml(纵向)

在此处输入图像描述

<androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="24dp">

    <TextView
        android:id="@+id/OtherViews1"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#FFCCCCCC"
        android:gravity="center"
        android:text="OtherViews1"
        app:layout_constraintBottom_toTopOf="@+id/OtherViews2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_weight="1" />

    <TextView
        android:id="@+id/OtherViews2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginTop="24dp"
        android:layout_marginBottom="24dp"
        android:background="#FFCCCCCC"
        android:gravity="center"
        android:text="OtherViews2"
        app:layout_constraintBottom_toTopOf="@+id/scrollbar"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottom="@+id/OtherViews1"
        app:layout_constraintTop_toBottomOf="@+id/OtherViews1"
        app:layout_constraintVertical_weight="4" />

    <include
        layout="@layout/scrollbar"
        android:id="@+id/scrollbar"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/OtherViews3"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/OtherViews2"
        app:layout_constraintVertical_weight="0.5" />

    <TextView
        android:id="@+id/OtherViews3"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginTop="24dp"
        android:background="#FFCCCCCC"
        android:gravity="center"
        android:text="OtherViews3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/scrollbar"
        app:layout_constraintVertical_weight="1" />

</androidx.constraintlayout.widget.ConstraintLayout>

activity_main.xml(横向)

在此处输入图像描述

<androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="24dp">

    <TextView
        android:id="@+id/OtherViews1"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#FFCCCCCC"
        android:gravity="center"
        android:text="OtherViews1"
        app:layout_constraintBottom_toTopOf="@+id/OtherViews2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_weight="1" />

    <TextView
        android:id="@+id/OtherViews2"
        android:layout_width="342dp"
        android:layout_height="0dp"
        android:layout_marginTop="24dp"
        android:background="#FFCCCCCC"
        android:gravity="center"
        android:text="OtherViews2"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottom="@+id/OtherViews1"
        app:layout_constraintTop_toBottomOf="@+id/OtherViews1"
        app:layout_constraintVertical_weight="8" />

    <include
        android:id="@+id/scrollbar"
        layout="@layout/scrollbar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="24dp"
        app:layout_constraintBottom_toTopOf="@+id/OtherViews3"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/OtherViews3" />

    <!-- OTHER VIEWS 3 -->
    <TextView
        android:id="@+id/OtherViews3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="24dp"
        android:background="#FFCCCCCC"
        android:gravity="center"
        android:text="OtherViews3"
        app:layout_constraintBottom_toBottomOf="@+id/OtherViews2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/OtherViews2" />

</androidx.constraintlayout.widget.ConstraintLayout>

包含的布局文件可以根据约束和大小进行处理,就像它自己的小部件一样。请参阅使用 <include/> 重用布局


推荐阅读