View之坐标体系

View关于坐标方法系列

相对坐标系列

MotionEvent 系列方法

  • e.getX()/e.getY()

    /**
     * Returns the X coordinate of this event for the given pointer
     * index (use {@link #getPointerId(int)} to find the pointer
     * identifier for this index).
     * Whole numbers are pixels; the 
     * value may have a fraction for input devices that are sub-pixel precise. 
     * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
     * (the first pointer that is down) to {@link #getPointerCount()}-1.
     *
     * @see #AXIS_X
     */
    

    触摸点相对于View自身的X,Y坐标偏移量。

View 系列方法

  • view.getTop()/getLeft()/getRight()/getBottom()

    /**
     * Left position of this view relative to its parent.
     *
     * @return The left edge of this view, in pixels.
     */
    

    得到的坐标是view相对于其父容器的坐标,也即是view在父容器中的绘制区域。实际上right-left 与bottom-top正好是view的width与height

    以父容器的左上角为坐标原点

    具体测试代码结果下文有贴入,这里简单描述一下结果。

    revenueLayout的top为100,恰好是其相对父容器的一个margin值;tvProfit的top为15,恰好是其父容器revenueLayout的padding大小。

  • view.getTranslationX()/getTranslationY()

    /**
     * The vertical location of this view relative to its {@link #getTop() top} position.
     * This position is post-layout, in addition to wherever the object's
     * layout placed it.
     *
     * @return The vertical position of this view relative to its top position,
     * in pixels.
     */
    

    得到的值是其相对于初始的left or top 的平移距离,,这个与属性动画中的translation设置有关系

绝对坐标系列

以屏幕的左上角为坐标原点

View系列方法

  • view.getLocationInWindow(@Size(2) int[] outLocation)

    /**
     * 

    Computes the coordinates of this view in its window. The argument * must be an array of two integers. After the method returns, the array * contains the x and y location in that order.

    * * @param outLocation an array of two integers in which to hold the coordinates */

    获取当前view在Window中的坐标,也即是window的绝对坐标

  • view.getLocationOnScreen(@Size(2) int[] outLocation)

    /**
     * 

    Computes the coordinates of this view on the screen. The argument * must be an array of two integers. After the method returns, the array * contains the x and y location in that order.

    * * @param outLocation an array of two integers in which to hold the coordinates */

    与getLocationInWindow()的返回相同,下面的测试结果中也验证了是相同。具体是不是存在特殊的差异,还未发现

  • view.getGlobalVisibleRect(Rect r)/getGlobalVisibleRect(Rect r, Point globalOffset)

    /**
     * If some part of this view is not clipped by any of its parents, then
     * return that area in r in global (root) coordinates. To convert r to local
     * coordinates (without taking possible View rotations into account), offset
     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
     * If the view is completely clipped or translated out, return false.
     *
     * @param r If true is returned, r holds the global coordinates of the
     *        visible portion of this view.
     * @param globalOffset If true is returned, globalOffset holds the dx,dy
     *        between this view and its root. globalOffet may be null.
     * @return true if r is non-empty (i.e. part of the view is visible at the
     *         root level.
     */
    

    获取当前view在绝对坐标系中的rect对象,也即是绘制区域的绝对坐标边界。

MotionEvent 系列方法

  • e.getRawX()/e.getRawY()

    /**
     * Returns the original raw X coordinate of this event.  For touch
     * events on the screen, this is the original location of the event
     * on the screen, before it had been adjusted for the containing window
     * and views.
     *
     * @see #getX(int)
     * @see #AXIS_X
     */
    

    触摸点相对于屏幕原点的x,y坐标。

测试案例

机型信息如下:

device_info.png

布局文件View位置



    

    


预览截图如下:

xml_preview.png

onResume()中执行结果:

location_onresume.png

onResume中并没有获取到View坐标信息

onWindowFocusChanged()中执行结果:

activity 应用全屏主题(NoTitle)

location_notitle.png

activity 为应用全屏主题(有actionbar)

location_actionbar.png

从上述两个运行结果来看,getLocationInWindow()与getLocationOnScreen()并未存在差异。

其中tvBalance的position [15,169],Y坐标169是100(revenueLayout的margin)+15(revenueLayout的padding)+54(状态栏status bar的高度,此值是反推出来的)。由此就可以看出获取的确实是View的绝对坐标。

而对于应用非全屏(NoTitle)主题的结果,position [15,337],恰好就是多出了一个actionbar的高度,即337-169 = 168。而168恰好满足56*3(density),这里就看到了,在系统默认的配置下当前的屏幕宽度下,actionbar的高度为56dp,当前的density恰好是3.0,而换算成px就是168。到了这里,整个测试结果就完全验证了,上述方法的解释。

备注:

  • View的坐标体系在OnCreate()中还未进行初始化,所以onCreate中无法获取View的相关坐标,都是return 0;
  • View的坐标在onWindowFocusChanged(true)时,才会初始化完毕,故在此方法的回调是获取View坐标的最佳之处。
  • 由于onResume与onWindowFocusChanged的调用时机的不同,在第一次执行onResume时也无法直接获取到View的坐标。

参考

  • Android视图坐标体系总结
  • Android MotionEvent详解

你可能感兴趣的:(View之坐标体系)