Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

View getX() and getY() return 0.0 after they have been added to the Activity

In an Activity onCreate() I instantiated a new View and added it via layout.addView to the activity. If i try getX() or getY() for that view I always get 0.0.

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    RelativeLayout main = (RelativeLayout)findViewById(R.id.main);

    RelativeLayout.LayoutParams tpos = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
    Token t = new Token(this,Token.TWO, fieldHeight,fieldWidth);
    tpos.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
    tpos.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
    main.addView(t, tpos);
    System.out.println(t.getX()); //Prints '0.0'
    System.out.println(t.getY()); //Prints '0.0'
like image 742
randomdev8712 Avatar asked Sep 04 '15 14:09

randomdev8712


3 Answers

ViewGroups such as RelativeLayout do not layout their children immediately, and thus your View does not yet know where it will lie on screen. You need to wait for the RelativeLayout to complete a layout pass before that can happen.

You can listen for global layout events like so:

view.getViewTreeObserver().addOnGlobalLayoutListener(
    new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            // Layout has happened here.

            // Don't forget to remove your listener when you are done with it.
            view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        }
    });
like image 186
Bryan Herbst Avatar answered Oct 18 '22 15:10

Bryan Herbst


Another option is to use post(Runnable action) method:

view.post(new Runnable() {
    @Override
    public void run() {
        System.out.println(view.getX());
        System.out.println(view.getY());
    }
});

This will cause the Runnable to be executed after the other pending tasks (such as laying out) are finished.

like image 36
Andrew Vovk Avatar answered Oct 18 '22 15:10

Andrew Vovk


Move your calls to getX() and getY() into onWindowFocusChanged() callback. As the official guide says, that's the best way to know if the activity is visible to the user. Looking at your code, you can put your square into member variables in order to be able to use it with both callbacks.

Try this:

    GameToken mSquare1 = new GameToken(this,GameToken.SQUARE, fieldHeight,fieldWidth);

    ...
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {

          super.onWindowFocusChanged(hasFocus);

          if(hasFocus) {
             System.out.println(mSquare1.getX());
             System.out.println(mSquare1.getY());
          }
    } 

The general rule is that you can't retrieve positions information from your layout within onCreate(), because you are just creating it and android still have to elaborate them.

You can give a chance to onResume() callback too, but for me it didn't work.

like image 2
FedMar Avatar answered Oct 18 '22 14:10

FedMar