在 Android Kotlin 的约束布局中设置适当的约束

Set proper constraint in Constraint Layout in Android Kotlin

我正在创建一个聊天应用程序。我使用 stackFromEnd = falsereverseLayout = true 从屏幕底部显示项目。我在其中使用了 reyclerview,它工作正常,我在下面添加了带有屏幕截图的代码。看起来如何

<?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="match_parent"
    android:background="#cccccc">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/conversationRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingStart="10dp"
        android:paddingEnd="10dp"
        android:paddingBottom="10dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0" />

</androidx.constraintlayout.widget.ConstraintLayout>

当 recyclerView 中只有一个项目时,上面的代码工作正常,它会打开这样的屏幕

图片 1

但是当有更多项目时,屏幕看起来像这样

图 2

Note: This above image is my expected output. Also soft keyboard shift the layout.

现在主线开始了,我想在屏幕底部添加editText。

<?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"
    android:background="#cccccc">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/conversationRecyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:paddingStart="10dp"
        android:paddingEnd="10dp"
        android:paddingBottom="10dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constraintBottom_toTopOf="@+id/inputContainer"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/inputContainer"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        android:paddingStart="10dp"
        android:paddingTop="14dp"
        android:visibility="gone"
        android:paddingEnd="10dp"
        android:paddingBottom="14dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/conversationRecyclerView"
        app:layout_constraintVertical_bias="1.0">

        <EditText
            android:id="@+id/edittext"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="textMultiLine|text|textNoSuggestions"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

问题 1

图片 1 没有得到正确的约束,看起来像这样

image 2工作正常,软键盘改变了布局。

问题2

我尝试了一些代码来解决问题 1 并且软键盘没有移动布局

<?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"
    android:background="#cccccc">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/conversationRecyclerView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:paddingStart="10dp"
        android:paddingEnd="10dp"
        android:paddingBottom="10dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constrainedHeight="true"
        app:layout_constraintBottom_toTopOf="@+id/inputContainer"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0" />

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/inputContainer"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        android:paddingStart="10dp"
        android:paddingTop="14dp"
        android:paddingEnd="10dp"
        android:paddingBottom="14dp"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintVertical_bias="1.0">

        <EditText
            android:id="@+id/sendMessageEditText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

更新

根据@Cheticamp 的建议,我添加了这个但没有用。它仍然存在 问题 1 问题。没有解决。

<?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"
    android:background="#cccccc">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/conversationRecyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:paddingStart="10dp"
        android:paddingEnd="10dp"
        android:paddingBottom="10dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constrainedHeight="true"
        app:layout_constraintBottom_toTopOf="@+id/inputContainer"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent"
         />

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/inputContainer"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        android:paddingStart="10dp"
        android:paddingTop="14dp"
        android:paddingEnd="10dp"
        android:paddingBottom="14dp"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
      >

        <EditText
            android:id="@+id/sendMessageEditText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

更新 1

根据@Tenfour04的建议,我添加了一些代码,请看。我做得对吗?

<?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"
    android:background="#cccccc">

    <FrameLayout
        android:id="@+id/conversationRecyclerViewViewWrapper"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/inputContainer"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/conversationRecyclerView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="top"
            android:paddingStart="10dp"
            android:paddingEnd="10dp"
            android:paddingBottom="10dp"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

    </FrameLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/inputContainer"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="#ffffff"
        android:paddingStart="10dp"
        android:paddingTop="14dp"
        android:paddingEnd="10dp"
        android:paddingBottom="14dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toBottomOf="@+id/conversationRecyclerView">

        <EditText
            android:id="@+id/sendMessageEditText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:inputType="textMultiLine|text|textNoSuggestions"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

对于问题 #1,设置 RecyclerView 0dp 的高度和宽度,并让约束调整其大小以填满屏幕。另外,删除垂直偏差 - 你不需要它。

顺便说一句,永远不要在 ConstraintLayout 中使用 match_parent。始终使用 0dp 和约束。

这可能会解决您与此布局有关的所有问题。

更新:我应该在你的布局中向下滚动。

我认为您希望 RecyclerView 填满屏幕,但底部的 EditText 除外。一般来说,ConstraintLayout 中的嵌套布局是不需要的,许多糟糕的设计都考虑到了这一点。

进行我上面建议的更改,删除内部 ConstraintLayout 并将两个视图放入垂直链中,如下所示:

<androidx.constraintlayout.widget.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#cccccc">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/conversationRecyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:paddingStart="10dp"
        android:paddingEnd="10dp"
        android:paddingBottom="10dp"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constrainedHeight="true"
        app:layout_constraintBottom_toTopOf="@+id/sendMessageEditText"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/sendMessageEditText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="This is the EditText"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/conversationRecyclerView" />

</androidx.constraintlayout.widget.ConstraintLayout>

问题是你的 RecyclerView 的高度是 wrap_content 而不是 0dp (a.k.a. "match_constraints"),所以它忽略了它应该高于的约束inputContainer.

因此,与其将其设置为 wrap_content 并使用垂直偏移来尝试将其保持在屏幕顶部,不如尝试将其包装在 FrameLayout 中并为其赋予“顶部”布局引力。 FrameLayout 应使用 0dp 作为高度,以便它可以填满整个 space,但不会重叠 inputContainer。 RecyclerView 可以使用 wrap_content 作为高度,布局重力会将它偏向 FrameLayout 的 space 的顶部。所以用这个替换你的 RecyclerView 元素:

<FrameLayout
    android:id="@+id/recyclerViewWrapper"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintBottom_toTopOf="@+id/inputContainer"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/conversationRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="top"
        android:paddingStart="10dp"
        android:paddingEnd="10dp"
        android:paddingBottom="10dp"
        app:layoutManager="LinearLayoutManager"
        app:reverseLayout="true"/>
</FrameLayout>

app:layout_constraintVertical_biasinputContainer 上没有意义,因为它没有顶部约束,因此您可以删除它。