以编程方式将边距设置为 RelativeLayout 内的视图时,如何解释这种奇怪的行为?

How to explain this weird behaviour when programmatically setting margins to a view inside RelativeLayout?

我在 TabView 中的三个选项卡之一的片段中有一个 RelativeLayout。请参阅此屏幕截图 - 大粉红色方块是我的 RelativeLayout: screenshot

里面的景色就是右下角的蓝色小方块。由于 RelativeLayout 是 300x300dp 而小方块是 8x8dp,如果我将它的上边距和左边距设置为 292dp,它就会在那个角落结束。 现在我想以编程方式更改其位置,但是当我这样做时,我的值一直被二除。因此,如果我将边距从 292 更改为 292,它最终会位于 RelativeLayout 的中心,但如果我将每个边距都设置为 292*2,它最终会回到角落。 也许有人知道这里发生了什么?

这是我的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

  
    <android.support.constraint.ConstraintLayout

        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:width="40dp"
            android:height="40dp"
            android:background="@color/colorAccent"
            android:text="Test!" />

        <RelativeLayout
            android:layout_width="300dp"
            android:layout_height="300dp"
            android:background="@color/colorAccent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <View
                android:id="@+id/position_dot"
                android:layout_width="8dp"
                android:layout_height="8dp"
                android:layout_alignParentStart="true"
                android:layout_alignParentTop="true"
                android:background="@color/colorPrimary"
                android:layout_marginLeft="292dp"
                android:layout_marginTop="292dp"/>

        </RelativeLayout>


    </android.support.constraint.ConstraintLayout>


</layout>

这是我用来更新边距的方法:

 fun moveDotToCurrentPosition() {
        var params = positionDot.layoutParams as RelativeLayout.LayoutParams

        params.topMargin = 292
        params.leftMargin = 292
       
        positionDot.layoutParams = params
    }

我尽量使代码简短并限制在相关内容内,如果缺少重要内容,请告诉我,我将其放入。 我正在用 Kotlin 编写这篇文章,但 Java 答案也会有所帮助。 谢谢。

几乎所有 Java-代码维度值只是原始 intfloat 使用 px 单位,不是 dp。您很可能正在 hdpi 设备上执行代码。如果是这样,您的屏幕密度意味着 1dp == 2px,这可以解释为什么一切看起来都是 "divided by 2".

您可以使用如下代码找到您当前的屏幕密度:

float density = [context].getResources().getDisplayMetrics().density;

然后您可以将任何 dp 值乘以这个 density 得到 px 值。

或者,如果您正在使用存储为 <dimen> 资源的维度,您可以调用:

int dimen = [context].getResources().getDimensionPixelSize(R.dimen.my_dimen);

您用于更新页边距的值以 px 大小为单位

params.topMargin = 292
params.leftMargin = 292

如果您想将它们更改为 292dp,您应该加载 dimen 资源或乘以 displayMetric 密度的值

可以使用anko dip函数

fun Context.dip(value: Int): Int = (value * resources.displayMetrics.density).toInt()

您的代码将如下所示:

params.topMargin = dip(292)
params.leftMargin = dip(292)

也许这可以解决您的问题。