Android 坐标系相关

1.getLocationInWindow和getLocationOnScreen

①一个控件在其父窗口中的坐标位置

View.getLocationInWindow(int[] location)

一个控件在其整个屏幕上的坐标位置,注意这个值要从屏幕顶端算起,也就是包括了通知栏的高度。

View.getLocationOnScreen(int[] location)

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5a2f6Iqz6Iqz,size_10,color_FFFFFF,t_70,g_se,x_16

 getLocationInWindow是以B为原点的C的坐标

getLocationOnScreen以A为原点。

注意:在Activity的onCreate()方法里获取这些值时,全为0,要等UI控件都加载完了才能获取到。因此在onWindowFocusChanged(boolean hasFocus)中获取为好。

②getLocationOnScreen示例:

start = (Button) findViewById(R.id.start);  

int []location=new int[2];  

start.getLocationOnScreen(location);  

int x=location[0];//获取当前位置的横坐标  

int y=location[1];//获取当前位置的纵坐标  

getLocationInWindow示例:

start = (Button) findViewById(R.id.start);  

int []location=new int[2];  

start.getLocationInWindow(location);  

int x=location[0];//获取当前位置的横坐标  

int y=location[1];//获取当前位置的纵坐标  

③源码

View.getLocationInWindow(int[] location):

/** 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. */  

public void getLocationInWindow(int[] location){  

    if (location == null || location.length < 2) {  

        throw new IllegalArgumentException( "location must be an array of two integers");  

    }    

    if (mAttachInfo == null) {  

        // When the view is not attached to a window, this method does not make sense  

        location[0] = location[1] = 0;  

        return;  

    }    

    float[] position = mAttachInfo.mTmpTransformLocation;  

    position[0] = position[1] = 0.0f;   

    if (!hasIdentityMatrix()) {  

        getMatrix().mapPoints(position);  

    }    

    position[0] += mLeft;  

    position[1] += mTop;  

    ViewParent viewParent = mParent;  

    while (viewParent instanceof View) {  

        final View view = (View) viewParent;    

        position[0] -= view.mScrollX;  

        position[1] -= view.mScrollY;   

        if (!view.hasIdentityMatrix()) {  

            view.getMatrix().mapPoints(position);  

        }   

        position[0] += view.mLeft;  

        position[1] += view.mTop;   

        viewParent = view.mParent;  

     }   

    if (viewParent instanceof ViewRootImpl) {  

        final ViewRootImpl vr = (ViewRootImpl) viewParent;  

        position[1] -= vr.mCurScrollY;  

    }    

    location[0] = (int) (position[0] + 0.5f);  

    location[1] = (int) (position[1] + 0.5f);  

}  

View.getLocationOnScreen(int[] location):

/**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.   */  

public void getLocationOnScreen(int[] location){  

    getLocationInWindow(location);  

    final AttachInfo info = mAttachInfo;  

    if (info != null) {  

        location[0] += info.mWindowLeft;  

        location[1] += info.mWindowTop;  

    }  

}  

  

2.View.getLocalVisibleRect

Android开发中有时候需要对View的可见性进行判断,常见的有:

public int View.getVisibility();

public boolean View.isShown();

但是这些只能简单的判断这个View是否可见,有时候需要更复杂的功能,比如View的可见区域占其自身的百分比等,常见需求为滚动视频列表时当滑出屏幕外一定百分比时暂停播放等。

这时候可以使用View.getLocalVisibleRect(Rect rect)。这个方法会返回View的可视区域的Rect对象。它有如下注意项:

①当View可见时,无论是否完全可见,Rect内的坐标所在坐标系的原点为View自己的坐标原点。

②当View不可见时,Rect内的坐标所在坐标系的原点为View的父控件的坐标原点。

(1)View可见

①部分可见,底部滑入

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5a2f6Iqz6Iqz,size_20,color_FFFFFF,t_70,g_se,x_16

 rect:left=0,top=0,right=990,bottom=150;

因为View可见时是以自己为坐标系计算的,所以left和top都为0,right为自身宽度,bottom为可视区域高度

②部分可见,顶部滑出

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5a2f6Iqz6Iqz,size_20,color_FFFFFF,t_70,g_se,x_16

 rect:left=0,top=150,right=990,bottom=300;

因为View可见时是以自己为坐标系计算的,所以left为0,top为滑出ScrollView的高度150,right为自身宽度,bottom为View自身高度。

③完全可见

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5a2f6Iqz6Iqz,size_19,color_FFFFFF,t_70,g_se,x_16

 rect:left=0,top=0,right=990,bottom=300;

因为View可见时是以自己为坐标系计算的,所以left和top都为0,right为自身宽度,bottom为View自身高度。

(2)不可见

①在底部

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5a2f6Iqz6Iqz,size_20,color_FFFFFF,t_70,g_se,x_16

 rect:left=15,top=2060,right=1005,bottom=2360

因为View不可见时是以父控件为坐标系计算的

ScrollView的高度为1860,加上View与ScrollView的距离200,所以top=2060

left为View与ScrollView的margin,所以left为15

right和bottom分别为加上View的宽度和高度

②在顶部

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5a2f6Iqz6Iqz,size_20,color_FFFFFF,t_70,g_se,x_16

 rect:left=15,top=-500,right=1005,bottom=-200;

通过以上分析,可以判断View是否在可视区域内:

当View不在可视区域内时,

在顶部,Rect.top <0

在底部,Rect.bottom>View.getHeight

所以

public boolean isVisible(Rect rect){

        return !(rect.top<0||rect.bottom>getHeight());

}

还可以判断View可视区域占其自身百分比:

public int getVisibilePercent(Rect rect){

        return rect.height() * 100 / getHeight();

}

猜你喜欢

转载自blog.csdn.net/zenmela2011/article/details/124674381