• View坐标,MotionEvent坐标, 二者的转换,可视区域


    MotionEvent event

    getX(),  getY() 是表示View相对于自身左上角的 x,y 坐标.  不是屏幕可见区域的坐标,而是以view左上角为原点(0,0)的坐标系。

    getRawX(),getRawY() 是表示相对于屏幕左上角的 x 坐标值(注意:这个屏幕左上角是手机屏幕左上角, 不管activity是否有titleBar或是否全屏幕)。

     -------------------------------------------------------------------------------------------------------------------------------------

    //获取View在当前屏幕内的绝对坐标, 相当于view的左上角的点在屏幕坐标系的坐标。计算该视图在全局坐标系中的x,y值,(注意这个值是要从屏幕顶端算起,也就是索包括了通知栏的高度)

    final int[] location = new int[2];   

    view.getLocationOnScreen(location);  

    Event 的 getX、 getY,getRawX、getRawY 可以通过 getLocationOnScreen 来进行转换:

    getX ()     ==     getRawX() - location[0]

    getY ()     ==     getRawY() - location[1]

    //使用例子:

    //ListView的滚动条位置

    lstView.setOnItemClickListener(new OnItemClickListener(){
     public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3){
      int Pos[] = { -1, -1 }; //保存当前坐标的数组
      arg1.getLocationOnScreen(Pos); //获取选中的 Item 在屏幕中的位置,以左上角为原点 (0, 0)
      OldListY = (float) Pos[1]; //我们只取 Y 坐标就行了
      }
    });

    在 setAdapter() 后恢复先前的位置: 

    lstView.setAdapter(adapter); // 重新绑定Adapter   

    lstView.setSelectionFromTop(index, (int) OldListY); // 恢复刚才的位置  

     ------------------------------------------

    Viwe的getLeft , getTop, getBottom, getRight,  这一组是获取View在直接父布局坐标系中的位置。

    以父布局的左上角位置为原点的坐标系,bottom是view的底边在y轴上的位置,同理getTop是获得view的顶部在父坐标系y轴上的位置。

    可能为负数。 可用于判断listView是否滑到最顶部:list.getChildAt(0).getTop() == 0

    --------------------------------------------

    getWidth, getHeight, View的长和宽, 是屏幕上可见的view的大小(布局文件指定)padding的大小是包含在width和height里面的,设置pading不会影响该view的widht和height

    public final int getHeight() {
      return mBottom - mTop;
    }

    --------------------------------------------

    Rect r1 = new Rect();
    view.getLocalVisibleRect(r1);      //以该view的左上角点为坐标原点,该view的可视区域。

    获取view的rect, left 和top为0, right和bottom是view的宽和高,相当于getWidth,getHeight

    --------------------------------------------

    Rect r2 = new Rect();
    view.getGlobalVisibleRect(r2);    // 获取view的各边在屏幕全局坐标系的位置,相当于getLeft等这一组函数,只是坐标系不一样。

    -------------------------------------------

    getScrollX, Return the scrolled left position of this view. This is the left edge of the displayed part of your view,in pixels.

    view实际内容占的大小(画布上画的内容)可能远远超过其显示区域的大小(view布局大小),ScrollX,是当前显示区域的左边界在画布坐标系中的位置。

    getScrollY, 同上。

    scrollBy,scrollTo,移动画布,在画布坐标系上移动x,y轴位置,调整显示区域。

    scrollBy(20)相当于画布向左移动了20px

     

     -----------------------------------------------------------------------------------

    源码中,由用户的点击事件坐标,找到目标view的过程:

    在父view中根据event的坐标,计算处在那个子view的范围 :
    Rect rect
    = new Rect();
    mImg.getHitRect(rect); //得到的是在父坐标中的响应区域,可结合event.getX event.getY 来判断点击在哪个子view的响应范围内 rect.contains(x, y); /** * Hit rectangle in parent's coordinates * * @param outRect The hit rectangle of the view. */ public void getHitRect(Rect outRect) {   outRect.set(mLeft, mTop, mRight, mBottom); }
    public boolean dispatchTouchEvent(MotionEvent ev) {
    
        final float xf = ev.getX();   //view 的屏幕坐标,如果view没有scroll,是和画布坐标重合的
        final float yf = ev.getY();
        final float scrolledXFloat = xf + mScrollX;  //加上滚动的值,转换为view的画布的坐标,这个坐标系是onMeasure和onLayout时用的坐标
        final float scrolledYFloat = yf + mScrollY;  
    
        final Rect frame = mTempRect;
    
        final int scrolledXInt = (int) scrolledXFloat;
        final int scrolledYInt = (int) scrolledYFloat;
        
        final View[] children = mChildren;
        final int count = mChildrenCount; 
        for (int i = count - 1; i >= 0; i--) {   //遍历子view
            final View child = children[i];
            child.getHitRect(frame);     //返回该子view的mLeft, mTop, mRight, mBottom值,这些值是onLayout的时候设上去的
            if (frame.contains(scrolledXInt, scrolledYInt)) { // 事件坐标是否落在该子view区域内
                // offset the event to the view's coordinate system
                final float xc = scrolledXFloat - child.mLeft;  //将事件的坐标由父view坐标系,转为子view的坐标系(都是画布坐标系)
                final float yc = scrolledYFloat - child.mTop;
                ev.setLocation(xc, yc);
                child.dispatchTouchEvent(ev)
            }
        }
    }

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    SilverLight使用WCF RIA SERVICE实现对数据库的操作 (添加,删除,更新)
    c# 创建、读取、添加、修改xml文件
    Winform 下载文件进度条设计
    WOrd ,excel实现打印功能
    码云与Git的使用
    while循环和字符串格式化
    python环境搭建
    python简介与简单入门
    整型与布尔的转换、字符串的切片和几个常用的方法
    python2与python3的区别
  • 原文地址:https://www.cnblogs.com/zijianlu/p/2475645.html
Copyright © 2020-2023  润新知