1、 Android坐标系
系统提供了getLocationScreen(intlocation[])这样的方式来获取Android系统的中的位置。另为,在触控事件使用getRawX()、getRawY的方法所获取的坐标同样是Android坐标系中的坐标。
2、 触控事件
MotionEevet中封装的一些常用的常量
public static finalint ACTION_DOWN=0//单点触发按下动作
public static finalint ACTION_UP=1//单点触摸离开动作
public static finalint ACTION_MONVE=2//触摸移动动作
public static finalint ACTION_CANCEL=3//触摸动作取消
public static finalint ACTION_OUTSIDE=4//触摸动作超出边界
public static finalint ACTION_POINTER_DOWN=5//多点触摸按下动作
public static finalint ACTION_POINTER_UP=6//多点离开动作
通常情况下,我们会在onTouchEvent(MotionEventevent)方法中通过event.getAction()方法来获取触摸事件的类型,并使用switch-case方法来进行筛选。
View提供的获取坐标方法
getTop():获取到的是View自身的顶边到其父布局顶边的距离。
getLeft():获取到的View自身的左边其父布局左边的距离。
getRigth():获取到的是View自身的右边到其父布局左边的距离。
getButtom():获取到的是View自身的底边到其父布局顶边的距离。
MotionEvent提供的方法
getX():获取点击事件距离控件左边的距离,即视图坐标。
getY():获取点击事件距离控件到顶边的距离,即视图坐标。
getRawX():获取点击事件距离整个屏幕左边的距离,即绝对距离。
getRawY():获取点击事件距离整个屏幕顶边的距离,及绝对距离。
3、 scrollTo与scrollBy
在一个View中,系统提供了scrollTo、scrollBy两个方式来该百年一个View的位置。scrollTo、scrollBy的方法移动的是View的content,即让View的内容移动,如果在ViewGroup中使用这两个,那么移动的是所有子View,但如果在View中使用,那么移动的将是View的内容,例如,TextView,content就是它的文本;ImageView,content就是它的drawable对象。在View所在的ViewGroup中使用scrollBy方法,移动它的子View;(View)getParent().scrollBy(offset,offsetY);由于屏幕中分为可是区域和不可使区域,当我们使用scrollBy移动的时候,选取的坐标系不同,如果将scrollBy中的参数dx和dy设置为正数,那么content将像坐标轴负方向移动,如果将scrollBy中的参数dx和dy设置为负数,那么content将向坐标的正方向移动,((View)(getParent())).scrollBy(-offset,-offsetY)。
4、 Touch事件分析
事件分发:public BooleandispatchTouchEvent(MotionEvent ev)
Touch事件发生时activity的dispatchTouchEvent(MotionEventev)方法会以隧道(从跟元素依次往下传递直到最内子元素或在中间某一元素中由于某一条件停止传递)将事件传递给最外层的View的dispatchTouchEvent(MotionEvent ev)方法,并由该View的dispatchTouchEvent(MotionEventev)方法进行分发,处理分发逻辑如下:
如果return true,事件会分发给当前View并由dispathcTouchEvent方法进行消费,同事事件会停止下传递。
如果return false,事件分发分为两种情况:
1、 如果当前View获取事件直接来自Activity,则会将返回给Activity的onTouchEvent进行消费。
2、 如果当前View获取的事件来自外层父控件,则会将返回给父View的onTouchEvent方法。
事件拦截:public BooleanonIntercepthTouchEvent(MotionEvent ev)
在外层View的dipatchTouchEvent(MitionEventev)方法返回系统默认的super.dispatchTouchEvent(e)情况下,事件会自动分发给当前View的onInterceptTouchEvent方法。OnInterceptTouchEvent的事件的拦截逻辑如下:
1、 如果onInterceptTouchEvent返回true,则表示将事件进行拦截,并将拦截的事件交由当前View的onTouchEvent进行处理。
2、 如果onInterceptTouchEvent返回false,则表示将事件放行,当前View上的事件会被传递到子View上,再由子View的dispatchTouchEvent来开始处理这个事件的分发。
3、 如果onInterceptTouchEvent返回super.onIntercepthTouchEvent(ev),事件默认会被拦截,并将拦截的事件交由当前View的onTouchEvent进行处理。
事件响应:public bolleanonTouchEvent(MotionEvent ev)
在dispatchTouchEvent返回super.dipatchTouchEvent(ev)并且onInterceptTouchEvent返回true或者super.OnIntercepTouchEvent(ev)的情况下onTouchEvent会被调用。onTouchEvent的事件响应逻辑如下:
1、 如果事件传递到当前View的onTouchEvent方法,而该方法返回了false,那么这个事件会从当前的View向上传递,并且都是有上层的View的onTouchEvent来接收,如果传递到上面的onTouchEvent也返回false,这个事件就会”消失”,而且接收不到下一次的事件。
2、 如果返回了true则会接收并消费该事件。
3、 如果返回super.onTouchEvent(ev)默认处理事件的逻辑和返回的false时相同。
测试
<?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:gravity="center" android:orientation="vertical"> <com.slfinance.app.myapplication.touchview.OutSphereViewGroup android:layout_width="330dp" android:layout_height="330dp" android:background="@android:color/darker_gray" android:gravity="center" android:orientation="vertical"> <com.slfinance.app.myapplication.touchview.InnerViewGroup android:layout_width="220dp" android:layout_height="220dp" android:background="@android:color/holo_blue_light" android:gravity="center" android:orientation="vertical"> <com.slfinance.app.myapplication.touchview.MyView android:layout_width="110dp" android:layout_height="110dp" android:background="@android:color/background_light" android:gravity="center" android:text="this is TextView" android:textSize="12sp" /> </com.slfinance.app.myapplication.touchview.InnerViewGroup> </com.slfinance.app.myapplication.touchview.OutSphereViewGroup> </LinearLayout>
package com.slfinance.app.myapplication.touchview; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.LinearLayout; /** * Created by xionglh on 2016/3/21. */ public class OutSphereViewGroup extends LinearLayout { public OutSphereViewGroup(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.e("OutSphereViewGroup", "super.dispatchTouchEvent(ev)"); return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.e("OutSphereViewGroup","super.onInterceptTouchEvent(ev)" ); return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { Log.e("OutSphereViewGroup", "onTouchEvent-true"); return true; } }
package com.slfinance.app.myapplication.touchview; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.LinearLayout; /** * Created by xionglh on 2016/3/21. */ public class InnerViewGroup extends LinearLayout { public InnerViewGroup(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.e("InnerViewGroup", "super.dispatchTouchEvent(ev)"); return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.e("InnerViewGroup", "super.onInterceptTouchEvent(ev)"); return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { Log.e("InnerViewGroup", "onTouchEvent(MotionEvent event)"); return super.onTouchEvent(event); } }
package com.slfinance.app.myapplication.touchview; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.TextView; /** * Created by xionglh on 2016/3/21. */ public class MyView extends TextView { public MyView(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent event) { Log.e("MyView", "super.dispatchTouchEvent(event)"); return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { Log.e("MyView", "super.onTouchEvent(event)"); return super.onTouchEvent(event); } }