Reputation: 320
I'm trying to understand what happens when I use setX and setY to change view position dynamically, what is the process the is taken by android to translate these values and preposition a view specially with different devices screen densities out there because obviously from what I have experienced the view doesn't move to the exact same Y coordinate, I even tried to setY() into a constant number and still there is always a shift in the result.
I made a new project just for testing, this is the xml file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/relativeLayout_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layoutDirection="ltr"
>
<TextView
android:id="@+id/move_me"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Move this!"
android:layout_alignParentBottom="true"/>
<TextView
android:id="@+id/here_to_stay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Here!"
/>
<Button
android:id="@+id/location_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Change Location"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
and this is the java file:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import org.w3c.dom.Text;
public class MainActivity extends AppCompatActivity {
private final String CONTEXT = "MainActivity";
//define view variables
TextView moveThisTxtView;
TextView hereToStayTxtView;
Button changeLocationBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
moveThisTxtView = (TextView)findViewById( R.id.move_me );
hereToStayTxtView = (TextView)findViewById( R.id.here_to_stay );
changeLocationBtn = (Button)findViewById( R.id.location_btn );
changeLocationBtn.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
//get view position
int[] textViewLocation = new int[2];
int[] oldLocation = new int[2];
moveThisTxtView.getLocationOnScreen( oldLocation );
int oldPosX = oldLocation[0];
int oldPosY = oldLocation[1];
hereToStayTxtView.getLocationOnScreen( textViewLocation );
final int targerPosX = textViewLocation[0];
final int targetPosY = textViewLocation[1];
Log.v(CONTEXT, "the here to stay x and y are:" + targerPosX +
", " + targetPosY);
Log.v(CONTEXT, "the view old x and y are:" + oldPosX+ ", " +
oldPosY);
moveThisTxtView.setX(targerPosX);
moveThisTxtView.setY(targetPosY);
}
} );
}
@Override
public void onWindowFocusChanged (boolean hasFocus) {
int[] newLocation = new int[2];
moveThisTxtView.getLocationOnScreen( newLocation );
int newPosX = newLocation[0];
int newPosY = newLocation[1];
Log.v(CONTEXT, "the new x and y are:" + newPosX + ", " + newPosY);
}
}
I have no idea why but I only having problem with y coordinate the x is always correct in all devices I don't even need to divide it by the density only the y is always wrong even in mdp devices. This what made me ask the question how is this all working?
Upvotes: 0
Views: 71
Reputation: 61
Pixels are the individual dots of light on a display. As you said, the view won't always move to the same place in the display because different displays have different pixel densities. For example, the new iPhone Xr is mocked for having such poor pixel density; it is a huge screen, but it only gets you 720p.
You should use density-independent pixels (dp
) as your unit of measurement when setting position, height, width, and other dimensional attributes. Using dp
should allow you to display your view the same way in any device.
In your case, you want to change positions dynamically, but you can't define dp
in Java. To do this, you could create a dimens.xml
under res/values
with the following contents:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="my_dimen">48dp</dimen>
</resources>
You can then refer to this value using getResources().getDimension(R.dimen.my_dimen)
Upvotes: 1