在 Android Kotlin 的约束布局中设置适当的约束
Posted
技术标签:
【中文标题】在 Android Kotlin 的约束布局中设置适当的约束【英文标题】:Set proper constraint in Constraint Layout in Android Kotlin 【发布时间】:2021-12-23 08:33:16 【问题描述】:我正在创建一个聊天应用程序。我使用 stackFromEnd = false 和 reverseLayout = 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_
android:layout_
android:background="#cccccc">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/conversationRecyclerView"
android:layout_
android:layout_
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_
android:layout_
android:background="#cccccc">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/conversationRecyclerView"
android:layout_
android:layout_
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_
android:layout_
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_
android:layout_
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_
android:layout_
android:background="#cccccc">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/conversationRecyclerView"
android:layout_
android:layout_
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_
android:layout_
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_
android:layout_
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_
android:layout_
android:background="#cccccc">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/conversationRecyclerView"
android:layout_
android:layout_
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_
android:layout_
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_
android:layout_
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_
android:layout_
android:background="#cccccc">
<FrameLayout
android:id="@+id/conversationRecyclerViewViewWrapper"
android:layout_
android:layout_
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_
android:layout_
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_
android:layout_
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_
android:layout_
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 的高度是 wrap_content
而不是 0dp
(又名“match_constraints”),因此它忽略了它应该高于 inputContainer
的约束。
因此,与其将其设为wrap_content
并使用垂直偏差来尝试将其保持在屏幕顶部,不如尝试将其包装在 FrameLayout 中并赋予其“顶部”的布局重力。 FrameLayout 应该使用 0dp 作为高度,以便它可以填充整个空间,但不能重叠inputContainer
。 RecyclerView 可以使用wrap_content
作为高度,布局重力会将其偏向FrameLayout 空间的顶部。所以用这个替换你的 RecyclerView 元素:
<FrameLayout
android:id="@+id/recyclerViewWrapper"
android:layout_
android:layout_
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_
android:layout_
android:layout_gravity="top"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:paddingBottom="10dp"
app:layoutManager="LinearLayoutManager"
app:reverseLayout="true"/>
</FrameLayout>
app:layout_constraintVertical_bias
在inputContainer
上毫无意义,因为它没有顶部约束,因此您可以删除它。
【讨论】:
再次感谢您对我的帮助。我正在尝试你的代码。我需要向app:layout_constraintTop_toBottomOf="@+id/conversationRecyclerView"
in inputContainer
提出一个问题吗?
我在 UPDATE 1 中添加代码,请看一下。谢谢一百万。
这没有意义,而且我认为不支持将 inputContainer
顶部约束到不是 ConstraintLayout 的直接子视图的视图。如果我理解正确,您只希望 inputContainer
偏向屏幕底部,因此您不需要限制其顶部。无论如何它都是多余的,因为 FrameLayout 的底部已经被限制在 inputContainer
的顶部。
感谢@Tenfour04 为您提供解决方案。
你能看看这个issue【参考方案2】:
对于问题 #1,将 RecyclerView 的高度和宽度设为0dp
并让约束调整其大小以填满屏幕。另外,消除垂直偏差 - 你不需要它。
顺便说一句,永远不要在 ConstraintLayout 中使用match_parent
。始终使用0dp
和约束。
这可能会解决您使用此布局的所有问题。
更新:我应该在你的布局中向下滚动。
我认为您希望 RecyclerView 填满屏幕,底部的 EditText 除外。一般来说,ConstraintLayout 中的嵌套布局是不需要的,许多糟糕的设计都会考虑这样做。
进行我上面建议的更改,删除内部 ConstraintLayout 并将两个视图放入垂直链中,如下所示:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_
android:layout_
android:background="#cccccc">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/conversationRecyclerView"
android:layout_
android:layout_
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_
android:layout_
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>
【讨论】:
在最后一个代码中我需要添加 0dp 吗? 需要在父视图中删除匹配父对象? 我添加了更新的代码,但仍然无法正常工作以上是关于在 Android Kotlin 的约束布局中设置适当的约束的主要内容,如果未能解决你的问题,请参考以下文章