手势识别兼容Android 1.x和2.x的代码(转载)
我们大家都知道,由于Android2.x开始很多API变动比较大新增了一些比如多点触控的支持,对于屏幕触控手势识别中我们需要考虑更多的实现方法,下面是一段兼容Android1.x和2.x的代码,可以让我们的程序兼容几乎99%的Android手机。
一、首先新建一个抽象类判断SDK版本问题
Java代码:
publicabstractclassVersionedGestureDetector{
privatestaticfinalStringTAG="VersionedGestureDetector";
OnGestureListenermListener;
publicstaticVersionedGestureDetectornewInstance(Contextcontext,
OnGestureListenerlistener){
/*设计实例化构造方法,这里Androideoe提示大家目前有3种API的实现方法,我们需要逐一考虑最优的解决方法,以满足高平台更多的功能实现。*/
finalintsdkVersion=Integer.parseInt(Build.VERSION.SDK);
//使用android.os.Build判断APILevel,但需要将字符串转换为整形
VersionedGestureDetectordetector=null;
if(sdkVersion<Build.VERSION_CODES.ECLAIR){
//如果版本小于2.0则使用1.5版本的API,可以兼容1.5和1.6
detector=newCupcakeDetector();
}elseif(sdkVersion<Build.VERSION_CODES.FROYO){
//如果版本小于2.1则使用2.0版本的API,可以兼容2.0,2.0.1和2.1这三个版本
detector=newEclairDetector();
}else{
//否则使用2.2开始的新的触控API
detector=newFroyoDetector(context);
}
Log.d(TAG,"Creatednew"+detector.getClass());//判断最终选择的到底是哪个版本的类
detector.mListener=listener;
returndetector;
}
publicabstractbooleanonTouchEvent(MotionEventev);
//我们需要根据版本决定onTouchEvent的实现
publicinterfaceOnGestureListener{//手势判断接口主要是实现两个方法
publicvoidonDrag(floatdx,floatdy);//拖拽
publicvoidonScale(floatscaleFactor);//缩放
}
privatestaticclassCupcakeDetectorextendsVersionedGestureDetector{
//针对Android1.5和1.6设计的兼容方式
floatmLastTouchX;
floatmLastTouchY;
floatgetActiveX(MotionEventev){//获得当前X坐标
returnev.getX();
}
floatgetActiveY(MotionEventev){//获得当前Y坐标
returnev.getY();
}
booleanshouldDrag(){//是否是拖拽中或者说移动中
returntrue;
}
@Override
publicbooleanonTouchEvent(MotionEventev){//重写onTouchEvent方法
switch(ev.getAction()){
caseMotionEvent.ACTION_DOWN:{//向下
mLastTouchX=getActiveX(ev);
mLastTouchY=getActiveY(ev);
break;
}
caseMotionEvent.ACTION_MOVE:{
/*Androideoe提醒大家,由于1.x时代的API比较简单,很多手势没有封装,我们只能从ACTION_MOVE中根据坐标变化判断手势样式*/
finalfloatx=getActiveX(ev);
finalfloaty=getActiveY(ev);
if(shouldDrag()){
mListener.onDrag(x-mLastTouchX,y-mLastTouchY);//处理拖拽移动
}
mLastTouchX=x;
mLastTouchY=y;
break;
}
}
returntrue;
}
}
privatestaticclassEclairDetectorextendsCupcakeDetector{
//这个是针对Android2.0,2.0.1和2.1提供的解决方法,可以看到有很多多点触控相关API出现
privatestaticfinalintINVALID_POINTER_ID=-1;
privateintmActivePointerId=INVALID_POINTER_ID;
privateintmActivePointerIndex=0;
@Override
floatgetActiveX(MotionEventev){
returnev.getX(mActivePointerIndex);
}
@Override
floatgetActiveY(MotionEventev){
returnev.getY(mActivePointerIndex);
}
@Override
publicbooleanonTouchEvent(MotionEventev){
finalintaction=ev.getAction();
switch(action&MotionEvent.ACTION_MASK){
caseMotionEvent.ACTION_DOWN:
mActivePointerId=ev.getPointerId(0);
break;
caseMotionEvent.ACTION_CANCEL:
caseMotionEvent.ACTION_UP:
mActivePointerId=INVALID_POINTER_ID;
break;
caseMotionEvent.ACTION_POINTER_UP://有个点松开
finalintpointerIndex=(ev.getAction()&MotionEvent.ACTION_POINTER_INDEX_MASK)
>>MotionEvent.ACTION_POINTER_INDEX_SHIFT;
finalintpointerId=ev.getPointerId(pointerIndex);//获取第几个点
if(pointerId==mActivePointerId){
finalintnewPointerIndex=pointerIndex==0?1:0;
mActivePointerId=ev.getPointerId(newPointerIndex);
mLastTouchX=ev.getX(newPointerIndex);//处理第newPointerIndex个点的x位置
mLastTouchY=ev.getY(newPointerIndex);
}
break;
}
mActivePointerIndex=ev.findPointerIndex(mActivePointerId);
returnsuper.onTouchEvent(ev);
}
}
privatestaticclassFroyoDetectorextendsEclairDetector{
//从Android2.2开始可以很好的处理多点触控的缩放问题
privateScaleGestureDetectormDetector;
publicFroyoDetector(Contextcontext){
mDetector=newScaleGestureDetector(context,
newScaleGestureDetector.SimpleOnScaleGestureListener(){
@OverridepublicbooleanonScale(ScaleGestureDetectordetector){
mListener.onScale(detector.getScaleFactor());//根据ScaleGestureDetector.SimpleOnScaleGestureListener这个系统类处理缩放情况通过onScale方法
returntrue;
}
});
}
@Override
booleanshouldDrag(){
return!mDetector.isInProgress();
}
@Override
publicbooleanonTouchEvent(MotionEventev){
mDetector.onTouchEvent(ev);
returnsuper.onTouchEvent(ev);
}
}
}
复制代码
有关调用方法,我们可以自定义一个View,取名为TouchExampleView类,这里来处理触控相关的问题
Java代码:
publicclassTouchExampleViewextendsView{
privateDrawablemIcon;//我们以一个图片为参照物,根据手势控制
privatefloatmPosX;
privatefloatmPosY;
privateVersionedGestureDetectormDetector;
privatefloatmScaleFactor=1.f;//原始缩放比例为1.0
publicTouchExampleView(Contextcontext){
this(context,null,0);
}
publicTouchExampleView(Contextcontext,AttributeSetattrs){
this(context,attrs,0);
}
publicTouchExampleView(Contextcontext,AttributeSetattrs,intdefStyle){//实现我们自定义View的构造
super(context,attrs,defStyle);
mIcon=context.getResources().getDrawable(R.drawable.icon);
mIcon.setBounds(0,0,mIcon.getIntrinsicWidth(),mIcon.getIntrinsicHeight());
mDetector=VersionedGestureDetector.newInstance(context,newGestureCallback());
//实例化刚才的版本自适应手势控制类
}
@Override
publicbooleanonTouchEvent(MotionEventev){
//重写onTouchEvent方法,使用VersionedGestureDetector类得出的数据。
mDetector.onTouchEvent(ev);
returntrue;
}
@Override
publicvoidonDraw(Canvascanvas){//处理自定义View绘制方法
super.onDraw(canvas);
canvas.save();
canvas.translate(mPosX,mPosY);//进行平移操作,根据mPosX和mPosY坐标
canvas.scale(mScaleFactor,mScaleFactor);//进行缩放操作,参数就是刚才定义的float类型的缩放比例
mIcon.draw(canvas);//直接绘制图片变化到画布中
canvas.restore();
}
privateclassGestureCallbackimplementsVersionedGestureDetector.OnGestureListener{
publicvoidonDrag(floatdx,floatdy){
//这里Android123提示大家在2.2中这个回调方法将可以支持拖拽的坐标处理
mPosX+=dx;
mPosY+=dy;
invalidate();
}
publicvoidonScale(floatscaleFactor){
mScaleFactor*=scaleFactor;//缩放控制
mScaleFactor=Math.max(0.1f,Math.min(mScaleFactor,5.0f));
//限制最小缩放比例为1.0最大为5.0倍数
invalidate();
}
}
}
复制代码
有关调用我们的自定义的TouchExampleView可以在Activity的onCreate方法中加入以下代码
Java代码:
TouchExampleViewview=newTouchExampleView(this);
view.setLayoutParams(newViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
setContentView(view);//替换掉原始的res.layout.main
复制代码
最后Androideoe需要给大家说明的是使用本例子,直接使用Android2.2的SDK创建工程,即APILevel为8,发布时在androidmanifest.xml中加入uses-sdkandroid:minSdkVersion="3"android:targetSdkVersion="8"这句可以兼容从Android1.5到2.2的版本,有关2.3中新增的一个可以处理5个或5个以上的多点触控增强类Android开发网将在以后的时间中介绍。
转载出自:http://www.apkbus.com/forum.php?mod=viewthread&tid=848