如何使用约束布局在 Android 中为所有显示尺寸正确对齐两个 imageView

How to correctly allign two imageViews in Android for all display sizes using constraint layout

提问人:VanessaF 提问时间:9/24/2023 最后编辑:VanessaF 更新时间:10/3/2023 访问量:74

问:

我在 Android 中有 2 个图像视图。一个是风力涡轮机杆,另一个是风力涡轮机叶片。如何设置布局约束,使风力涡轮机叶片始终正确连接到杆上?它们应该适合不同的屏幕分辨率。

这是布局编辑器的屏幕截图:

enter image description here

下面是 xml 布局代码:

<?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:id="@+id/constraintLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    tools:context=".MainActivity">


    <ImageView
        android:id="@+id/imageView_windTurbinePole"
        android:layout_width="150dp"
        android:layout_height="150dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/wind_turbine_pole" />

    <ImageView
        android:id="@+id/imageView_windTurbineBlade"
        android:layout_width="120dp"
        android:layout_height="120dp"
        app:layout_constraintBottom_toTopOf="@+id/imageView_windTurbinePole"
        app:layout_constraintEnd_toEndOf="@+id/imageView_windTurbinePole"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="@+id/imageView_windTurbinePole"
        app:srcCompat="@drawable/wind_turbine_blade" />
    
</androidx.constraintlayout.widget.ConstraintLayout>

更新:所需的图像应该看起来像一个“真正的”风力涡轮机,叶片在杆子上。更大的图景是,我想在 Android 中制作一个叶片旋转的动画。

enter image description here

安卓 android-layout android-imageview

评论

0赞 Vlad Guriev 9/25/2023
您能否描述一下“正确连接到杆子”的预期含义和预期结果?也许还提供某些屏幕分辨率可能不正确的示例
0赞 VanessaF 9/28/2023
@VladGuriev:感谢弗拉德的评论。我添加了一张所需结果的图片
0赞 Vlad Guriev 9/28/2023
感谢您的澄清!我认为您可以尝试添加以将其中一张图像放置在更靠近另一张图像的位置android:translationY="...dp"
0赞 VanessaF 9/29/2023
@VladGuriev:感谢弗拉德的评论。但是我怎么能保证它们正确地相互对接,特别是考虑到不同的屏幕尺寸和分辨率
1赞 Vlad Guriev 10/3/2023
写了以上的总结作为答案

答:

1赞 Vlad Guriev 10/3/2023 #1

如果您需要视图高度是屏幕高度的一小部分,则可以使用如下所示:

app:layout_constraintHeight_percent="0.224"

然后,如果需要将杆子移近刀片,可以在 doOnPreDraw 中的代码中完成。

您也可以从 Java 中使用它:

androidx.core.view.ViewKt.doOnPreDraw(windTurbinePoleView, view -> {
    windTurbinePoleView.setTranslationY(- FRACTION * windTurbineBlade.getHeight());
    return null;
});

在这里,我将移动 windTurbinePoleView,您可以将类似的方法应用于 windTurbineBladeView。 是一个常数,表示叶片的图像底部与中心圆底部之间的距离除以叶片的图像高度。FRACTION

如果“doOnPreDraw”部分未解析,则可以添加依赖项。或者,您可以出于相同的目的使用。androidx.core:core-ktx:VERSIONwindTurbinePoleView.getViewTreeObserver().addOnPreDrawListener(...)

评论

0赞 VanessaF 10/3/2023
非常感谢弗拉德的回答。我有一些问题。1) 为什么我必须在 doOnPreDraw 方法之前使用?这看起来很奇怪。3) 为什么我必须返回方法?我是在定义一个新方法,还是只是调用它?如果我调用它,就不需要 null(至少我从未见过这样的东西) 3)你是怎么计算的,你为什么要计算它。你能给我看一下代码吗?实际上,在我的情况下,杆的位置应该是固定的,叶片应该是平移的androidx.core.view.ViewKtnullFraction
0赞 Vlad Guriev 10/3/2023
1)这是完整的路径,但您可以将这部分移动到该部分,只需将光标放在或上,然后按Option+Enter。当使用从 Java 3) 返回的 lambda 时,这是 Kotlin-Java 互操作权衡,不是在代码上计算的,它是一个常量。您只需在图像编辑器中测量叶片的图像底部和中心圆底部之间的距离,然后测量叶片的图像高度,然后将第一个值除以第二个值。importViewKtdoOnPreDrawkotlin.UnitFRACTION
0赞 Vlad Guriev 10/3/2023
@VanessaF,如果移动刀片,则此处不需要“-”:windTurbineBlade.setTranslationY(FRACTION * windTurbineBlade.getHeight())
0赞 VanessaF 10/5/2023
非常感谢弗拉德的回答。它帮助很大。我真的很感激。