区别
最近在研究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;
}
}