michpohl
michpohl

Reputation: 1115

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

I have a RelativeLayout inside a fragment that one of three tabs in a TabView. See this Screenshot - big pink square is my RelativeLayout: screenshot

The view that is inside it is the little blue square in the bottom right corner. Since the RelativeLayout is 300x300dp and the little square is 8x8dp, if I set its top and left margin to 292dp it ends up in that corner. Now I want to change its position programmatically, but when I do it, my values keep getting divided by two. So if I change the margins from 292 to 292 it ends up in the center of the RelativeLayout, but if I set each to 292*2, it ends up back in the corner. Maybe there is someone who knows what is happening here?

This is my layout file:

<?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>

and this is the method I use to update the margins:

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

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

I tried to keep the code short and limited to what's relevant, if something important is missing please let me know and I put it in. I'm writing this one in Kotlin, but Java answers will be helpful too. Thank you.

Upvotes: 0

Views: 48

Answers (2)

Fredy Mederos
Fredy Mederos

Reputation: 2636

The values you are using to update your margins are in px size

params.topMargin = 292
params.leftMargin = 292

If you want to change them to 292dp you should load a dimen resource or multiply the value for displayMetric density

You can use the anko dip function

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

Your code will look like this:

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

Maybe this can fix your issue.

Upvotes: 0

Ben P.
Ben P.

Reputation: 54204

Almost all Java-code dimension values that are just raw int or float use px units, not dp. It is very likely that you are executing your code on an hdpi device. If so, your screen density means that 1dp == 2px, and this would explain why everything seems to be "divided by 2".

You can find your current screen density with code like this:

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

And you can then multiply any dp values by this density to get the px values.

Alternatively, if you're working with dimensions that you've stored as <dimen> resources, you can just call:

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

Upvotes: 1

Related Questions