getDrawingRect,getHitRect,getLocalVisibleRect,getGlobalVisibleRect

本文详细讲解了Android中getHitRect, getDrawingRect, getLocalVisibleRect, getGlobalVisibleRect等方法的作用,并通过实例展示了它们在视图坐标系统中的应用,帮助理解这些方法如何处理视图的可见区域和位置。" 124873350,12787778,单机快速部署多实例MySQL 8,"['mysql', 'database', 'debian', 'installation']

本文主要大体讲下getHitRect()getDrawingRect()getLocalVisibleRect()getGlobalVisibleRect
getLocationOnScreengetLocationWindow方法的作用。

getHitRect()

android sdk文档中给出的解释是:Hit rectangle in parent's coordinates.看字面的意思应该是将矩形映射为父视图中的坐标,看起来还不是非常的清楚,下面就拿一个具体的示例来说明。

代码样式如下

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<LinearLayout
    android:layout_width="450px"
    android:layout_height="450px"
    android:orientation="vertical"
    android:layout_gravity="center_horizontal"
    android:background="@android:color/holo_red_light">

    <TextView
        android:layout_width="200px"
        android:layout_height="200px"
        android:layout_marginTop="100px"
        android:layout_gravity="center_horizontal"
        android:text="测试区域"
        android:gravity="center"
        android:textStyle="bold"
        android:background="@android:color/holo_blue_bright"/>

</LinearLayout>

public class MainActivity extends Activity {

private View testView;

private final static String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    testView = findViewById(R.id.testView);

    testView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            testView.getViewTreeObserver().removeGlobalOnLayoutListener(this);

            Rect rect = new Rect();
            testView.getHitRect(rect);

            Log.i(TAG, "--left:  " + rect.left + "--top: " + rect.top + "--right: " + rect.right + "--bottom: " + rect.bottom);

        }
    });
}

在模拟器显示样式如下:

280020498606702.png


打印的结果:
07-27 16:03:00.017 9540-9540/? I/MainActivity﹕ --left: 125--top: 100--right: 325--bottom: 300

getDrawingRect()


下面测试getDrawingRect()方法,先看布局文件如下:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
    android:layout_width="400px"
    android:layout_height="400px"
    android:layout_gravity="center"
    android:background="@android:color/holo_blue_dark"
    android:orientation="vertical">

    <TextView
        android:id="@+id/test"
        android:layout_width="200px"
        android:layout_height="200px"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="150px"
        android:background="@android:color/holo_red_light"
        android:gravity="center"
        android:text="测试区域" />
</LinearLayout>



测试代码如下

public class MainActivity extends Activity {

private final static String TAG = "MainActivity";

private View testView;

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    testView = findViewById(R.id.test);

    testView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
                 testView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            Rect rect = new Rect();
            testView.getDrawingRect(rect);
            Log.i(TAG, ">>>>>>>>>>>>>>>>rect.left:  " + rect.left + "---rect.top:  " + rect.top + "---rect.right:  " + rect.right + "---rect.bottom:  " + rect.bottom);
        }
    });
}

}



300809105645673.png

运行后结果如下:
I/MainActivity﹕ >>>>>>>>>>>>>>>>rect.left: 0---rect.top: 0---rect.right: 200---rect.bottom: 200

下面看下源码中的实现,源码实现如下:

   public void getDrawingRect(Rect outRect) {
    outRect.left = mScrollX;
    outRect.top = mScrollY;
    outRect.right = mScrollX + (mRight - mLeft);
    outRect.bottom = mScrollY + (mBottom - mTop);
}

从代码实现我们可以看出:

1.getDrawingRect方法,是以view自身作为坐标系的,上例中rect.left与rect.top的值是均为0,因为测试的view均未发生滚动。

2.如果view自身发生了滚动,那么getDrawingRect(Rect outRect)中outRect存储了view滚动后到原始的坐标系的位置。

getLocalVisibleRect()与getGlobalVisibalRect的区别

以下摘自:http://cxyclub.cn/n/76738/
作为测试的目的,我写了这样一个布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/container"
            tools:context=".MainActivity"
            android:paddingLeft="10px">

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:id="@+id/innerL"
    android:paddingLeft="20px">
    <ImageView
        android:id="@+id/expandedImage"
        android:layout_width="wrap_content"
        android:src="@drawable/thumb1"
        android:layout_height="wrap_content"/>
</LinearLayout>

</RelativeLayout>

另外为了方便测试,我将虚拟机设置为1dp=1px,大小等于320x480,因为这两个方法在View对象里面,所以基本上继承自View的对象都可以使用,也是为了方便自己,我使用ImageView作为测试对象,图片大小为160x120px。
下面是我自己的一个测试过程:
因为getLocalVisibleRect只有一个参数,所以我从这个方法入手代码如下:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    final ImageView imageView = (ImageView) findViewById(R.id.expandedImage);

    imageView.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            Rect localRect = new Rect();
            imageView.getLocalVisibleRect(localRect);
            System.out.println("local" + localRect);
        }
    });
}

程序执行后Logcat输出:
localRect(0, 0 ,160, 120)
很明显localRect变量中的right和bottom正是图片的长和宽。
目前的结论是:getLocalVisibleRect(Rect r)方法可以把视图的长和宽映射到一个Rect对象上。

这里我们先放下这个方法,把注意力集中到getGlobalVisibleRect方法中。
将代码改为:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    final ImageView imageView = (ImageView) findViewById(R.id.expandedImage);

    imageView.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            Rect globalRect = new Rect();
            imageView.getGlobalVisibleRect(globalRect);
            System.out.println("global" + globalRect);
        }
    });
}

Logcat输出:
globalRect(30, 81,190, 201)


除了30和190可以猜测出是什么(即left和right),其他的基本上没有什么线索,只知道是top和bottom。30是paddingLeft,即图片向右偏移了30px,因此right很自然就多了30px
top和bottom要知道是什么,我用了最笨的办法,就是用尺子量。
040816093304901.jpg
可见,这81像素就是状态栏加上ActionBar的高度,所以Bottom120加上81就是201
目前的结论是:getGlobalVisibleRect方法的作用是获取视图在屏幕坐标系中的偏移量。

那么,我的结论真的是正确的吗,其实我也不知道,继续测试下去。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/container"
            tools:context=".MainActivity">

<LinearLayout
    android:layout_width="320dp"
    android:layout_height="480dp"
    android:orientation="vertical"
    android:id="@+id/innerL"
    android:background="#550000ff"
    android:layout_marginLeft="-50px"
    android:layout_marginTop="30px">
</LinearLayout>

</RelativeLayout>

布局效果如下:这种布局的目的是让这个View超出屏幕区域

040819307514466.png

java代码如下:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    final LinearLayout ll = (LinearLayout) findViewById(R.id.innerL);

    ll.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            Rect localRect = new Rect();
            ll.getLocalVisibleRect(localRect);
            Rect globalRect = new Rect();

            ll.getGlobalVisibleRect(globalRect);
            System.out.println("global" + globalRect);
            System.out.println("local" + localRect);
        }
    });
}



Logcat数据:
globalRect(0, 111 - 271, 480) localRect(49, 0 - 320, 369)
先来画图分析globalRect中的数据,在前面我们知道globalRect是基于屏幕坐标系的
040822393922969.jpg

从上图可以看出,蓝色区域的四个点的坐标实际上是LinearLayout在屏幕坐标系的可见区域。

结论:
getGlobalVisibleRect方法的作用是获取视图在屏幕坐标中的可视区域
另外需要说的是,getGlobalVisibleRect还可以接受第二个Point类型的参数:
targetView.getGlobalVisibleRect(Rect r, Point gobalOffset)
调用完毕后,globalOffset的值就是targetView原点偏离屏幕坐标原点的距离。

现在来看localRect(49, 0 - 320, 369),初步猜测它是基于视图本身的坐标,只要该视图没有被遮挡,targetView.getLocalVisibleRect()的坐标总是等于:
(0, 0, targetView.getwidth(), targetView.getheight())


从布局不难看出,我们让它向左偏移了50个像素,因此它本身的坐标也跟着向左移动50像素,
至于为什么是49,这个我也不太清楚。因为视图的top和right在该布局中总是可见,所以是0和320,而bottom已经超出了屏幕, 所以480(屏幕的高度)-111(ActionBar+statusBar+marginTop)=369.

结论:
getLocalVisibleRect的作用是获取视图本身可见的坐标区域,坐标以自己的左上角为原点(0,0)

最后测试图:

040831536583570.gif
布局文件代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/container"
            tools:context=".MainActivity">

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:id="@+id/innerL">

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/thumb1"/>
</LinearLayout>


<TextView
    android:id="@+id/local"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"/>

<TextView
    android:id="@+id/global"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@id/local"
    android:layout_below="@id/local"/>

<TextView
    android:id="@+id/offset"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@id/local"
    android:layout_below="@id/global"/>


</RelativeLayout>

程序逻辑:

package com.whathecode.zoomimage;

import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.MotionEvent;
    import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;


public class MainActivity extends ActionBarActivity
{

private int lastX = 0;
private int lastY = 0;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    ImageView imageView = (ImageView) findViewById(R.id.img);
    imageView.setOnTouchListener(new View.OnTouchListener()
    {
        @Override
        public boolean onTouch(View v, MotionEvent event)
        {
            switch (event.getAction())
            {
                case MotionEvent.ACTION_DOWN:
                    lastX = (int) event.getRawX();
                    lastY = (int) event.getRawY();
                    break;
                    
                case MotionEvent.ACTION_MOVE:
                    int dx = (int) event.getRawX() - lastX;
                    int dy = (int) event.getRawY() - lastY;

                    int left = v.getLeft() + dx;
                    int top = v.getTop() + dy;
                    int right = v.getRight() + dx;
                    int bottom = v.getBottom() + dy;

                    v.layout(left, top, right, bottom);
                    lastX = (int) event.getRawX();
                    lastY = (int) event.getRawY();

                    Rect localRect = new Rect();
                    v.getLocalVisibleRect(localRect);
                    ((TextView) findViewById(R.id.local))
                            .setText("local" + localRect.toString());

                    Rect globalRect = new Rect();
                    Point globalOffset = new Point();
                    v.getGlobalVisibleRect(globalRect, globalOffset);
                    ((TextView) findViewById(R.id.global))
                            .setText("global" + globalRect.toString());
                    ((TextView) findViewById(R.id.offset))
                            .setText("globalOffset:" + globalOffset.x + "," + globalOffset.y);
                    break;
                    
                case MotionEvent.ACTION_UP:
                    break;
            }
            return true;
        }
    });


}
}

getLocationOnScreen()

getLocationWindow()

转载于:https://www.cnblogs.com/rookier/p/4681648.html

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值