我正在尝试获取视图左上角的绝对屏幕像素坐标。但是,我可以找到的所有方法(例如getLeft()
和getRight()
)都不起作用,因为它们似乎都与视图的父级相关,从而为我提供了0
。这样做的正确方法是什么?
如果有帮助,这是为了“让图片重新整理”游戏。我希望用户能够绘制一个框来选择多个部分。我的假设是,最简单的方法是getRawX()
中的getRawY()
和MotionEvent
,然后将这些值与包含各个部分的布局的左上角进行比较。知道了件的大小,我就可以确定已经选择了多少件。我意识到我可以在getX()
上使用getY()
和MotionEvent
,但是会返回一个相对位置,以确定选择哪些部分更加困难。 (我知道,并非不可能,但似乎不必要地复杂化了。)
编辑:根据其中一个问题,这是我用来尝试获取保留容器大小的代码。 TableLayout
是包含所有拼图的表格。
TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
Log.d(LOG_TAG, "Values " + tableLayout.getTop() + tableLayout.getLeft());
编辑2:这是我尝试过的代码,遵循更多建议的答案。
public int[] tableLayoutCorners = new int[2];
(...)
TableLayout tableLayout = (TableLayout) findViewById(R.id.tableLayout);
tableLayout.requestLayout();
Rect corners = new Rect();
tableLayout.getLocalVisibleRect(corners);
Log.d(LOG_TAG, "Top left " + corners.top + ", " + corners.left + ", " + corners.right
+ ", " + corners.bottom);
cells[4].getLocationOnScreen(tableLayoutCorners);
Log.d(LOG_TAG, "Values " + tableLayoutCorners[0] + ", " + tableLayoutCorners[1]);
在所有初始化完成后添加了此代码。图像已被分割为TableLayout
中包含的ImageViews(cells []数组)数组。单元格[0]是左上角ImageView
,我选择了单元格[4],因为它位于中间的某个位置,绝对不应该有(0,0)的坐标。
上面显示的代码仍然在日志中给我全部0,我真的不明白,因为各种拼图正确显示。 (我为tableLayoutCorners和默认可见性尝试了public int,两者都给出了相同的结果。)
我不知道这是否重要,但ImageView
s最初没有给出大小。当我给它显示图像时,视图会自动初始化时确定ImageView
s的大小。这可能会导致它们的值为0,即使这些日志代码是在它们被赋予图像并自动调整大小之后吗?为了解决这个问题,我添加了代码tableLayout.requestLayout()
,如上所示,但这没有帮助。
答案 0 :(得分:576)
答案 1 :(得分:89)
接受的答案实际上并没有说明如何获取位置,所以这里有更多细节。传入长度为2的int
数组,并将值替换为视图的(x,y)坐标(顶部,左上角)。
int[] location = new int[2];
myView.getLocationOnScreen(location);
int x = location[0];
int y = location[1];
备注强>
getLocationOnScreen
替换为getLocationInWindow
应该会得到相同的结果(请参阅this answer)。但是,如果您在像Dialog或自定义键盘这样的较小窗口中,那么您需要选择哪一个更适合您的需求。(0,0)
中调用此方法,则会获得onCreate
,因为该视图尚未布局。你可以使用ViewTreeObserver
来监听布局完成后你可以获得测量的坐标。 (见this answer。)答案 2 :(得分:68)
首先,您必须获取视图的localVisible矩形
例如:
Rect rectf = new Rect();
//For coordinates location relative to the parent
anyView.getLocalVisibleRect(rectf);
//For coordinates location relative to the screen/display
anyView.getGlobalVisibleRect(rectf);
Log.d("WIDTH :", String.valueOf(rectf.width()));
Log.d("HEIGHT :", String.valueOf(rectf.height()));
Log.d("left :", String.valueOf(rectf.left));
Log.d("right :", String.valueOf(rectf.right));
Log.d("top :", String.valueOf(rectf.top));
Log.d("bottom :", String.valueOf(rectf.bottom));
希望这会有所帮助
答案 3 :(得分:44)
使用全局布局侦听器一直很适合我。它具有能够在布局改变时重新测量事物的优点,例如,如果某些内容设置为View.GONE或添加/删除子视图。
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// inflate your main layout here (use RelativeLayout or whatever your root ViewGroup type is
LinearLayout mainLayout = (LinearLayout ) this.getLayoutInflater().inflate(R.layout.main, null);
// set a global layout listener which will be called when the layout pass is completed and the view is drawn
mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
//Remove the listener before proceeding
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
mainLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
mainLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
// measure your views here
}
}
);
setContentView(mainLayout);
}
答案 4 :(得分:17)
按照Romain Guy的评论,这是我如何修复它。希望它能帮助其他任何有这个问题的人。
我确实试图在屏幕布局之前获得观点的位置,但事实并非如此。这些行已经在初始化代码运行后放置,所以我假设一切准备就绪。但是,此代码仍在onCreate()中;通过试验Thread.sleep()我发现布局实际上没有完成,直到onCreate()一直到onResume()完成执行。实际上,代码试图在布局完成定位在屏幕上之前运行。通过将代码添加到OnClickListener(或其他一些Listener),获得了正确的值,因为它只能在布局完成后触发。
以下行被建议为社区编辑:
请使用onWindowfocuschanged(boolean hasFocus)
答案 5 :(得分:5)
我的utils函数用于获取视图位置,它将返回Point
对象x value
和y value
public static Point getLocationOnScreen(View view){
int[] location = new int[2];
view.getLocationOnScreen(location);
return new Point(location[0], location[1]);
}
使用
Point viewALocation = getLocationOnScreen(viewA);
答案 6 :(得分:4)
除了上述答案外,还有关于您应在何时何地致电getLocationOnScreen
的问题?
在与您想要获取的任何视图相关的任何信息中,只有在将视图布置在屏幕上之后,该信息才可用。您可以通过将依赖于视图创建的代码放入其中来轻松实现此目的:(view.post(Runnable))
view.post(new Runnable() {
@Override
public void run() {
// This code will run when view created and rendered on screen
// So as the answer to this question, you can put the code here
int[] location = new int[2];
myView.getLocationOnScreen(location);
int x = location[0];
int y = location[1];
}
});
答案 7 :(得分:1)
第一种方式:
在科特林中,我们可以为视图创建一个简单的扩展名:
predict(Model, newdata=df)[1:4]
245 246 247 248
11.71199 272.55443 246.69057 220.82672
只需获取坐标:
fun View.getLocationOnScreen(): Point
{
val location = IntArray(2)
this.getLocationOnScreen(location)
return Point(location[0],location[1])
}
第二种方式:
第二种方法更简单:
val location = yourView.getLocationOnScreen()
val absX = location.x
val absY = location.y
并仅通过fun View.absX(): Int
{
val location = IntArray(2)
this.getLocationOnScreen(location)
return location[0]
}
fun View.absY(): Int
{
val location = IntArray(2)
this.getLocationOnScreen(location)
return location[1]
}
获得绝对X,通过view.absX()
获得Y
答案 8 :(得分:1)
您可以使用getLocationOnScreen()
或getLocationInWindow()
int[] point = new int[2];
view.getLocationOnScreen(point); // or getLocationInWindow(point)
int x = point[0];
int y = point[1];
然后,x
和y
应该在视图的左上角。如果您的根目录布局小于屏幕(例如在对话框中),则使用getLocationInWindow
相对于其容器,而不是整个屏幕。
注意::如果值始终为0,则可能会在请求位置之前立即更改视图。
为确保视图有机会更新,请在使用view.post
计算出视图的新布局后运行您的位置请求:
view.post(() -> {
// Values should no longer be 0
int[] point = new int[2];
view.getLocationOnScreen(point); // or getLocationInWindow(point)
int x = point[0];
int y = point[1];
});
答案 9 :(得分:0)
val viewTreeObserver: ViewTreeObserver = videoView.viewTreeObserver;
if (viewTreeObserver.isAlive) {
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
//Remove Listener
videoView.viewTreeObserver.removeOnGlobalLayoutListener(this);
//View Dimentions
viewWidth = videoView.width;
viewHeight = videoView.height;
//View Location
val point = IntArray(2)
videoView.post {
videoView.getLocationOnScreen(point) // or getLocationInWindow(point)
viewPositionX = point[0]
viewPositionY = point[1]
}
}
});
}
答案 10 :(得分:-2)
使用此代码查找确切的X和Y坐标:
int[] array = new int[2];
ViewForWhichLocationIsToBeFound.getLocationOnScreen(array);
if (AppConstants.DEBUG)
Log.d(AppConstants.TAG, "array X = " + array[0] + ", Y = " + array[1]);
ViewWhichToBeMovedOnFoundLocation.setTranslationX(array[0] + 21);
ViewWhichToBeMovedOnFoundLocation.setTranslationY(array[1] - 165);
我添加/减去了一些值来调整我的视图。 请仅在整个视图曝光后执行这些行。