Android字谜开发:获取TextView坐标始终为0的问题求解
解决Android中TextView获取位置返回0的问题
你遇到的问题本质上是调用位置获取方法的时机太早——在View完成布局测量和绘制之前,这些方法返回的坐标自然都是0。Android的View有一套完整的布局流程:先执行measure(测量尺寸),再执行layout(确定位置),最后才是draw(绘制)。只有在layout阶段完成后,getLeft()、getLocationInWindow()这类方法才能拿到真实的坐标值。
下面给你几个可靠的解决方案,按场景选择即可:
方法一:使用View.post()延迟执行
这是最简单的解决方案,post()提交的Runnable会被加入View的消息队列,等到View完成布局后再执行:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_game_layout); // 把位置获取的逻辑放到post里 findViewById(R.id.tablojj).post(new Runnable() { @Override public void run() { konumal(); } }); } public void konumal() { int[] korr = new int[2]; TextView targetTv = findViewById(R.id.tablojj); targetTv.getLocationInWindow(korr); Log.w("Dikkat", "x : " + korr[0] + " y : " + korr[1]); }
方法二:监听ViewTreeObserver的布局完成事件
如果你的TextView位置可能随布局动态变化(比如屏幕旋转、窗口调整),可以用这个监听,它会在整个视图树完成布局时触发,记得拿到位置后移除监听避免重复执行:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_game_layout); TextView tablojj = findViewById(R.id.tablojj); ViewTreeObserver observer = tablojj.getViewTreeObserver(); observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // 根据API版本移除监听 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { tablojj.getViewTreeObserver().removeOnGlobalLayoutListener(this); } else { tablojj.getViewTreeObserver().removeGlobalOnLayoutListener(this); } konumal(); } }); }
方法三:在onWindowFocusChanged中调用
当Activity获得窗口焦点时,View的布局肯定已经完成了,适合需要在界面完全显示后获取位置的场景:
private boolean isPositionFetched = false; // 标记是否已经获取过位置,避免重复执行 @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus && !isPositionFetched) { konumal(); isPositionFetched = true; } }
关于方法选择的补充
你原本用的getLocationInWindow()或者getLocationOnScreen()都是正确的方法,问题完全出在调用时机上:
- 如果只需要单次获取位置,优先用
View.post(),代码最简洁; - 如果需要监听布局变化(比如字谜游戏中可能有动态调整布局的需求),用
OnGlobalLayoutListener; - 如果要在界面完全可见后获取位置,用
onWindowFocusChanged。
另外,如果你想获取TextView相对于父布局(比如你的TableLayout)的位置,getLeft()、getTop()同样有效,只要在布局完成后调用就行。
内容的提问来源于stack exchange,提问作者Ahmet Veli
相关产品推荐
相关产品推荐

