getRawX、getRawY和getX、getY的区别

区别

最近在研究SwipeCard时,需要用到View的手势识别(GestureDetectorCompat),在GestureDetector的静态内部类SimpleOnGestureListener中有个onScroll(MotionEvent e1, MotionEvent e2, float distanceX,float distanceY)。关于具体的参数的含义这里就不一一介绍。主要讲通过e1.getX和e1.getRawX之间的区别。
1. getX()是表示Widget相对于自身左上角的x坐标。
getRawX()是表示相对于屏幕左上角的x坐标值,这个屏幕左上角是手机屏幕左上角,不管activity是否有titleBar或是否全屏幕。
getGlobalVisibleRect , 获取全局坐标系的一个视图区域, 返回一个填充的Rect对象;该Rect是基于总整个屏幕的。
2.在onTouch(View v, MotionEvent event)得到的结果符合1中的描述,但是 在onTouchEvent(MotionEvent event)中无论是getX和getRawX还是getY和getRawY得到的结果都是一样的。都是相对于屏幕的左上角而言。

实例

代码

public class GetRawActivity extends Activity implements View.OnTouchListener{
    private static final String TAG = GetRawActivity.class.getSimpleName();
    private float density;
    private ImageView imageView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_raw_get);
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        density = metrics.density;
        imageView = (ImageView)this.findViewById(R.id.imageView);
        imageView.setOnTouchListener(this);
        Log.i(TAG,"屏幕密度  :"+density+"   parent view  "+imageView.getParent().toString()+" ststusHeight "+getStatusBarHeight(GetRawActivity.this));

    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.i(TAG,"onTouch  move on imageview  X: "+event.getX() +"    Y: "+event.getY()+"   rawX : "+
                event.getRawX()+"  rawY  :"+event.getRawY());
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG,"onTouchEvent  move on imageview  X: "+event.getX() +"    Y: "+event.getY()+"   rawX : "+
                event.getRawX()+"  rawY  :"+event.getRawY());
        return super.onTouchEvent(event);
    }

/**
*获取statusBar的高度
**/
    public static int getStatusBarHeight(Context context){
        Class<?> c = null;
        Object obj = null;
        Field field = null;
        int x = 0, statusBarHeight = 0;
        try {
            c = Class.forName("com.android.internal.R$dimen");
            obj = c.newInstance();
            field = c.getField("status_bar_height");
            x = Integer.parseInt(field.get(obj).toString());
            statusBarHeight = context.getResources().getDimensionPixelSize(x);
            Log.v("@@@@@@", "the status bar height is : " + statusBarHeight);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return statusBarHeight;
    }
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:padding="100.0dp">

    <!--<LinearLayout-->
        <!--android:layout_width="wrap_content"-->
        <!--android:layout_height="wrap_content"-->
        <!--android:gravity="center"-->
        <!--android:background="@android:color/holo_blue_dark"-->
        <!--android:layout_marginLeft="40.0dp"-->
        <!--android:layout_marginRight="20.0dp">-->
        <!-- -->
    <!--</LinearLayout>-->

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:src="@drawable/image1"
        android:scaleType="fitXY"
        />

</LinearLayout>

打印结果

屏幕密度 :2.5
屏幕密度 :2.5 parent view android.widget.LinearLayout{70cff48 V.E….. ……I. 0,0-0,0} ststusHeight 50
onTouch move on imageview X: 294.0 Y: 679.0 rawX : 544.0 rawY :979.0
onTouchEvent move on imageview X: 544.0 Y: 979.0 rawX : 544.0 rawY :979.0

分析

这里需要打印出当前的屏幕密度,这样就可以根据ImageView距离手机屏幕的距离计算出在OnTouch中,我们上面的分析是否合理了。ImageView距离屏幕 上部和左侧都是100dp,我的测试手机的density是2.5。如果getRawX - getX = desity * 100.说明我们的分析是合理的。因为我们通过getX和getRawX得到是像素(px)。所以需要将90dp同样转化为像素单位(px).根据上面的打印数据,可以算出,上面的分析是合理的。在计算Y方向时,要算上状态栏的高度,一般是25dp,在我的测试机上就是50个像素。

打印状态栏高度的代码:

 public static int getStatusBarHeight(Context context){
        Class<?> c = null;
        Object obj = null;
        Field field = null;
        int x = 0, statusBarHeight = 0;
        try {
            c = Class.forName("com.android.internal.R$dimen");
            obj = c.newInstance();
            field = c.getField("status_bar_height");
            x = Integer.parseInt(field.get(obj).toString());
            statusBarHeight = context.getResources().getDimensionPixelSize(x);
            Log.v("@@@@@@", "the status bar height is : " + statusBarHeight);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return statusBarHeight;
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这种情况可以通过在PopupWindow的setOnTouchListener()中监听手势事件,判断手势方向,然后决定是否让RecyclerView或者PopupWindow处理手势事件。 具体实现可以按照以下步骤: 1. 在PopupWindow的构造函数中设置setTouchable(true)和setFocusable(true),使PopupWindow能够响应点击和触摸事件。 2. 在PopupWindow的setOnTouchListener()中监听手势事件,并根据手势方向来判断是否让RecyclerView或者PopupWindow处理手势事件。例如: ``` popupWindow.setOnTouchListener(new View.OnTouchListener() { private float mLastY; @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mLastY = event.getRawY(); break; case MotionEvent.ACTION_MOVE: float dy = event.getRawY() - mLastY; if (Math.abs(dy) > 10) { // 如果手指上下滑动距离大于10,则拦截事件,让RecyclerView处理滑动事件 recyclerView.onTouchEvent(event); return true; } break; } return false; } }); ``` 3. 在RecyclerView的OnTouchListener()中,判断是否在PopupWindow内部,并根据需要决定是否拦截事件。例如: ``` recyclerView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // 判断是否在PopupWindow内部 Rect rect = new Rect(); popupWindow.getContentView().getGlobalVisibleRect(rect); if (!rect.contains((int) event.getRawX(), (int) event.getRawY())) { // 如果不在PopupWindow内部,则让PopupWindow处理手势事件 popupWindow.onTouchEvent(event); return true; } return false; } }); ``` 通过这种方式,可以在PopupWindow中嵌套RecyclerView,并解决它们之间的手势冲突问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值