getGlobalVisibleRect和getLocalVisibleRect


在看android官網的demo的時候遇到這兩個api,開始不是很明白這兩個方法的作用。

通過多次的調試和測試之后慢慢開始有了點眉目,為了防止以后忘記,以此博文為記。

 

作為測試的目的,我寫了這樣一個布局

<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要知道是什么,我用了最笨的辦法,就是用尺子量。

2015-04-09_161933

可見,這81像素就是狀態欄加上ActionBar的高度,所以Bottom120加上81就是201

目前的結論是:getGlobalVisibleRect方法的作用是獲取視圖在屏幕坐標系中的偏移量

 

那么,我的結論真的是正確的嗎,其實我也不知道,繼續測試下去。

把原先的布局文件改成下面這樣的,現在我們重點對LinearLayout進行測試

<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超出屏幕區域

image

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是基於屏幕坐標系的

2015-04-09_1725522

從上圖可以看出,藍色區域的四個點的坐標實際上是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)

最后測試圖:

getRect

 

布局文件代碼:

<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;
            }
        });


    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM