如何相对于彼此定位 2 个视图?

Posted

技术标签:

【中文标题】如何相对于彼此定位 2 个视图?【英文标题】:How to position 2 Views relative to each other? 【发布时间】:2019-08-31 11:09:04 【问题描述】:

我想相对于彼此定位 2 个视图,但不只是相对于顶部、底部、左侧或右侧,而是以 成比例的方式。让我解释。以下是4种定位场景:

其中,2) 和 4) 很容易实现,并且具有由标准布局容器(例如 RelativeLayout、ConstraintLayout)提供的内置支持,但我当前的任务需要场景 1)/3) 中描述的定位

此问题的一个简单解决方案是为两个视图与父级设置不同的左/上边距,但这意味着如果需要将两个视图一起放置到其他位置,则所有边距都必须更改。

相反,我希望在这两个视图之间进行某种相对定位安排,以使它们保持相对“正确”的距离,无论它们作为一个单元放置在父级中的什么位置。

我怎样才能达到同样的效果?一个有效的解决方案(具有扁平的层次结构,没有视图黑客)将不胜感激。

【问题讨论】:

您希望它们在运行时更改吗? @AvinashJoshi :不。我想将它们定位在 XML 中一次 【参考方案1】:

将不胜感激一个有效的解决方案(具有扁平的层次结构,没有视图黑客)。,您可以使用 ConstraintLayout 和 guidelines。

指南具有app:layout_constraintGuide_percent 属性,使其能够响应屏幕尺寸。 您可以在为按钮添加app:layout_constraintWidth_percentapp:layout_constraintHeight_percent 属性时使用它(不是强制性的,您可以将视图限制在指南中,但我相信它更简单)。

这是您想要的具有扁平层次结构的布局示例:

<?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_
  android:layout_>

<Button
    android:id="@+id/button2"
    android:layout_
    android:layout_
    android:text="Button"
    app:layout_constraintHeight_percent=".1"
    app:layout_constraintStart_toStartOf="@+id/guideline"
    app:layout_constraintTop_toTopOf="@+id/guideline2"
    app:layout_constraintWidth_percent=".3" />

<Button
    android:id="@+id/button"
    android:layout_
    android:layout_
    android:text="Button"
    app:layout_constraintBottom_toTopOf="@+id/guideline4"
    app:layout_constraintEnd_toStartOf="@+id/guideline"
    app:layout_constraintHeight_percent=".1"
    app:layout_constraintWidth_percent=".3" />

<android.support.constraint.Guideline
    android:id="@+id/guideline"
    android:layout_
    android:layout_
    android:orientation="vertical"
    app:layout_constraintGuide_percent=".5" />

<android.support.constraint.Guideline
    android:id="@+id/guideline2"
    android:layout_
    android:layout_
    android:orientation="horizontal"
    app:layout_constraintGuide_percent=".4" />

<android.support.constraint.Guideline
    android:id="@+id/guideline4"
    android:layout_
    android:layout_
    android:orientation="horizontal"
    app:layout_constraintGuide_percent=".45" />
</android.support.constraint.ConstraintLayout>

看起来像这样(我从预览中添加屏幕截图以便更好地理解指南):

这只是一个示例,但使用这些工具,您可以根据需要创建布局。


一些额外的信息

我的解决方案在我的视图上不包含任何固定大小的尺寸,这将使布局具有响应性(无需为每个屏幕尺寸构建布局)

您可能还会找到与您的问题相关的ConstraintLayout: Circular Positioning,但我认为这对您来说并不是最好的选择。

【讨论】:

据我了解,在您的解决方案中,如果我需要将 2 个视图作为一个单元在任何方向对角移动,我将不得不移动所有指南。在移动所有准则时,我还必须确保准则之间的相对距离保持不变。第三,准则到新位置的计算映射会变得有点复杂。 据我了解,在您的解决方案中,如果我需要将 2 个视图作为一个单元在任何方向对角移动,我将不得不移动所有指南,您可以放置它在片段内并在布局中移动您的片段。但也许考虑检查我的回答中提到的圆形定位,在看到您的评论后,我相信它可能适合您的用例。 或者,我害怕的是……有一个自定义的ViewGroup,它支持具有 2 个视图的合成,并具有有助于指定相对位置尺寸的自定义属性。如果任何视图的大小发生变化,layout()/invalidate() 也会重新计算父视图的相对定位。相当多的工作! 工作量很大,因为你想要一些非常具体的东西,据我所知,你可以使用指南或使用ConstraintLayout: Circular Positioning,如果你能找到更好的东西,请在这里评论我我也可以学。【参考方案2】:

是的,可以在第 3 点的 XML 代码下方使用约束布局签出。(如果您有疑问,将执行相同的第 2 点,让我知道)

<?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:orientation="vertical"
        android:layout_
        android:layout_>

    <androidx.appcompat.widget.AppCompatButton
            android:layout_
            android:layout_
            android:id="@+id/buttonA"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:text="Add"
            android:layout_marginTop="15dp"
    />

    <androidx.appcompat.widget.AppCompatButton
            android:layout_
            android:layout_
            app:layout_constraintStart_toEndOf="@id/buttonA"
            app:layout_constraintEnd_toEndOf="@id/buttonA"
            app:layout_constraintTop_toBottomOf="@id/buttonA"
            android:text="Add"
    />

</androidx.constraintlayout.widget.ConstraintLayout>`

请查看下面的代码,这是一种补丁,但工作正常。在这里我们可以将大块相对于小块。因为我们使用了约束,所以无论你放在哪里都会粘在一起。如果我做错了什么,请告诉我。

这里我们使用一个 dummyView 和 app:layout_constraintHorizontal_bias="0.1" 使其相对值从 0 变为 1,例如 1 表示 100% 表示从左到小块 smae 方式 0.5 表示从小块开始到左的 50%。

 <?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:orientation="vertical"
        android:layout_
        android:layout_>

    <androidx.appcompat.widget.AppCompatButton
            android:layout_
            android:layout_
            android:id="@+id/buttonA"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            android:text="Add"
            android:layout_marginTop="15dp"
    />

    <TextView android:layout_
              android:layout_
              android:id="@+id/dummyView"
              app:layout_constraintTop_toBottomOf="@id/buttonA"
              app:layout_constraintStart_toStartOf="@id/buttonA"
              app:layout_constraintEnd_toEndOf="@id/buttonA"
              app:layout_constraintHorizontal_bias="0.1"/>

    <androidx.appcompat.widget.AppCompatButton
            android:layout_
            android:layout_
            app:layout_constraintTop_toBottomOf="@id/buttonA"
            app:layout_constraintStart_toEndOf="@id/dummyView"
            android:text="Add"
    />

</androidx.constraintlayout.widget.ConstraintLayout>

【讨论】:

不,这仅适用于视图需要相对于另一个视图的宽度/高度中间定位的特殊情况。不适用于一般定位! 好的,我已经更新了我的答案,如果有问题请查看并告诉我。

以上是关于如何相对于彼此定位 2 个视图?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用 ConstraintLayout 中的边距属性的情况下相对于屏幕宽度设置 2 个视图之间的空间

使用 iOS 6 Auto Layout 相对于 superview 的大小定位视图

如何锚定相对于屏幕 iPhone 一侧的视图

iOS - 如何在不调整大小和重新定位按钮视图的情况下更改按钮图像

了解自动布局中的乘数以使用相对定位

如何使用自动布局将图像彼此水平对齐