手势识别兼容Android 1.x和2.x的代码【转】
生活随笔
收集整理的這篇文章主要介紹了
手势识别兼容Android 1.x和2.x的代码【转】
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
摘要: 由于Android 2.x開始很多API變動(dòng)比較大新增了一些比如多點(diǎn)觸控的支持,對于屏幕觸控手勢識別中我們需要考慮更多的實(shí)現(xiàn)方法,下面是一段兼容Android 1.x和2.x的代碼,可以讓我們的程序兼容幾乎99%的Android手機(jī)。 一 ...
| ?由于Android 2.x開始很多API變動(dòng)比較大新增了一些比如多點(diǎn)觸控的支持,對于屏幕觸控手勢識別中我們需要考慮更多的實(shí)現(xiàn)方法,下面是一段兼容Android 1.x和2.x的代碼,可以讓我們的程序兼容幾乎99%的Android手機(jī)。 ? 一、首先新建一個(gè)抽象類判斷SDK版本問題 ?public abstract class VersionedGestureDetector { ??? private static final String TAG = "VersionedGestureDetector"; ??? OnGestureListener mListener; ??? public static VersionedGestureDetector newInstance(Context context, ??????????? OnGestureListener listener) {? //設(shè)計(jì)實(shí)例化構(gòu)造方法,這里Android123提示大家目前有3種API的實(shí)現(xiàn)方法,我們需要逐一考慮最優(yōu)的解決方法,以滿足高平臺更多的功能實(shí)現(xiàn)。 ??????? final int sdkVersion = Integer.parseInt(Build.VERSION.SDK); //使用android.os.Build判斷API Level,但需要將字符串轉(zhuǎn)換為整形 ??????? VersionedGestureDetector detector = null; ??????? if (sdkVersion < Build.VERSION_CODES.ECLAIR) { //如果版本小于2.0則使用1.5版本的API,可以兼容1.5和1.6 ??????????? detector = new CupcakeDetector(); ??????? } else if (sdkVersion < Build.VERSION_CODES.FROYO) { //如果版本小于2.1則使用2.0版本的API,可以兼容2.0,2.0.1和2.1這三個(gè)版本 ??????????? detector = new EclairDetector(); ??????? } else {? //否則使用2.2開始的新的觸控API ??????????? detector = new FroyoDetector(context); ??????? } ??????? Log.d(TAG, "Created new " + detector.getClass()); //判斷最終選擇的到底是哪個(gè)版本的類 ??????? detector.mListener = listener; ??????? return detector; ??? } ??? public abstract boolean onTouchEvent(MotionEvent ev); //我們需要根據(jù)版本決定onTouchEvent的實(shí)現(xiàn) ??? public interface OnGestureListener { //手勢判斷接口主要是實(shí)現(xiàn)兩個(gè)方法 ??????? public void onDrag(float dx, float dy);? //拖拽 ??????? public void onScale(float scaleFactor); //縮放 ??? } ??? private static class CupcakeDetector extends VersionedGestureDetector { //針對Android 1.5和1.6設(shè)計(jì)的兼容方式 ??????? float mLastTouchX; ??????? float mLastTouchY; ??????? float getActiveX(MotionEvent ev) { //獲得當(dāng)前X坐標(biāo) ??????????? return ev.getX(); ??????? } ??????? float getActiveY(MotionEvent ev) { //獲得當(dāng)前Y坐標(biāo) ??????????? return ev.getY(); ??????? } ??????? boolean shouldDrag() { //是否是拖拽中或者說移動(dòng)中 ??????????? return true; ??????? } ??????? @Override ??????? public boolean onTouchEvent(MotionEvent ev) { //重寫onTouchEvent方法 ??????????? switch (ev.getAction()) { ??????????? case MotionEvent.ACTION_DOWN: {? //向下 ??????????????? mLastTouchX = getActiveX(ev); ??????????????? mLastTouchY = getActiveY(ev); ??????????????? break; ??????????? } ??????????? case MotionEvent.ACTION_MOVE: { //Android開發(fā)網(wǎng)提醒大家,由于1.x時(shí)代的API比較簡單,很多手勢沒有封裝,我們只能從ACTION_MOVE中根據(jù)坐標(biāo)變化判斷手勢樣式 ??????????????? final float x = getActiveX(ev); ??????????????? final float y = getActiveY(ev); ??????????????? if (shouldDrag()) { ??????????????????? mListener.onDrag(x - mLastTouchX, y - mLastTouchY); //處理拖拽移動(dòng) ??????????????? } ??????????????? mLastTouchX = x; ??????????????? mLastTouchY = y; ??????????????? break; ??????????? } ??????????? } ??????????? return true; ??????? } ??? } ??? private static class EclairDetector extends CupcakeDetector { //這個(gè)是針對Android 2.0,2.0.1和2.1提供的解決方法,可以看到有很多多點(diǎn)觸控相關(guān)API出現(xiàn) ??????? private static final int INVALID_POINTER_ID = -1; ??????? private int mActivePointerId = INVALID_POINTER_ID; ??????? private int mActivePointerIndex = 0; ??????? @Override ??????? float getActiveX(MotionEvent ev) { ??????????? return ev.getX(mActivePointerIndex); ??????? } ??????? @Override ??????? float getActiveY(MotionEvent ev) { ??????????? return ev.getY(mActivePointerIndex); ??????? } ??????? @Override ??????? public boolean onTouchEvent(MotionEvent ev) { ??????????? final int action = ev.getAction(); ??????????? switch (action & MotionEvent.ACTION_MASK) { ??????????? case MotionEvent.ACTION_DOWN: ??????????????? mActivePointerId = ev.getPointerId(0); ??????????????? break; ??????????? case MotionEvent.ACTION_CANCEL: ??????????? case MotionEvent.ACTION_UP: ??????????????? mActivePointerId = INVALID_POINTER_ID; ??????????????? break; ??????????? case MotionEvent.ACTION_POINTER_UP: //有個(gè)點(diǎn)松開 ??????????????? final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) ??????????????????????? >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; ??????????????? final int pointerId = ev.getPointerId(pointerIndex); //獲取第幾個(gè)點(diǎn) ??????????????? if (pointerId == mActivePointerId) { ??????????????????? final int newPointerIndex = pointerIndex == 0 ? 1 : 0; ??????????????????? mActivePointerId = ev.getPointerId(newPointerIndex); ??????????????????? mLastTouchX = ev.getX(newPointerIndex); //處理第newPointerIndex個(gè)點(diǎn)的x位置 ??????????????????? mLastTouchY = ev.getY(newPointerIndex); ??????????????? } ??????????????? break; ??????????? } ??????????? mActivePointerIndex = ev.findPointerIndex(mActivePointerId); ??????????? return super.onTouchEvent(ev); ??????? } ??? } ??? private static class FroyoDetector extends EclairDetector { //從Android 2.2開始可以很好的處理多點(diǎn)觸控的縮放問題 ??????? private ScaleGestureDetector mDetector; ??????? public FroyoDetector(Context context) { ??????????? mDetector = new ScaleGestureDetector(context, ??????????????????? new ScaleGestureDetector.SimpleOnScaleGestureListener() { ??????????????? @Override public boolean onScale(ScaleGestureDetector detector) { ??????????????????? mListener.onScale(detector.getScaleFactor()); //根據(jù) ScaleGestureDetector.SimpleOnScaleGestureListener這個(gè)系統(tǒng)類處理縮放情況通過onScale方法 ??????????????????? return true; ??????????????? } ??????????? }); ??????? } ??????? @Override ??????? boolean shouldDrag() { ??????????? return !mDetector.isInProgress(); ??????? } ??????? @Override ??????? public boolean onTouchEvent(MotionEvent ev) { ??????????? mDetector.onTouchEvent(ev); ??????????? return super.onTouchEvent(ev); ??????? } ??? } } ?有關(guān)調(diào)用方法,我們可以自定義一個(gè)View,取名為TouchExampleView類,這里來處理觸控相關(guān)的問題 public class TouchExampleView extends View { ??? private Drawable mIcon; //我們以一個(gè)圖片為參照物,根據(jù)手勢控制 ??? private float mPosX; ??? private float mPosY; ??? private VersionedGestureDetector mDetector; ??? private float mScaleFactor = 1.f; //原始縮放比例為1.0 ??? public TouchExampleView(Context context) { ??????? this(context, null, 0); ??? } ??? public TouchExampleView(Context context, AttributeSet attrs) { ??????? this(context, attrs, 0); ??? } ??? public TouchExampleView(Context context, AttributeSet attrs, int defStyle) { //實(shí)現(xiàn)我們自定義View的構(gòu)造 ??????? super(context, attrs, defStyle); ??????? mIcon = context.getResources().getDrawable(R.drawable.icon); ??????? mIcon.setBounds(0, 0, mIcon.getIntrinsicWidth(), mIcon.getIntrinsicHeight()); ??????? mDetector = VersionedGestureDetector.newInstance(context, new GestureCallback()); //實(shí)例化剛才的版本自適應(yīng)手勢控制類 ??? } ??? @Override ??? public boolean onTouchEvent(MotionEvent ev) { //重寫onTouchEvent方法,使用VersionedGestureDetector類得出的數(shù)據(jù)。 ??????? mDetector.onTouchEvent(ev); ??????? return true; ??? } ??? @Override ??? public void onDraw(Canvas canvas) { //處理自定義View繪制方法 ??????? super.onDraw(canvas); ??????? canvas.save(); ??????? canvas.translate(mPosX, mPosY); //進(jìn)行平移操作,根據(jù)mPosX和mPosY坐標(biāo) ??????? canvas.scale(mScaleFactor, mScaleFactor); //進(jìn)行縮放操作,參數(shù)就是剛才定義的float類型的縮放比例 ??????? mIcon.draw(canvas); //直接繪制圖片變化到畫布中 ??????? canvas.restore(); ??? } ??? private class GestureCallback implements VersionedGestureDetector.OnGestureListener { ??????? public void onDrag(float dx, float dy) { //這里Android123提示大家在2.2中這個(gè)回調(diào)方法將可以支持拖拽的坐標(biāo)處理 ??????????? mPosX += dx; ??????????? mPosY += dy; ??????????? invalidate(); ??????? } ??????? public void onScale(float scaleFactor) { ??????????? mScaleFactor *= scaleFactor; //縮放控制 ??????????? mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f)); //限制最小縮放比例為1.0最大為5.0倍數(shù) ??????????? invalidate(); ??????? } ??? } } ?有關(guān)調(diào)用我們的自定義的TouchExampleView可以在Activity的onCreate方法中加入以下代碼, ???? TouchExampleView view = new TouchExampleView(this); ???? view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ????? ViewGroup.LayoutParams.MATCH_PARENT)); ???? setContentView(view);? //替換掉原始的res.layout.main 最后Android123需要給大家說明的是使用本例子,直接使用Android 2.2的SDK創(chuàng)建工程,即API Level為8,發(fā)布時(shí)在androidmanifest.xml中加入uses-sdk android:minSdkVersion="3" android:targetSdkVersion="8"這句可以兼容從Android 1.5到2.2的版本,有關(guān)2.3中新增的一個(gè)可以處理5個(gè)或5個(gè)以上的多點(diǎn)觸控增強(qiáng)類Android開發(fā)網(wǎng)將在以后的時(shí)間中介紹。 |
轉(zhuǎn)載于:https://www.cnblogs.com/stay/articles/1928943.html
與50位技術(shù)專家面對面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的手势识别兼容Android 1.x和2.x的代码【转】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WCF 第八章 安全 基于证书的加密
- 下一篇: Virtools 3D行为编程系列(一)