一. View 获取坐标的方法

  1. View.getTop()、View.getLeft()、View.getBottom()、View.getRight();

  2. View.getX()、View.getY();

  3. View.getTranslationX()、View.getTranslationY(); 等

  4. View.getLocationInWindow(int[] position);

  5. View.getLocationOnScreen(int[] position);

二. 获取View真实位置的坐标

  • 这四个获取View坐标位置的方法是相对于父ViewGroup来说的。
  • 这四个获取的值不会因为补间动画而发生改变。
1
2
3
4
View.getLeft()  //View 左上顶点相对于父容器的横坐标
View.getTop() //View 左上顶点相对于父容器的纵坐标
View.getRight() //View 右下顶点相对于父容器的横坐标
View.getBottom()//View 右下顶点相对于父容器的纵坐标

三.获取View显示位置的坐标

  • 这两个获取View坐标位置的方法是相对于父ViewGroup来说的。
  • 这两个获取的值会因为补间动画而发生改变。
1
2
getX() //view的左上角相对父容器的横坐标
getY() //view的左上角相对父容器的纵坐标

四.获取View属性动画的偏移值

  • 一般情况下 getX() = getLeft(),但是如果发生了属性动画,比如TranslationX。那么,getX() - getLeft() = getTranslationX()。

  • translationX是真实view 相对于看到view的 x 方向偏移量。

1
2
3
4
5
6
7
8
9
10
11
getTranslationX() //真实view 相对于看到view的 x 方向偏移量
getPivotX()
getRotationX()
getScaleX()
getScrollX()

getTranslationY() //真实view 相对于看到view的 y 方向偏移量
getPivotY()
getRotationY()
getScaleY()
getScrollY()

五.获取View相对于父窗口的坐标

  • 获取的是相对于父窗口的坐标,而不是父容器的坐标。
  • 一般情况下获取的值和View.getLocationOnScreen(position);获取的值相同。有弹窗的情况下,两者会不同。
1
2
3
4
5
int[] position = new int[2];
View.getLocationInWindow(position);

position[0] //view的左上角相对父窗口的横坐标
position[1] //view的左上角相对父窗口的纵坐标

六.获取View相对于屏幕的坐标

  • 获取的是相对于屏幕的坐标。
  • 可以利用position[1]-View.getTop()),作为一种获取状态栏高度的方法。
1
2
3
4
5
int[] position = new int[2];
View.getLocationOnScreen(position);

position[0] //view的左上角相对屏幕的横坐标
position[1] //view的左上角相对屏幕的纵坐标

七.其他

1.获取屏幕的宽高

1
2
3
4
5
View.getWidth()
View.getRight()-View.getLeft()

View.getHeight()
View.getBottom()-View.getTop()

2.获取状态栏的高度

1
2
3
Rect frame = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;

3.Touch事件获取触摸点的坐标

1
2
3
4
5
6
7
MotionEvent event;

float x = event.getX(); //获得触摸点相对于控件的横坐标
float y = event.getY(); //获得触摸点相对于控件的纵坐标

float rawX = event.getRawX();//获取触摸点相对于屏幕的横坐标
float rawY = event.getRawY();//获取触摸点相对于屏幕的纵坐标

八.测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class MainActivity extends AppCompatActivity {

public static final String TAG = MainActivity.class.getSimpleName();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

RelativeLayout relativeLayout = findViewById(R.id.root);
final ImageView imageView = findViewById(R.id.imgView);

imageView.post(new Runnable() {
@Override
public void run() {
Log.d(TAG,"Width:"+imageView.getWidth());
Log.d(TAG,"Height:"+imageView.getHeight());

Log.d(TAG,"Left:"+imageView.getLeft());
Log.d(TAG,"Top:"+imageView.getTop());
Log.d(TAG,"Right:"+imageView.getRight());
Log.d(TAG,"Bottom:"+imageView.getBottom());

Log.d(TAG,"X:"+imageView.getX());
Log.d(TAG,"Y:"+imageView.getY());

int[] position1 = new int[2];
imageView.getLocationInWindow(position1);
Log.d(TAG,"窗口左上角X:"+position1[0]);
Log.d(TAG,"窗口左上角Y:"+position1[1]);

int[] position2 = new int[2];
imageView.getLocationOnScreen(position2);
Log.d(TAG,"屏幕左上角X:"+position2[0]);
Log.d(TAG,"屏幕左上角Y:"+position2[1]);

Log.d(TAG,"状态栏的dp:"+(position2[1]-imageView.getTop()));

Rect frame = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
Log.d(TAG,"状态栏的dp:"+statusBarHeight);
}
});
}
}

小米8的测试结果,注意,下面的数值都是以 px 作为单位的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
2020-03-25 11:13:12.864 9239-9239/? D/MainActivity: Width:297
2020-03-25 11:13:12.864 9239-9239/? D/MainActivity: Height:297
2020-03-25 11:13:12.864 9239-9239/? D/MainActivity: Left:391
2020-03-25 11:13:12.865 9239-9239/? D/MainActivity: Top:931
2020-03-25 11:13:12.865 9239-9239/? D/MainActivity: Right:688
2020-03-25 11:13:12.865 9239-9239/? D/MainActivity: Bottom:1228
2020-03-25 11:13:12.865 9239-9239/? D/MainActivity: X:391.0
2020-03-25 11:13:12.865 9239-9239/? D/MainActivity: Y:931.0
2020-03-25 11:13:12.865 9239-9239/? D/MainActivity: 窗口左上角X:391
2020-03-25 11:13:12.865 9239-9239/? D/MainActivity: 窗口左上角Y:1020
2020-03-25 11:13:12.866 9239-9239/? D/MainActivity: 屏幕左上角X:391
2020-03-25 11:13:12.866 9239-9239/? D/MainActivity: 屏幕左上角Y:1020
2020-03-25 11:13:12.866 9239-9239/? D/MainActivity: 状态栏的dp:89
2020-03-25 11:13:12.867 9239-9239/? D/MainActivity: 状态栏的dp:89

参考文章

Android View坐标系详解(getTop()、getX、getTranslationX…)

View 的 translationX、 translationY , X、Y 和 Left、Top,Right、Bottom

深刻理解getLocationInWindow 和 getLocationOnScreen区别

android getLocationOnScreen笔记

【Android开发】View的平移、缩放、旋转以及位置、坐标系