Android游戲開發(fā):實(shí)現(xiàn)手勢操作切換圖片的實(shí)例
對于Android 的手勢不光在軟件中會經(jīng)常用到,比如瀏覽器中的翻頁,滾動頁面等等;當(dāng)然其實(shí)在我們開發(fā)Android游戲的時候加上了Android手勢操作更會讓游戲增加一個亮點(diǎn),比如一般的CAG、PUZ等類型的游戲選擇關(guān)卡、簡單背景的移動等,都可以使用手勢來操作即可,類似前段時間很火的《憤怒的小鳥》,小鳥這個游戲確實(shí)不錯,我所看到的唯一的亮點(diǎn)是這款游戲的創(chuàng)意!說實(shí)話,現(xiàn)在的游戲沒有做不出來的只有想不出來的好創(chuàng)意。回到話題來,那么下面我們來了解下什么是Android 手勢!
手勢識別概述
所謂手勢操作,類似跳舞機(jī)、EZdancer等這些利用不同動作和音符讓人手舞足蹈一樣,那么Android這里的手勢只是讓我們在游戲和軟件中的操作有了更多的花樣和玩法,根據(jù)玩家接觸屏幕時間的長短,在屏幕上滑動的距離,按下抬起的時間等進(jìn)行了包裝,其實(shí)就是Android 對觸屏處理做了包裝和處理。
那么在Android中其實(shí)有兩種手勢識別技術(shù)。一種是觸摸屏手勢識別,另一種是輸入法手勢識別。兩者比較起來第二種比較靈活,可以自定義手勢,比較high!那么這一節(jié)我們先來介紹第一種手勢識別:觸摸屏手勢識別。在下篇博文中我會給童鞋們講解輸入法手勢識別!
手勢識別實(shí)例
先把兩張截圖放上來吧:


OK,先上代碼:
MySurfaceView.java
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;
/**
*@author 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 )是必須的,因?yàn)?只有這樣,
// 我們當(dāng)前的SurfaceView(view)才能夠處理不同于觸屏形式;
// 例如:ACTION_MOVE,或者多個ACTION_DOWN
this.setOnTouchListener(this);// 將本類綁定觸屏監(jiān)聽器
gd = new GestureDetector(this);
gd.setIsLongpressEnabled(true);
}
public void surfaceCreated(SurfaceHolder holder) {
// 當(dāng)系統(tǒng)調(diào)用了此方法才創(chuàng)建了view所以在這里才能取到view的寬高!!有些童鞋總是把東西都放在初始化函數(shù)里!
// 線程最好放在這里來啟動,因?yàn)榉旁诔跏蓟锏漠?,那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);// 設(shè)置文字大小
paint.setColor(Color.WHITE);
//這里畫出一個矩形方便童鞋們看到手勢操作調(diào)用的函數(shù)都是哪些
canvas.drawRect(50, 30, 175,120, paint);
paint.setColor(Color.RED);// 設(shè)置文字顏色
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手勢監(jiān)聽的時候重寫的函數(shù)---------
/**
* @以下方法中的參數(shù)解釋:
* @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;
}
}
補(bǔ)充一下:代碼初始化手勢的時候有這么一句:gd.setIsLongpressEnabled(true);這個函數(shù)標(biāo)識,如果你設(shè)置true的話就是開啟了長按鍵,當(dāng)你長時間觸屏不動就能得到 onLongPress 手勢,如果設(shè)置false,那么你長時間觸屏不移動也得不到這個手勢的支持。此函數(shù)不設(shè)置也默認(rèn)設(shè)置為true。
備注1:
這里我只是給一些不太熟悉這種定義Vector方式的童鞋簡單介紹一下:我們一般定義容器的時候都是直接 Vector vc =new Vector();,嗯,沒錯,但是這種Vector<String>的定義是種泛型定義,那么簡單的說下區(qū)別,如果Vector vc =new Vector();這種方式裝入Object的以后,取的時候是不是要把取出的進(jìn)行強(qiáng)轉(zhuǎn)一下類型?! 呵呵,而Vector<String>這種定義的時候就表明了這個容器我只裝String類型的元素,so~取出的時候也不用再去強(qiáng)轉(zhuǎn)了。
備注2:
通過測試發(fā)現(xiàn),這里仍然響應(yīng)觸屏事件,即使你把觸屏焦點(diǎn)設(shè)置成setFocusableInTouchMode(false)也會調(diào)用!原因是因?yàn)槲覀儽绢惖膙iew綁定了觸屏事件監(jiān)聽器,那么肯定會先響應(yīng)備注3,然后我們備注4這里沒有 return true 而是直接返給了手勢監(jiān)聽器去監(jiān)聽,讓監(jiān)聽器找合適的函數(shù)來處理用戶的手勢,也就是說沒有標(biāo)志處理完成,所以我們的重寫的onTouchEvent()也會繼續(xù)去處理!
備注5:
這里注釋的代碼我是在測試兩個動作到底是哪兩個,因?yàn)榫W(wǎng)上介紹Android手勢帖子都瘋傳說:
第一個是MotionEvent.ACTION_DOWN,第二個是MotionEvent.ACTION_MOVE。那么第一個動作是按下好理解,是玩家剛觸屏的動作,第二個是move!難道是移動的點(diǎn)都記錄下來了??
其實(shí)測試結(jié)果發(fā)現(xiàn):
第一個是MotionEvent.ACTION_DOWN,第二個是MotionEvent.ACTION_UP!
唉~現(xiàn)在網(wǎng)上的帖子真是各種抄襲~就不能測試下??郁悶! 既然這兩個動作一個是按下一個是抬起那就很明確其意義了,我們可以根據(jù)這兩個動作知道用戶到底滑動的距離等等了,其距離e2.getX()-e1.getX()。
總結(jié)
1、觸屏后、一直觸屏不動、演變順序:onDown->onShowPress->onLongPress;
2、觸屏后、一直觸屏慢移動是onScroll/快移動是onFling 、手指離開屏幕;
注意 :觸屏后、一直觸屏移動,如果手指不離開屏幕一直都是onScroll,不管你移動的速度多快,永遠(yuǎn)不會是onFling!
Ok,手勢雖然挺簡單的,但是如果熟練來使用并且加入游戲中肯定讓你的Game增色不少。
這個實(shí)例我只做了一個手勢的處理,因?yàn)槠渌膭幼鞫己芎唵尉筒欢嗾f了。
補(bǔ)充內(nèi)容:
網(wǎng)上很多關(guān)于手勢文章都說Android 對手勢的支持是從SDK 1.6 (也就是 API 4)才開始的,但是我用SDK1.5模擬器也能識別?。ū鞠霚y試下更低的SDK的支持效果,但是我沒有SDK低于1.5版本的),所以查了Api 發(fā)現(xiàn):
android.view.GestureDetector.OnGestureListener; since api-1 ,
android.view.GestureDetector; since api-1 ,
從API來看從api-1開始就已經(jīng)支持手勢和手勢監(jiān)聽器了,那么很多說api-4才支持這句話也沒錯!因?yàn)椋篴ndroid.gesture 這個類是從 api-4才開始支持的,這個類輸入法手勢識別中會用到。
結(jié)論:觸摸屏手勢識別是從API-1 就開始支持了。 而輸入法手勢識別是API-4才開始支持的!這里要搞清楚!
以上就是對Android 實(shí)現(xiàn)手勢操作切換圖片的資料整理,后續(xù)繼續(xù)補(bǔ)充相關(guān)資料,謝謝大家對本站的支持!
- Android開發(fā)之使用ViewPager實(shí)現(xiàn)圖片左右滑動切換效果
- Android編程單擊圖片實(shí)現(xiàn)切換效果的方法
- Android自定義ImageView實(shí)現(xiàn)點(diǎn)擊兩張圖片切換效果
- Android實(shí)現(xiàn)圖片輪播切換實(shí)例代碼
- Android基于ImageSwitcher實(shí)現(xiàn)圖片切換功能
- Android實(shí)現(xiàn)滑動屏幕切換圖片
- android控件實(shí)現(xiàn)多張圖片漸變切換
- Android使用ViewFlipper實(shí)現(xiàn)圖片切換功能
- Android開發(fā)實(shí)現(xiàn)高仿優(yōu)酷的客戶端圖片左右滑動切換功能實(shí)例【附源碼下載】
- Android開發(fā)實(shí)現(xiàn)的圖片點(diǎn)擊切換功能示例
相關(guān)文章
Android 中為什么要用Fragment.setArguments(Bundle bundle)來傳遞參數(shù)
這篇文章主要介紹了Android 中為什么要用Fragment.setArguments(Bundle bundle)來傳遞參數(shù),非常不錯,具有參考借鑒價值,需要的朋友參考下2017-01-01
淺談Android IPC機(jī)制之Binder的工作機(jī)制
IPC機(jī)制即為跨進(jìn)程通信,是inter-Process Communication的縮寫。是指兩個進(jìn)程之間進(jìn)行通信。在說進(jìn)程通信之前,我們的弄明白什么是線程,什么是進(jìn)程。進(jìn)程和線程是兩個截然不同的概念。本文將介紹Android IPC機(jī)制之Binder的工作機(jī)制。2021-06-06
Android Popupwindow彈出窗口的簡單使用方法
這篇文章主要為大家詳細(xì)介紹了Android Popupwindow彈出窗口的簡單使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07
Android保存多張圖片到本地的實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于Android保存多張圖片到本地的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
android用java和c實(shí)現(xiàn)查找sd卡掛載路徑(sd卡路徑)的方法
這篇文章主要介紹了android用java和c實(shí)現(xiàn)查找sd卡掛載路徑(sd卡路徑)的方法,需要的朋友可以參考下2014-02-02
Android 實(shí)現(xiàn)伸縮布局效果示例代碼
這篇文章主要介紹了Android 實(shí)現(xiàn)伸縮布局效果的示例代碼,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-01-01

