ConstraintLayout:如何使一个视图宽度为屏幕的一半并居中?

56

简短概述
视图宽度必须恰好为屏幕的一半,并且位于中心位置。使用ConstraintLayout实现。

请注意,该视图没有任何内部宽度。

<View android:background="#ff0000" ... />

原问题
我想要实现一个布局,其中一个视图的大小为屏幕大小的一半,并水平居中。

类似这样:|--view--|

我无法在ConstraintLayout中找到任何方法。我发现最好的方法是在左侧和右侧分别放置两个虚拟视图,并在我的视图上使用 app:layout_constraintHorizontal_weight="1.5" , 并在这两个虚拟视图上使用 app:layout_constraintHorizontal_weight="1"

有更好的办法吗?


正如我在问题中提到的,使用XML和3个视图的解决方案,我想你足够聪明可以推断出“更好的方法”意味着比3行XML代码更少的代码。我想错了,下次我会改进我的问题。谢谢你的回答。 - Softlion
5个回答

70

在beta版本中,您可以使用百分比宽度。如果您无法使用beta版本,则可以使用两个垂直指南:一个位于屏幕宽度的25%处,另一个位于75%的宽度处。宽度为0dp的视图将被限制在这两个指南之间。此设置将为您提供一个宽度为屏幕宽度的1/2且居中的视图。

以下XML演示了两种方法:一种使用ConstraintLayout beta版本,另一种使用当前生产版本中可用的功能。

enter image description here XML布局

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main_inference"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <View
        android:id="@+id/viewTop"
        android:layout_width="0dp"
        android:layout_height="100dp"
        android:layout_marginTop="16dp"
        android:background="@android:color/darker_gray"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_default="percent"
        app:layout_constraintWidth_percent="0.5" />


    <android.support.constraint.Guideline
        android:id="@+id/guidelineLeft"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.25" />

    <View
        android:layout_width="0dp"
        android:layout_height="100dp"
        android:layout_marginTop="16dp"
        android:background="@android:color/darker_gray"
        app:layout_constraintEnd_toStartOf="@id/guidelineRight"
        app:layout_constraintStart_toEndOf="@id/guidelineLeft"
        app:layout_constraintTop_toBottomOf="@id/viewTop" />

    <android.support.constraint.Guideline
        android:id="@+id/guidelineRight"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.75" />

</android.support.constraint.ConstraintLayout>

你知道为什么他们不像苹果在iOS和Mac上实现完整的约束布局吗?这应该不难... - Softlion
首先,这并不容易,所以不要说“应该不太难”的话,除非你愿意自己实现它;去为谷歌工作并做到这一点。其次,如果你有AutoLayout的经验,你应该知道它对用户来说有多么困难(而且仍然如此);即使是有经验的用户也需要花费大量时间才能完全理解它(如果有的话),更重要的是,在日常实践中,如果布局复杂,AutoLayout可能非常难以调试。CL在某些方面比AL做得更好,反之亦然。 - Martin Marconcini
测试版发布不会出来吗? - Softlion
1
@MartinMarconcini,我很乐意实现这个功能,因为它很简单。Cl 比 AL 做的更好的只有计算布局的速度了,或者说可能只是计算布局的速度更快。这是一个简单的方程列表,可以转换成矩阵,然后很容易地解决。 - Softlion

63

自** ConstraintLayout1.1.0-beta1 **起,您可以使用百分比来定义宽度高度

android:layout_width="0dp"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent=".4"

这将定义宽度为屏幕宽度的40%。 结合百分比指导方针,可创建任何基于百分比的布局


谢谢,但问题是如何使视图的宽度恰好为屏幕宽度的一半。顺便说一句,在你的例子中可以使用"parent"代替"@+id/activity_main"。 - Softlion
好的,但如果我不能使用beta组件怎么办? - Softlion
谢谢!如https://developer.android.com/reference/android/support/constraint/ConstraintLayout中所述,“`layout_constraintWidth_percent`和`layout_constraintHeight_percent`将把此维度的大小设置为父级的百分比”。因此,您应该在父级`ConstraintLayout`中包装您的布局。如果您希望拥有占用屏幕一部分的布局,则无济于事。 - CoolMind
好的解决方案。非常感谢。 - KSR
感谢您提供的解决方案。 - Adnan Bashir

8

尝试使用垂直分割

    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.constraint.ConstraintLayout
            android:id="@+id/clPart1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:background="@color/white"
            android:visibility="visible"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_chainStyle="spread"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toLeftOf="@+id/clPart2">


        </android.support.constraint.ConstraintLayout>

        <android.support.constraint.ConstraintLayout
            android:id="@+id/clPart2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:background="@color/black"
            android:visibility="visible"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toRightOf="@+id/clPart1"
            app:layout_constraintRight_toRightOf="parent">


        </android.support.constraint.ConstraintLayout>
    </android.support.constraint.ConstraintLayout>

嵌套ConstraintLayouts是不好的实践。 - The Berga

4
使用ConstraintLayout,您可以像这样将视图居中在屏幕上:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#FF0000"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHeight_percent=".5"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintWidth_percent=".5"></LinearLayout>

</android.support.constraint.ConstraintLayout>

将您的Gradle更新到最新版本的ConstraintLayout:

dependencies {
...
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
}

enter image description here


0

结果

你需要做的是:
只需将此添加到您的XML中

    <View
        android:id="@+id/viewV1"
        android:layout_height="match_parent"
        android:background="#ff0000"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_width="match_parent"
        />

在你的Java中,可以这样写:
首先导入以下内容。

    import android.graphics.Point;
    import android.support.constraint.ConstraintLayout;
    import android.view.Display;
    import android.view.View;

然后在您的Java文件的onCreate函数中添加这些行。

    Display display = getWindowManager().getDefaultDisplay();
    Point size = new Point();
    display.getSize(size);
    int width1 = size.x;
    //int height = size.y;
    View v =  findViewById(R.id.viewV1);        
    ConstraintLayout.MarginLayoutParams params = (ConstraintLayout.MarginLayoutParams) v.getLayoutParams();
    params.width = width1/2; params.leftMargin = width1/4; params.rightMargin = width1/4;
    v.setLayoutParams(params);

您也可以使用此方法设置高度。是的,无论屏幕大小如何,此视图将使用屏幕宽度的一半。

由于您不想通过Java执行此操作,请将以下内容添加到您的XML中。

<android.support.constraint.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/guideline5"
        app:layout_constraintGuide_begin="411dp"
        android:orientation="vertical"
         />

选择此选项,将此指南移动到屏幕末尾,并注意此值app:layout_constraintGuide_begin="411dp"。 现在无论该值为何,都是您屏幕的宽度。

marginStartmarginEnd添加到您的视图中,作为411/4 dp。 (计算该值,XML不会执行此操作)。
这将使您的视图位于中心位置,并且其宽度为父级宽度的一半。

请记住,并非每个屏幕的宽度都为411dp。 这对于所有手机屏幕大小都不起作用。


谢谢,但这并没有回答问题“视图大小必须是屏幕大小的一半”。它必须是准确的一半屏幕宽度。该视图不是文本视图。 - Softlion
尝试使用您的解决方案与<View android:background="#ff0000" />:这个视图使用了屏幕宽度的一半吗?不是 :) - Softlion
问题要求提供一个比已经提出的解决方案更简单的解决方案。你的方案更加复杂。 - Softlion
用这种方法实现自己想要的效果比在 XML 中处理边距更简单,而且不会因为不同屏幕尺寸而出现问题。完全没有问题。这可能对其他人也有帮助。 - Lalit Fauzdar
我不使用任何边距。 - Softlion
显示剩余2条评论

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