zoukankan      html  css  js  c++  java
  • 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;
                }
            });
    
    
        }
    }
  • 相关阅读:
    学习Spring Cloud中eureka注册中心添加security认证,eureka client注册启动报错
    MySQL 建索引时 Specified key was too long; max key length is 767 bytes 错误的处理
    python3.x运行的坑:AttributeError: 'str' object has no attribute 'decode'
    CENTOS7下安装REDIS
    ubuntu 安装net-tools
    awk命令应用
    shell简单的循环
    Leetcode 713 Subarray Product Less Than K (子数组乘积大于K的个数) (双指针)
    Leetcode 77 Combinations (Backtracking)
    Leetcode 1052 Grumpy Bookstore Owner. (滑动窗口)
  • 原文地址:https://www.cnblogs.com/ai-developers/p/4413585.html
Copyright © 2011-2022 走看看