marginTop在使用ConstraintLayout和wrap_content时无效。

34

我在Fragment中有一个ConstraintLayout,其中layout_height="wrap_content",我想在视图底部的两个按钮之间添加边距。

当我将此边距作为layout_marginBottom添加到上面的按钮(button_welcome_signup)时,它似乎可以正常工作。 但是,如果我尝试将其添加到下面的按钮(button_welcome_signin),如layout_marginTop,则不起作用。

有人知道问题所在/ 我是否做错了什么吗?

(请注意,我使用wrap_content是有原因的,并且我真的想在底部按钮上使用边距,以便在我的项目中实现更好的UI一致性)。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:MyAppApp="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical"
    android:background="@color/white"
    android:minHeight="@dimen/min_height_welcome_frame"
    android:padding="@dimen/margin_all_frame_inner">

    <ImageView
        android:id="@+id/imageview_welcome_logo"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:adjustViewBounds="true"
        android:scaleType="fitCenter"
        android:src="@drawable/logo_header"
        MyAppApp:layout_constraintTop_toTopOf="parent"
        MyAppApp:layout_constraintLeft_toLeftOf="parent"
        MyAppApp:layout_constraintRight_toRightOf="parent" />

    <TextView
        android:id="@+id/textiew_welcome_title"
        style="@style/MyAppTextViewTitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/margin_all_component_l"
        android:text="@string/welcome_title"
        MyAppApp:layout_constraintTop_toBottomOf="@id/imageview_welcome_logo" />

    <TextView
        android:id="@+id/textview_welcome_text"
        style="@style/MyAppTextViewText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/welcome_message"
        MyAppApp:layout_constraintTop_toBottomOf="@id/textiew_welcome_title" />

    <Button
        android:id="@+id/button_welcome_signin"
        style="@style/MyAppSubButton"
        android:layout_width="match_parent"
        android:layout_height="46dp"
        android:layout_marginTop="@dimen/margin_all_component_s" 
        android:text="@string/welcome_sign_in"
        MyAppApp:layout_constraintBottom_toBottomOf="parent" />

    <Button
        android:id="@+id/button_welcome_signup"
        style="@style/MyAppButton"
        android:layout_width="match_parent"
        android:layout_height="46dp"
        android:layout_marginTop="@dimen/margin_all_component_l"
        android:text="@string/welcome_sign_up"
        MyAppApp:layout_constraintBottom_toTopOf="@id/button_welcome_signin"
        MyAppApp:layout_constraintTop_toBottomOf="@id/textview_welcome_text"
        MyAppApp:layout_constraintVertical_bias="1" />

</android.support.constraint.ConstraintLayout>

样式.xml:

<style name="MyAppButton" parent="Widget.AppCompat.Button">
    <item name="android:background">@drawable/button_selector_blue</item>
    <item name="android:textSize">@dimen/textsize_all_l</item>
    <item name="android:textColor">@color/white</item>
    <item name="fontFamily">@font/my_sans_serif_regular</item>
</style>

<style name="MyAppSubButton" parent="Widget.AppCompat.Button">
    <item name="android:background">@drawable/button_selector_transparent</item>
    <item name="android:textSize">@dimen/textsize_all_l</item>
    <item name="android:textColor">@color/turquoise_blue</item>
    <item name="fontFamily">@font/my_sans_serif_regular</item>
</style>
8个回答

57

ConstraintLayout 中,若一个子视图的某一侧与另一个视图相连,则该子视图的侧间距才会生效。在原例中,顶部按钮的底部间距有效是因为顶部按钮有一个底部约束:

MyAppApp:layout_constraintBottom_toTopOf="@id/button_welcome_signin"

然而,底部按钮的顶部边距无法生效,因为底部按钮没有顶部约束。

如果你想在底部按钮上使用顶部边距,请添加以下约束:

MyAppApp:layout_constraintTop_toBottomOf="@+id/button_welcome_signup"

请注意,您还需要更新链式样式(因为此新约束创建了一个链),通过将此属性添加到顶部按钮:

MyAppApp:layout_constraintVertical_chainStyle="packed"

太好了,非常感谢,这正是我需要知道的。此外 - 代码似乎可以正常工作,即使不添加链式风格。我是否仍应该出于“最佳实践”原因添加它,或者只有在我打算对我的打包链施加偏见时才需要它? - Simon Mayrshofer
1
@g-mac 如果不需要添加任何功能,那么可以不添加。我忘记你正在使用wrap_content,所以spread(默认值)和packed之间没有区别。 - Ben P.
我在一年多之后回到了这个相同的答案,因为我忘记了解决方案(我只需要设置所有视图的顶部和底部约束,但不设置垂直链式样式也可以工作)。我现在将收藏此页面。感谢您的答案。 - Sufian
1
谢谢,有帮助的(“对于子视图的边缘,只有在该边缘被限制到另一个视图时才会生效”) - ror
@BenP. 我想知道 ConstraintLayout 类中是否有记录。 - DYS

2

试一试

<Button
    android:id="@+id/button_welcome_signin"
    style="@style/MyAppSubButton"
    android:layout_width="match_parent"
    android:layout_height="46dp"
    android:layout_marginTop="16dp"
    android:text="@string/welcome_sign_in"
    MyAppApp:layout_constraintBottom_toBottomOf="parent"
    MyAppApp:layout_constraintEnd_toEndOf="parent"
    MyAppApp:layout_constraintStart_toStartOf="parent"
    MyAppApp:layout_constraintTop_toBottomOf="@+id/button_welcome_signup" />

1

我花了一段时间才明白自己的思路有误,希望这能帮助到其他人。

在ConstraintLayout中,它是从约束条件开始设置边距。

换句话说,假设你有两个并排的按钮。

右侧的一个被限制为与左侧的按钮“StartToEnd”,“TopToTop”和“BottomToBottom”对齐。

如果你给右侧的按钮设置一个marginBottom,它不会将下面的内容向下推,而是会从第一个按钮的底部向上推。边距是指它的底线和其约束对象的底线之间的距离,而不是屏幕上所有视图之间的距离。


0
我同时使用了 android:margin_verticalandroid:margin_top,这时 margin_vertical 会优先生效。 android:margin 也可能出现问题。

0

首先,我已经在您的代码中去除了边距。

enter image description here

第二张图片在左、右、上、下方添加了边距

enter image description here


我认为 @g-mac 知道如何设置边距,他想知道为什么 layout_marginTop 在 button_welcome_signin 上不起作用。 - Misha Akopov
我不确定,“wrap_content”不是固定大小,而是根据内容而定,但是“match_parent”是固定大小,如果内容超过了大小,它将不会显示。如果有任何错误,请告诉我,我会进行更正。 - Poovarasan Selvaraj
你不能在ConstraintLayout中使用match_parent作为任何视图的布局参数。相反,应该使用"match constraints"(0dp)。 - Eugene Brusov

0
<Button
        android:id="@+id/SaveBtnId"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/Save"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginLeft="16dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginRight="16dp"
        app:layout_constraintRight_toRightOf="parent"
         />

enter image description here


0
如果有人遇到和我一样的问题,尝试将一个View(RecyclerView)作为另一个View(ImageView)底部的match_parent。但是即使我在我的RecyclerView中放置了一个与ImageView高度相同的top_margin,它仍然会重叠我的ImageView。
解决方案: 设置 - android:layout_height="0dp" - 对我非常有效。解释如下。
MATCH_PARENT不起作用。
<View
    android:id="@+id/view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"/>

任何视图都应该遵循其父ViewGroup的属性规则。ConstraintLayout支持“0dp”值(match_constraint)而不是“match_parent”以获得与父级相匹配的行为。因此,在ConstraintLayout中永远不要使用“match_parent”!我从这里得到了信息... https://medium.com/@jemli.idea/constraintlayout-never-ever-97c121286100

-3

android:layout_marginTop="@dimen/_10sdp"

安卓:布局顶部边距 = "@dimen/_10sdp"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接