亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

【Android每周專題】觸摸屏手勢

系統 1838 0

本系列文章均為A2BGeek原創,轉載務必在明顯處注明:
轉載自A2BGeek的【Android每周專題】系列,原文鏈接: http://blog.csdn.net/benbmw2008/article/details/11367631

這篇專題來研究一下Android的觸摸屏手勢Gesture,Android的手勢有兩種,一種是View和Activity的(基于觸摸屏事件,所以Activity也能添加手勢),一種是手寫輸入法或者一些手機瀏覽器的快捷手勢那樣的帶筆跡的手勢識別。這一點從API文檔中就能體現出來:分別有android.view.GestureDetector和android.gesture.Gesture。

【Android每周專題】觸摸屏手勢

我們先來介紹View和Activity的手勢,再介紹輸入法手勢識別。

View和Activity的手勢

這一部分想必大家都已經非常熟悉了,現在很多APP都會加入手勢來提高交互體驗,其中在某個界面向右Fling關閉該界面這一操作貌似成了APP的標配了。廢話不多說了,直接進入正題。
為View和Activity加入手勢操作的步驟如下:
1、為View或者Activity實現OnGestureListener接口。
2、覆寫View或者Activity的OnTouchEvent方法,這里要返回GestureDetector.onTouchEvent()。
3、覆寫你需要的手勢的回調方法。
這里解釋一下各種回調方法的含義:
按下(onDown): 剛剛手指接觸到觸摸屏的那一剎那,就是觸的那一下。
拋擲(onFling): 手指在觸摸屏上迅速移動,并松開的動作。
長按(onLongPress): 手指按在持續一段時間,并且沒有松開。
滾動(onScroll): 手指在觸摸屏上滑動。
按住(onShowPress): 手指按在觸摸屏上,它的時間范圍在按下起效,在長按之前。
抬起(onSingleTapUp):手指離開觸摸屏的那一剎那。
除了這些定義之外,鄙人也總結了一點算是經驗的經驗吧,在這里和大家分享一下。
任何手勢動作都會先執行一次按下(onDown)動作。
長按(onLongPress)動作前一定會執行一次按住(onShowPress)動作。
按住(onShowPress)動作和按下(onDown)動作之后都會執行一次抬起(onSingleTapUp)動作。
長按(onLongPress)、滾動(onScroll)和拋擲(onFling)動作之后都不會執行抬起(onSingleTapUp)動作。
我這里貼上一段代碼,大家可以看一下實現的步驟,實驗代碼和觸摸屏事件專題的代碼差不多,我就不重復上傳了。
      package com.example.gesturedemo;

import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.widget.TextView;

public class MyTextView extends TextView implements OnGestureListener {

	private GestureDetector mGestureDetector;

	public MyTextView(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		mGestureDetector = new GestureDetector(context, this);
	}

	public MyTextView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		mGestureDetector = new GestureDetector(context, this);
	}

	public MyTextView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
		mGestureDetector = new GestureDetector(context, this);
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		DebugTool.log("MyTextView--->dispatchTouchEvent");
		return super.dispatchTouchEvent(event);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		DebugTool.log("MyTextView--->onTouchEvent");
		// int action = event.getAction();
		// switch (action) {
		// case MotionEvent.ACTION_DOWN:
		// DebugTool.log("MyTextView--->onTouchEvent--->DOWN");
		// break;
		// case MotionEvent.ACTION_MOVE:
		// DebugTool.log("MyTextView--->onTouchEvent--->MOVE");
		// break;
		// case MotionEvent.ACTION_UP:
		// DebugTool.log("MyTextView--->onTouchEvent--->UP");
		// break;
		// }
		return mGestureDetector.onTouchEvent(event);
	}

	@Override
	public boolean onDown(MotionEvent e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		// TODO Auto-generated method stub
		DebugTool.log("MyTextView--->onFling");
		return false;
	}

	@Override
	public void onLongPress(MotionEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void onShowPress(MotionEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		// TODO Auto-generated method stub
		return false;
	}

}

    

在OnGestureListener的帶返回值的幾個回調方法默認返回false的情況下,你會發現Fling手勢是識別不到的,這是什么原因呢?這需要用上一專題的知識來解釋 http://blog.csdn.net/benbmw2008/article/details/11143893 大家應該能看出來手勢是基于觸摸屏事件傳遞的,對照著上一篇的“默認事件流向”圖,讀者可以想象其實就是在“MyTextView onTouchEvent”和“MyRelativeLayout onTouchEvent”之間加一個"MyTextView's GestureDetector onTouchEvent",而"MyTextView's GestureDetector onTouchEvent"返回false,事件還是會繼續傳遞給“MyRelativeLayout onTouchEvent”。 解決的辦法是什么呢?自然是把OnGestureListener的帶返回值的幾個回調方法返回true,這樣觸摸屏事件就被“GestureDetector onTouchEvent”所消費,看一下日志會更加清楚:
09-08 10:36:10.714: V/gesturedemo(13130): MainActivity--->dispatchTouchEvent
09-08 10:36:10.718: V/gesturedemo(13130): MyRelativeLayout--->dispatchTouchEvent
09-08 10:36:10.722: V/gesturedemo(13130): MyRelativeLayout--->onInterceptTouchEvent
09-08 10:36:10.722: V/gesturedemo(13130): MyTextView--->dispatchTouchEvent
09-08 10:36:10.722: V/gesturedemo(13130): MyTextView--->onTouchEvent
09-08 10:36:10.824: V/gesturedemo(13130): MainActivity--->dispatchTouchEvent
09-08 10:36:10.828: V/gesturedemo(13130): MyRelativeLayout--->dispatchTouchEvent
09-08 10:36:10.832: V/gesturedemo(13130): MyRelativeLayout--->onInterceptTouchEvent
09-08 10:36:10.835: V/gesturedemo(13130): MyTextView--->dispatchTouchEvent
09-08 10:36:10.835: V/gesturedemo(13130): MyTextView--->onTouchEvent
09-08 10:36:10.863: V/gesturedemo(13130): MainActivity--->dispatchTouchEvent
09-08 10:36:10.878: V/gesturedemo(13130): MyRelativeLayout--->dispatchTouchEvent
09-08 10:36:10.886: V/gesturedemo(13130): MyRelativeLayout--->onInterceptTouchEvent
09-08 10:36:10.886: V/gesturedemo(13130): MyTextView--->dispatchTouchEvent
09-08 10:36:10.886: V/gesturedemo(13130): MyTextView--->onTouchEvent
09-08 10:36:10.898: V/gesturedemo(13130): MainActivity--->dispatchTouchEvent
09-08 10:36:10.898: V/gesturedemo(13130): MyRelativeLayout--->dispatchTouchEvent
09-08 10:36:10.898: V/gesturedemo(13130): MyRelativeLayout--->onInterceptTouchEvent
09-08 10:36:10.898: V/gesturedemo(13130): MyTextView--->dispatchTouchEvent
09-08 10:36:10.898: V/gesturedemo(13130): MyTextView--->onTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MainActivity--->dispatchTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MyRelativeLayout--->dispatchTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MyRelativeLayout--->onInterceptTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MyTextView--->dispatchTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MyTextView--->onTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MyTextView--->onFling
Activity的手勢實現和View的是一樣的,這里就不重復說了,只不過你不用再修改手勢回調方法的返回值了。
下面我又突然想到了一個問題,就是手勢區域重復了怎么辦?舉個例子,有一個只包含一個View的Activity,需要實現在View區域向右Fling關閉Activity,向下Fling做別的一些操作,
1、如果邏輯都實現在View上是非常簡單的,在onFling中直接判斷就可以了。
2、但是有的情況只允許向右Fling的判斷實現在Activity中,向下Fling的判斷實現在View中(或者相反,總之是分開判斷),這個時候又該怎么辦?
對于第二種情況,答案還是很有意思的,讀者如果感興趣的話可以發表評論,有營養的評論超過5條后我會將答案的代碼下載地址放在文章的最后。

輸入法手勢識別

在手寫輸入中,會為每一個字符定義一個特征碼,這些特征碼都保存在相應的文件中(可能有一個或多個這樣的文件),當用戶繪制一個描述字符的圖形時,系統會為所繪制的圖形提取特征碼,然后會在保存特征碼文件中查找相對應的特征碼,如果找到,就會將對應的字符返回。其中,這些文件被稱為手勢文件。
我們來做一個簡單的手勢識別APP。
一、首先需要建立手勢文件,這里需要借助SDK自帶的Sample,大家在Eclipse中File--->New--->Project--->Android--->Android Sample Project,選擇GestureBuilder,運行之,建立幾個自己的手勢,然后把手勢文件拿出來即可(每建立一個手勢會有一個Toast彈出,告訴你文件的保存路徑)。
其實可以想像gestures手勢文件中就是一個一個的鍵值對。
二、把gestures文件放入工程的res/raw目錄下,有關raw和assets的區別,請移步 http://blog.csdn.net/benbmw2008/article/details/8754373
布局文件如下:
      <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/tv1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:text="@string/hello_world"
        android:textSize="24sp" />

    <android.gesture.GestureOverlayView
        android:id="@+id/gestures"
        android:layout_width="200dip"
        android:layout_height="200dip"
        android:layout_centerInParent="true"
        android:background="#33B5E5" >
    </android.gesture.GestureOverlayView>

</RelativeLayout>
    

代碼如下:
      package com.a2bgeek.gesturedemo2;

import java.util.ArrayList;

import android.os.Bundle;
import android.app.Activity;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.gesture.Prediction;
import android.view.Menu;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

	private TextView mTextView;
	private GestureOverlayView mGestureOverlayView;
	private GestureLibrary mGestureLibrary;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initViews();
	}

	private void initViews() {
		mTextView = (TextView) findViewById(R.id.tv1);
		mGestureLibrary = GestureLibraries.fromRawResource(
				getApplicationContext(), R.raw.gestures);
		if (mGestureLibrary.load()) {
			mGestureOverlayView = (GestureOverlayView) findViewById(R.id.gestures);
			mGestureOverlayView
					.addOnGesturePerformedListener(new MyGesturePerformListener());
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	private class MyGesturePerformListener implements
			OnGesturePerformedListener {

		@Override
		public void onGesturePerformed(GestureOverlayView overlay,
				Gesture gesture) {
			// TODO Auto-generated method stub
			ArrayList<Prediction> list = mGestureLibrary.recognize(gesture);
			if (list.size() > 0) {
				//list是mGestureLibrary中可能與gesture匹配的手勢集,匹配的程度會有一個score評分。
				StringBuilder sb = new StringBuilder();
				for (Prediction prediction : list) {
					sb.append(prediction.name);
					sb.append(":");
					sb.append(prediction.score);
					sb.append("\n");
				}
				mTextView.setText(sb.toString());
			} else {
				Toast.makeText(getApplicationContext(), "沒有匹配",
						Toast.LENGTH_SHORT).show();
			}
		}

	}

}

    

【Android每周專題】觸摸屏手勢
好了,今天的內容就到這里了,第一周更新了兩篇專題,是個良好的開始,嗯嗯,加油。

【Android每周專題】觸摸屏手勢


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产区视频在线 | 国产精品一区视频 | 久草在线观看福利 | 国产精品久久久久久久久福利 | 中文字幕日本不卡 | 欧美男女视频 | 九九在线观看精品视频6 | 97av在线播放 | 99热在线精品观看 | 天海冀一二三区 | 日日爽日日操 | 日韩一区二区在线免费观看 | 夜夜躁狠狠躁日日躁视频 | 亚洲你xx我xx网站 | 久久久青草 | 狠狠的搞 | 久久这里只有精品免费看青草 | 国产目拍亚洲精品一区麻豆 | 99热成人精品免费久久 | 伊人五月天婷婷琪琪综合 | 日韩亚洲人成在线综合 | 欧美另类久久久精品 | 人人澡人人澡人人看欧美 | 亚洲精品永久一区 | 天天综合久久 | 天色噜噜噜噜 | 九九99 | 国产91免费在线观看 | 亚洲精品久久久久影 | 国产免费播放 | 简单视频在线播放jdav | 亚洲精品免费观看 | 成人免费播放视频777777 | 欧美18videosex护士 | 狠狠2019| 日本 在线播放 | 日本a在线视频 | 欧美一级毛片免费网站 | 欧美亚洲国产视频 | 天天草人人草 | 亚洲一区二区欧美日韩 |