3

in the project, I tried adding a View object dynamically in a RelativeLayout

    ImageView card = new ImageView(this);
    card.setImageResource(R.drawable.card);
    RelativeLayout.LayoutParams layoutParams =
            new RelativeLayout.LayoutParams(225, 315);
    layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
    layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
    layoutParams.rightMargin = 40;
    parent.addView(card, layoutParams);

after a while, when I tried to get the location of this View, no method works. As I found in Studio's debug view, the View's layoutparams and all its attrs like mLeft... got the value 0.

So how could I solve the problem? thanks a lot.

haitong
  • 53
  • 1
  • 1
  • 9

4 Answers4

8

It might be because you tried to get position before onLayout has happened.

You might try something like this:

ViewTreeObserver vto=view.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener(){
@Override public void onGlobalLayout(){
    int [] location = new int[2];
    view.getLocationOnScreen(location);
    x = location[0];
    y = location[1];
    view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
    }
}

Also check how to get view's position in coordinates?

Community
  • 1
  • 1
Rostyslav Roshak
  • 3,859
  • 2
  • 35
  • 56
  • thanks dude, it works. it still bothers, addView function runs on UIThread, so does getX(). the timing should be addView-measure-layout-draw-getLocation(such as getX). – haitong Apr 14 '17 at 09:56
  • addView just adds the view to the list of children of the `viewgroup`, and marks that the `viewgroup` needs relayout. Relayout would happen when the main looper will get that event. So it would be on the main thread but some time later. – Rostyslav Roshak Apr 14 '17 at 10:09
  • The main thread has its looper, it process all the event's it calls your onCreate, onStart methods, when the screen is resumed it checks, rather views need relayout redraw and layouts, draws them. So when you add the view to the viewgroup, it will not layout it, until the main looper will call layout method. – Rostyslav Roshak Apr 14 '17 at 10:13
  • Hi @haitong if this or any answer has solved your question please consider [accepting it](https://meta.stackexchange.com/q/5234/179419) by clicking the check-mark. This indicates to the wider community that you've found a solution and gives some reputation to both the answerer and yourself. There is no obligation to do this. – Rostyslav Roshak Apr 14 '17 at 11:05
4

You can use these code to get the location:

int loc[]=new int[2];
card.getLocationOnScreen(loc);
int x=loc[0];
int y=loc[1];

If you want to get the location, you have to wait for the View to complete the measurement.

forevas
  • 41
  • 6
4

Simple and best way to find a location of view on screen.

view.post(() -> { 
    xPosition = view.getX());
    yPosition = view.getY();
});

view.post() is used because of that if you try to get view location onCreate() method without using post then you get (0,0) because of that view takes few millisecond to inflate on the screen.

mortalis
  • 2,060
  • 24
  • 34
Asad Mukhtar
  • 391
  • 6
  • 18
0

Using the Data Binding Library in Android to get location of a view.

 private fun getViewLocation(){
    val loginBinding = ActivityLoginBinding.inflate(layoutInflater)
    val locationX = loginBinding.forgotPasswordBtn.x
    val locationY = loginBinding.forgotPasswordBtn.y

// locationX and locationY are returned as Float values }

hayzie101
  • 23
  • 5