ConstraintLayout 相对于 ImageView 尺寸

Tim*_*Tim 1 android vector-graphics android-custom-view android-constraintlayout

我目前正在开发一个小型 Android 应用程序并使用新的 ConstraintLayout。

我有一个 ImageView,它包含一个矢量图形图像,它应该根据其纵横比占用最大的可用空间。我让它与以下代码一起工作:

<ImageView
    android:id="@+id/imageView"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_margin="@dimen/margin"
    android:src="@drawable/image"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    />
Run Code Online (Sandbox Code Playgroud)

现在,我想在确切位置放置多个自定义视图(按钮)。使用约束指南,我想出了以下内容:

<android.support.constraint.Guideline
    android:id="@+id/guideline_x"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.20"
    tools:layout_editor_absoluteX="..."
    tools:layout_editor_absoluteY="..."
    />

<android.support.constraint.Guideline
    android:id="@+id/guideline_y"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintGuide_percent="0.20"
    tools:layout_editor_absoluteX="..."
    tools:layout_editor_absoluteY="..."
    />

<com.example.android.myCustomView
    android:id="@+id/myCustomView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="doSomething"
    app:layout_constraintLeft_toLeftOf="@+id/guideline_x"
    app:layout_constraintTop_toTopOf="@+id/guideline_y"
    />
Run Code Online (Sandbox Code Playgroud)

这对于我最初测试的特定设备非常有用。但是:一旦设备尺寸发生变化,自定义视图就会放置在错误的位置。

我正在寻找一种方法来放置一个自定义视图 n% 相对于图像视图的 x 坐标。我已经尝试添加app:layout_constraintLeft_toLeftOf="@+id/imageView"到指南中,但这没有任何改变。您对我如何解决此问题有任何想法吗?非常感谢!

编辑:这里有 2 张图片说明了这个问题。

三星 Galaxy S8: 三星盖乐世S8

谷歌像素 XL: 谷歌像素 XL

小红方块应始终位于相对于 Android 图标完全相同的位置。

Che*_*amp 5

这是一种更简单的方法,可以将小部件精确地放置在一个ImageView或任何其他视图上,ImageView只要纵横比保持不变,无论大小的任何变化都将保留它的位置。在我的其他答案的第一个建议解决方案中,我建议使用偏差将小部件放置在ImageView. 不幸的是,widget 相对大小的变化ImageView会导致widget 在图像上移动,这是不希望的。

为了解决这个问题,我建议SpaceImageViewusing bias上放置一个 1x1 像素的视图。因为空间视图的大小只有 1x1 像素,所以它可以ImageView通过使用偏置放置在任何地方。它的相对位置将保持不变,ImageView因为在单个设备上旋转或因为应用程序托管在具有不同屏幕尺寸的设备上而改变大小。无论屏幕大小如何,图像的纵横比都必须保持不变,这一点很重要。

放置 1x1 像素视图后,可以通过约束附加小部件。在下面的示例中,我选择通过将每个眼睛小部件的所有边约束到其放置像素的相应边来将眼睛的小部件居中放置在放置像素上。

下面是一些显示效果的图像。我测试过的不同尺寸的屏幕显示相同的结果。

Nexus 6 肖像

Nexus 6 肖像

Nexus 6 横向

在此处输入图片说明

因为ImageView眼睛的s 没有缩放,所以它们在 Nexus 10 屏幕上显得更小。眼睛放置在与 Nexus 6 相同的位置。缩放眼睛是另一回事。

Nexus 10 横向

在此处输入图片说明

这是显示约束的布局:

在此处输入图片说明

位置视图.xml

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

    <ImageView
        android:id="@+id/androidGreen"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:src="@drawable/android_image"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="H,1:1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="ContentDescription" />

    <Space
        android:id="@+id/pinpoint1"
        android:layout_width="1px"
        android:layout_height="1px"
        app:layout_constraintBottom_toBottomOf="@id/androidGreen"
        app:layout_constraintEnd_toEndOf="@id/androidGreen"
        app:layout_constraintHorizontal_bias="0.373"
        app:layout_constraintStart_toStartOf="@id/androidGreen"
        app:layout_constraintTop_toTopOf="@id/androidGreen"
        app:layout_constraintVertical_bias="0.19" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/circle"
        app:layout_constraintBottom_toBottomOf="@id/pinpoint1"
        app:layout_constraintEnd_toEndOf="@id/pinpoint1"
        app:layout_constraintStart_toStartOf="@id/pinpoint1"
        app:layout_constraintTop_toTopOf="@id/pinpoint1"
        app:srcCompat="@drawable/circle"
        tools:ignore="ContentDescription" />

    <Space
        android:id="@+id/pinpoint2"
        android:layout_width="1px"
        android:layout_height="1px"
        android:background="@android:color/holo_red_light"
        app:layout_constraintBottom_toBottomOf="@id/androidGreen"
        app:layout_constraintEnd_toEndOf="@id/androidGreen"
        app:layout_constraintHorizontal_bias="0.625"
        app:layout_constraintStart_toStartOf="@id/androidGreen"
        app:layout_constraintTop_toTopOf="@id/androidGreen"
        app:layout_constraintVertical_bias="0.19" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/circle"
        app:layout_constraintBottom_toBottomOf="@id/pinpoint2"
        app:layout_constraintEnd_toEndOf="@id/pinpoint2"
        app:layout_constraintStart_toStartOf="@id/pinpoint2"
        app:layout_constraintTop_toTopOf="@id/pinpoint2"
        tools:ignore="ContentDescription" />

</android.support.constraint.ConstraintLayout>
Run Code Online (Sandbox Code Playgroud)

您也可以通过包装达到同样的目的ImageViewConstraintLayout与设定的宽度和高度ImageViewmatch_parent。然后,您可以使用百分比指南在ImageView. 此方法在布局层次结构中引入了另一个级别,但可能更容易理解。

这是将演示此方法的 XML。

XML 在嵌套中使用指南 ConstraintLayout

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

    <android.support.constraint.ConstraintLayout
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="H,1:1"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/androidGreen"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/android_image"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:ignore="ContentDescription" />

        <android.support.constraint.Guideline
            android:id="@+id/guidelineHorizontal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.19" />

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

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

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/circle"
            app:layout_constraintBottom_toBottomOf="@id/guidelineHorizontal"
            app:layout_constraintEnd_toEndOf="@id/guidelineVerticalLeft"
            app:layout_constraintStart_toStartOf="@id/guidelineVerticalLeft"
            app:layout_constraintTop_toTopOf="@id/guidelineHorizontal"
            app:srcCompat="@drawable/circle"
            tools:ignore="ContentDescription" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/circle"
            app:layout_constraintBottom_toBottomOf="@id/guidelineHorizontal"
            app:layout_constraintEnd_toEndOf="@id/guidelineVerticalRight"
            app:layout_constraintStart_toStartOf="@id/guidelineVerticalRight"
            app:layout_constraintTop_toTopOf="@id/guidelineHorizontal"
            tools:ignore="ContentDescription" />

    </android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
Run Code Online (Sandbox Code Playgroud)