在看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要知道是什么,我用了最笨的辦法,就是用尺子量。
可見,這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超出屏幕區域
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是基於屏幕坐標系的
從上圖可以看出,藍色區域的四個點的坐標實際上是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)
最后測試圖:
布局文件代碼:
<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; } }); } }




