編輯:Android開發實例
本文補充:網上很多關於手勢文章都說Android 對手勢的支持是從SDK 1.6 (也就是 API 4)才開始的,但是我用SDK1.5模擬器也能識別!。(本想測試下更低的SDK的支持效果,但是我沒有SDK低於1.5版本的....我手機SDK 2.2的 - -、),所以查了Api 發現:
android.view.GestureDetector.OnGestureListener; since api-1 ,
android.view.GestureDetector; since api-1 ,
從API來看從api-1開始就已經支持手勢和手勢監聽器了,那麼很多說api-4才支持這句話也沒錯!因為:android.gesture 這個類是從 api-4才開始支持的,這個類輸入法手勢識別中會用到!so~
結論:觸摸屏手勢識別是從API-1 就開始支持了。 而輸入法手勢識別是API-4才開始支持的!這裡要搞清楚!
對於Android 的手勢不光在軟件中會經常用到,比如浏覽器中的翻頁,滾動頁面等等;當然其實在我們開發Android游戲的時候加上了Android手勢操作更會讓游戲增加一個亮點,比如一般的CAG ,PUZ等類型的游戲選擇關卡啦、簡單背景的移動啦,都可以使用手勢來操作即可,類似前段時間很火的《讓人憤怒的小鳥!》咳咳、不好意思說錯了,是《憤怒的小鳥》,因為總是聽群裡啊,朋友啊說小鳥出新版本啦,小鳥出PC硬盤版啦! 唉~你說可讓人憤怒,其實說實話,小鳥這個游戲確實不錯,我所看到的唯一的亮點是這款游戲的創意!說實話,現在的游戲沒有做不出來的只有想不出來的好創意、咳咳。回到話題來,那麼下面我們來稍微了解下什麼是Android 手勢!
所謂手勢操作,類似跳舞機、EZdancer~這些利用不同動作和音符讓人手舞足蹈一樣,那麼Android這裡的手勢只是讓我們在游戲和軟件中的操作有了更多的花樣和玩法,根據玩家接觸屏幕時間的長短,在屏幕上滑動的距離,按下抬起的時間等進行了包裝,其實就是Android 對觸屏處理做了包裝和處理。
那麼在Android中其實有兩種手勢識別技術。一種是觸摸屏手勢識別,另一種是輸入法手勢識別;兩者比較起來第二種比較靈活,可以自定義手勢,比較high!那麼這一節我們先來介紹第一種手勢識別:觸摸屏手勢識別;在下篇博文中我會給童鞋們講解輸入法手勢識別!
先把兩張截圖放上來吧:
OK,老方式,先上代碼:
MySurfaceView.java
- package com.himi;
- import java.util.Vector;
- import android.content.Context;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.util.Log;
- import android.view.GestureDetector;
- import android.view.MotionEvent;
- import android.view.SurfaceHolder;
- import android.view.SurfaceView;
- import android.view.View;
- import android.view.GestureDetector.OnGestureListener;
- import android.view.SurfaceHolder.Callback;
- import android.view.View.OnTouchListener;
- /**
- [email protected] Himi
- *@ Gesture (上文)觸摸屏手勢識別
- */
- public class MySurfaceViewAnimation extends SurfaceView implements Callback,
- Runnable, OnGestureListener, OnTouchListener {
- private Thread th = new Thread(this);
- private SurfaceHolder sfh;
- private Canvas canvas;
- private Paint paint;
- private Bitmap bmp;
- private GestureDetector gd;
- private int bmp_x, bmp_y;
- private boolean isChagePage;
- private Vector<String> v_str;// 備注1
- public MySurfaceViewAnimation(Context context) {
- super(context);
- v_str = new Vector<String>();
- this.setKeepScreenOn(true);
- bmp = BitmapFactory.decodeResource(getResources(),
- R.drawable.himi_dream);
- sfh = this.getHolder();
- sfh.addCallback(this);
- paint = new Paint();
- paint.setAntiAlias(true);
- this.setLongClickable(true);
- // setLongClickable( true )是必須的,因為 只有這樣,
- // 我們當前的SurfaceView(view)才能夠處理不同於觸屏形式;
- // 例如:ACTION_MOVE,或者多個ACTION_DOWN
- this.setOnTouchListener(this);// 將本類綁定觸屏監聽器
- gd = new GestureDetector(this);
- gd.setIsLongpressEnabled(true);
- }
- public void surfaceCreated(SurfaceHolder holder) {
- // 當系統調用了此方法才創建了view所以在這裡才能取到view的寬高!!有些童鞋總是把東西都放在初始化函數裡!
- // 線程最好放在這裡來啟動,因為放在初始化裡的畫,那view還沒有呢,到了提交畫布unlockCanvasAndPost的時候就異常啦!
- bmp_x = (getWidth() - bmp.getWidth()) >> 2;
- bmp_y = (getHeight() - bmp.getHeight()) >> 2;
- th.start();
- }
- public void draw() {
- try {
- canvas = sfh.lockCanvas();
- if (canvas != null) {
- canvas.drawColor(Color.WHITE);// 畫布刷屏
- canvas.drawBitmap(bmp, bmp_x, bmp_y, paint);
- paint.setTextSize(20);// 設置文字大小
- paint.setColor(Color.WHITE);
- //這裡畫出一個矩形方便童鞋們看到手勢操作調用的函數都是哪些
- canvas.drawRect(50, 30, 175,120, paint);
- paint.setColor(Color.RED);// 設置文字顏色
- if (v_str != null) {
- for (int i = 0; i < v_str.size(); i++) {
- canvas.drawText(v_str.elementAt(i), 50, 50 + i * 30,
- paint);
- }
- }
- }
- } catch (Exception e) {
- Log.v("Himi", "draw is Error!");
- } finally {
- sfh.unlockCanvasAndPost(canvas);
- }
- }
- @Override
- public void run() {
- // TODO Auto-generated method stub
- while (true) {
- draw();
- try {
- Thread.sleep(100);
- } catch (Exception ex) {
- }
- }
- }
- public void surfaceChanged(SurfaceHolder holder, int format, int width,
- int height) {
- }
- public void surfaceDestroyed(SurfaceHolder holder) {
- }
- // @Override
- // public boolean onTouchEvent(MotionEvent event) {// 備注2
- // return true;
- // }
- @Override
- public boolean onTouch(View v, MotionEvent event) {// 備注3
- if (v_str != null)
- v_str.removeAllElements();
- return gd.onTouchEvent(event);// 備注4
- }
- // --------------以下是使用OnGestureListener手勢監聽的時候重寫的函數---------
- /**
- * @以下方法中的參數解釋:
- * @e1:第1個是 ACTION_DOWN MotionEvent 按下的動作
- * @e2:後一個是ACTION_UP MotionEvent 抬起的動作(這裡要看下備注5的解釋)
- * @velocityX:X軸上的移動速度,像素/秒
- * @velocityY:Y軸上的移動速度,像素/秒
- */
- @Override
- public boolean onDown(MotionEvent e) {
- // ACTION_DOWN
- v_str.add("onDown");
- return false;
- }
- @Override
- // ACTION_DOWN 、短按不移動
- public void onShowPress(MotionEvent e) {
- v_str.add("onShowPress");
- }
- @Override
- // ACTION_DOWN 、長按不滑動
- public void onLongPress(MotionEvent e) {
- v_str.add("onLongPress");
- }
- @Override
- // ACTION_DOWN 、慢滑動
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
- float distanceY) {
- v_str.add("onScroll");
- return false;
- }
- @Override
- // ACTION_DOWN 、快滑動、 ACTION_UP
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
- float velocityY) {
- v_str.add("onFling");
- //-------備注5----------
- // if(e1.getAction()==MotionEvent.ACTION_MOVE){
- // v_str.add("onFling");
- // }else if(e1.getAction()==MotionEvent.ACTION_DOWN){
- // v_str.add("onFling");
- // }else if(e1.getAction()==MotionEvent.ACTION_UP){
- // v_str.add("onFling");
- // }
- // if(e2.getAction()==MotionEvent.ACTION_MOVE){
- // v_str.add("onFling");
- // }else if(e2.getAction()==MotionEvent.ACTION_DOWN){
- // v_str.add("onFling");
- // }else if(e2.getAction()==MotionEvent.ACTION_UP){
- // v_str.add("onFling");
- // }
- if (isChagePage)
- bmp = BitmapFactory.decodeResource(getResources(),
- R.drawable.himi_dream);
- else
- bmp = BitmapFactory.decodeResource(getResources(),
- R.drawable.himi_warm);
- isChagePage = !isChagePage;
- return false;
- }
- @Override
- // 短按ACTION_DOWN、ACTION_UP
- public boolean onSingleTapUp(MotionEvent e) {
- v_str.add("onSingleTapUp");
- return false;
- }
- }
補充一下:代碼初始化手勢的時候有這麼一句:gd.setIsLongpressEnabled(true);這個函數標識,如果你設置true的話就是開啟了長按鍵,當你長時間觸屏不動就能得到 onLongPress 手勢,如果設置false 那麼你長時間觸屏不移動也得不到這個手勢的支持~此函數不設置也默認設置為true
備注1:
這裡我只是給一些不太熟悉這種定義Vector方式的童鞋簡單介紹一下:我們一般定義容器的時候都是直接 Vector vc =new Vector();嗯,沒錯,但是這種Vector<String>的定義是種泛型定義,那麼簡單的說下區別,如果Vector vc =new Vector();這種方式裝入Object的以後,取的時候是不是要把取出的進行強轉一下類型?! 呵呵,而Vector<String>這種定義的時候就表明了這個容器我只裝String類型的元素,so~取出的時候也不用再去強轉了。
備注2 :通過測試發現,這裡仍然響應觸屏時間,即使你把觸屏焦點設置成setFocusableInTouchMode(false)也會調用!!!原因是因為我們本類的view綁定了觸屏事件監聽器,那麼肯定會先響應備注3,然後我們備注4這裡沒有 return true而是直接返給了手勢監聽器去監聽,讓監聽器找合適的函數來處理用戶的手勢,也就是說沒有標志處理完成,所以我們的重寫的onTouchEvent()也會繼續去處理!
備注5:
這裡注釋的代碼我是在測試兩個動作到底是哪兩個,因為網上介紹Android手勢帖子都瘋傳說:
第一個是MotionEvent.ACTION_DOWN 第二個是MotionEvent.ACTION_MOVE!那麼第一個動作是按下好理解是玩家剛觸屏的動作,第二個是move!難道是移動的點都記錄下來了??
其實測試結果發現:
第一個是MotionEvent.ACTION_DOWN 第二個是MotionEvent.ACTION_UP!
唉~現在網上的帖子真是各種抄襲~就不能測試下??郁悶! 既然這兩個動作一個是按下一個是抬起那就很明確其意義了,我們可以根據
這兩個動作知道用戶到底滑動的距離等等了,其距離e2.getX()-e1.getX();
總結:
1.觸屏後、一直觸屏不動、演變順序:onDown->onShowPress->onLongPress;
2.觸屏後、一直觸屏慢移動是onScroll/快移動是onFling 、手指離開屏幕;
注意 :觸屏後、一直觸屏移動,如果手指不離開屏幕一直都是onScroll,不管你移動的速度多快,永遠不會是onFling!
Ok,手勢雖然挺簡單的,但是如果熟練來使用並且加入游戲中肯定讓你的Game增色不少~
我這裡給出源碼:這個實例我只做了一個手勢的處理,因為其他的動作都很簡單不多說了~OK 各位晚安~
源碼下載地址:http://download.csdn.net/source/2977447
1.底層網絡接口采用apache的httpclient連接池框架; 2.圖片緩存采用基於LRU的算法; 3.網絡接口采用監聽者模式; 4.包含圖片的OOM處理(及
可以顯示在的Android任務,通過加載進度條的進展。進度條有兩種形狀。加載欄和加載微調(spinner)。在本章中,我們將討論微調(spinner)。Spinner 用
這篇文章主要介紹了Android字段驗證的實例代碼的相關資料,代碼簡單易懂,具有參考借鑒價值,需要的朋友可以參考下 先給大家展示效果圖:
先明確幾個概念的區別: padding margin都是邊距的含義,關鍵問題得明白是什麼相對什麼的邊距. padding是控件的內容相對控件的邊緣的邊距. mar