View-相关位置参数

View的简介

View是所有控件的基础,熟悉和了解对于每个Android开发者来说必不可少,接下来我们就针对于Android的View从源码角度上进行深入的学习。

1.View的坐标

我们知道,获取一个View 左上和右下的两个坐标的四个值,分别对应以下四个函数:

图片来自Android开发艺术探索

 /**
     * Top position of this view relative to its parent.
     *
     * @return The top of this view, in pixels.
     */
    @ViewDebug.CapturedViewProperty
    public final int getTop() {
        return mTop;
    }

  /**
     * Bottom position of this view relative to its parent.
     *
     * @return The bottom of this view, in pixels.
     */
    @ViewDebug.CapturedViewProperty
    public final int getBottom() {
        return mBottom;
    }


 /**
     * Left position of this view relative to its parent.
     *
     * @return The left edge of this view, in pixels.
     */
    @ViewDebug.CapturedViewProperty
    public final int getLeft() {
        return mLeft;
    }

    /**
     * Right position of this view relative to its parent.
     *
     * @return The right edge of this view, in pixels.
     */
    @ViewDebug.CapturedViewProperty
    public final int getRight() {
        return mRight;
    }

以上四个函数获取到的就是 mTop,mBottom,mLeft,mRight View的四个位置属性。

 /**
     * The distance in pixels from the left edge of this view's parent
     * to the left edge of this view.
     * {@hide}
     */
    @ViewDebug.ExportedProperty(category = "layout")
    protected int mLeft;
    /**
     * The distance in pixels from the left edge of this view's parent
     * to the right edge of this view.
     * {@hide}
     */
    @ViewDebug.ExportedProperty(category = "layout")
    protected int mRight;
    /**
     * The distance in pixels from the top edge of this view's parent
     * to the top edge of this view.
     * {@hide}
     */
    @ViewDebug.ExportedProperty(category = "layout")
    protected int mTop;
    /**
     * The distance in pixels from the top edge of this view's parent
     * to the bottom edge of this view.
     * {@hide}
     */
    @ViewDebug.ExportedProperty(category = "layout")
    protected int mBottom;
结论

通过注释上面介绍的很清楚,我们获取到的值都是基于当前View的父布局而言。这点要特别注意。

通过以上图示,我们可以很容易得到布局的宽高和这四个参数之间的关系

width = mRight - mLeft
height = mBottom - mTop

 /**
     * Return the width of your view.
     *
     * @return The width of your view, in pixels.
     */
    @ViewDebug.ExportedProperty(category = "layout")
    public final int getWidth() {
        return mRight - mLeft;
    }

    /**
     * Return the height of your view.
     *
     * @return The height of your view, in pixels.
     */
    @ViewDebug.ExportedProperty(category = "layout")
    public final int getHeight() {
        return mBottom - mTop;
2.getX与getY和getleft,getBottom区别?

我们先来看下getX与getY的源码

   /**
     * The visual x position of this view, in pixels. This is equivalent to the
     * {@link #setTranslationX(float) translationX} property plus the current
     * {@link #getLeft() left} property.
     *
     * @return The visual x position of this view, in pixels.
     */
    @ViewDebug.ExportedProperty(category = "drawing")
    public float getX() {
        return mLeft + getTranslationX();
    }
 /**
     * The visual y position of this view, in pixels. This is equivalent to the
     * {@link #setTranslationY(float) translationY} property plus the current
     * {@link #getTop() top} property.
     *
     * @return The visual y position of this view, in pixels.
     */
    @ViewDebug.ExportedProperty(category = "drawing")
    public float getY() {
        return mTop + getTranslationY();
    }

getX上面注释写到:此视图的可视x位置,单位为像素。它等价于translationX+当前getLeft()的属性。

结论

1.getX获取到是View在X轴上移动以后相对于父布局的值。如果view并未进行平移操作,该值与getleft一致,getY同理**

3.getTranslationX()与getTranslationY()

我们再来看一看这两个方法的源码

   /**
     * The horizontal location of this view relative to its {@link #getLeft() left} position.
     * This position is post-layout, in addition to wherever the object's
     * layout placed it.
     *
     * @return The horizontal position of this view relative to its left position, in pixels.
     */
    @ViewDebug.ExportedProperty(category = "drawing")
    public float getTranslationX() {
        return mRenderNode.getTranslationX();
    }

/**
     * 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.
     */
    @ViewDebug.ExportedProperty(category = "drawing")
    public float getTranslationY() {
        return mRenderNode.getTranslationY();
    }
结论

通过注释了解到getTranslationX() getTranslationY() 得到是新位置与最初位置的差值,也即移动了多少距离。

4.RenderNode是什么?

有同学注意到了,getTranslationX()获取view的偏移量是通过RenderNode这个类去实现的,RenderNode是个什么呢?我们看下RenderNode的源码

我们先看一下RenderNode是在哪和View联系起来的

RenderNode与View建立关联

 public View(Context context) {
        mContext = context;
        mResources = context != null ? context.getResources() : null;
        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
        // Set some flags defaults
        mPrivateFlags2 =
                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
        mUserPaddingStart = UNDEFINED_PADDING;
        mUserPaddingEnd = UNDEFINED_PADDING;
        mRenderNode = RenderNode.create(getClass().getName(), this);

RenderNode初始化方法

  /**
     * Creates a new RenderNode that can be used to record batches of
     * drawing operations, and store / apply render properties when drawn.
     *
     * @param name The name of the RenderNode, used for debugging purpose. May be null.
     *
     * @return A new RenderNode.
     */
    public static RenderNode create(String name, @Nullable View owningView) {
        return new RenderNode(name, owningView);
    }


RenderNode获取偏移量的方法

  /**
     * Returns the translation value for this display list on the X axis, in pixels.
     *
     * @see #setTranslationX(float)
     */
    public float getTranslationX() {
        return nGetTranslationX(mNativeRenderNode);
    }

    /**
     * Sets the translation value for the display list on the Y axis.
     *
     * @param translationY The Y axis translation value of the display list, in pixels
     *
     * @see View#setTranslationY(float)
     * @see #getTranslationY()
     */
    public boolean setTranslationY(float translationY) {
        return nSetTranslationY(mNativeRenderNode, translationY);
    }


	//除了获取xy偏移量还有一大堆其他属性,例如,缩放,旋转,等偏移量参数

 	@CriticalNative
    private static native float nGetTranslationX(long renderNode);
    @CriticalNative
    private static native float nGetTranslationY(long renderNode);
    @CriticalNative
    private static native float nGetTranslationZ(long renderNode);
    @CriticalNative
    private static native float nGetRotation(long renderNode);
    @CriticalNative
    private static native float nGetRotationX(long renderNode);
    @CriticalNative
    private static native float nGetRotationY(long renderNode);
    @CriticalNative
    private static native boolean nIsPivotExplicitlySet(long renderNode);
    @CriticalNative
    private static native float nGetPivotX(long renderNode);
    @CriticalNative
    private static native float nGetPivotY(long renderNode);
	。。。。。。。
结论

(1).通过代码我们看到,RenderNode是view在构造函数中与View关联起来的。
(2).RenderNode作用是用于记录View的批次绘制操作,并在绘制时存储/应用渲染属性。
(3).RenderNode记录获取绘制相关是通过调用底层C处理的。

5.MotionEvent 中的 getX,getY,getRawX,getRawY?

手指接触屏幕后发生的一系列事件中,通过MotionEvent类我们可以使用getX,getY,和getRawX,getRawY,这个获取到的坐标有什么区别呢?

我们先看下getRawX

/**
     * 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
     */
    public final float getRawX() {
        return nativeGetRawAxisValue(mNativePtr, AXIS_X, 0, HISTORY_CURRENT);
    }

注释介绍很清楚,rawX返回的是点击屏幕,相对于屏幕的的绝对坐标

 /**
     * {@link #getX(int)} for the first pointer index (may be an
     * arbitrary pointer identifier).
     *
     * @see #AXIS_X
     */
    public final float getX() {
        return nativeGetAxisValue(mNativePtr, AXIS_X, 0, HISTORY_CURRENT);
    }

nativeGetAxisValue是一个调用C层代码的函数,传入三个参数:mNativePtr MotionEvent的指针,AXIS_X,轴常数运动事件的X轴
。由于C层的代码我们不清楚文档上也没有具体说明,但是我们可以通过代码试验的方式去验证一下。这里就不在具体写了,最终的结果就是getX()返回的是相对于当前view父布局的坐标,getY同理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值