android多點觸摸手勢&手勢庫GestureLibraries

一.手勢事件的監聽方式

1.使用 onTouchEvent事件監聽器或者使用 setOnTouchEventListener監聽觸摸事件javascript

2.事件類型的判斷java

event.getAction()或者event.getActionMask(),注意,前者包含後者,後者判斷起來比較精確android

3.事件的生命週期  Action_DOWN(按下) ---> Action_MOVE(移動) --->Action_UP/Action_CANCELED(擡起手指或者滑出屏幕)ide

在一些事件,如Click,LongClick等事件按照該週期的時間長度和 移動位置來決定的測試

4.事件傳遞的3個階段ui


第一階段是  分發/攔截階段 ondispatchEvent和onInteceptorEvent(通常在此階段處理事件,可能致使事件沒法傳遞)this

第二階段是 向下傳遞階段 onTouchEventspa


學過javascript的讀者可能會發現,這種事件的傳遞和js的十分相似,不過少了一個階段就是 目標View處理階段,按照javascript的劃分,code

第一個階段 捕獲階段(不管如何處理,事件總會傳遞到目標控件)orm

第二個階段 目標控件事件處理階段

第三個階段 冒泡階段(這個階段處理事件的比較多,可終止冒泡)


很顯然,android的事件傳遞階段彷佛很不友好,由於此階段捕獲致使不少處理衝突,甚至目標控件沒法獲得事件,好比ViewGroup攔截事件以後,將直接把事件交給本身的onTouchEvent進行處理,形成子View上的事件處理程序一直沒法執行,不少時候因爲這種事件分發問題致使的錯誤很是多,所以對於這種問題的處理要務必格外當心,若是遇到這種衝突,通常的作法是 2個聯繫密切的 View控件分別綁定事件,並調用getParent().requestDisallowInterceptTouchEvent(true),但這種方法也是由侷限性的,但願有更好想法的讀者指正一下。  


5.多點觸摸事件的處理,對於多點觸摸,可使用

event.getPointersCount()或者觸摸點的數量,而後經過 event.getX(index) ,event.getY(index)得到觸摸點的座標


public class MultiTouchActivity extends Activity
{

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

    public boolean onTouchEvent(MotionEvent event)
    {
    	//  ֻ2個手指
    	if(event.getPointerCount() == 2)
    	{
    		if(event.getAction() == MotionEvent.ACTION_MOVE)
    		{
    			int historySize = event.getHistorySize();
    			if(historySize == 0)
    				return true;
    			//第1個手指的Y座標
    			float currentY1 = event.getY(0);
    			//第1個手指的歷史縱座標 
    			float historyY1 = event.getHistoricalY(0, historySize - 1);
    			//第二個手指的的Y座標
    			float currentY2 = event.getY(1);
    			//第2個手指的歷史縱座標 
    			float historyY2 = event.getHistoricalY(1,historySize - 1);
    			
    			float distance =  Math.abs(currentY1 - currentY2);
    			float historyDistance = Math.abs(historyY1 - historyY2);
    			
    			if(distance > historyDistance)
    			{
    				Log.d("status", "放大");
    				
    			}
    			else if(distance < historyDistance)
    			{
    				Log.d("status", "縮小");
    			}
    			else
    			{
    				Log.d("status", "平行移動");
    			}
    				
    			
    			
    		}
    	}
    	return true;
    }


}


二.使用手勢庫

public class DrawGestureTest extends Activity implements OnGesturePerformedListener  
{  
      
    private GestureOverlayView mDrawGestureView;  
    private static GestureLibrary sStore;  
      
    /** Called when the activity is first created. */  
    @Override  
    public void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
          
        mDrawGestureView = (GestureOverlayView)findViewById(R.id.gesture);  
          
        //設置手勢可多筆畫繪製,默認狀況爲單筆畫繪製  
        mDrawGestureView.setGestureStrokeType(GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE);  
        //設置手勢的顏色(藍色)  
        mDrawGestureView.setGestureColor(gestureColor(R.color.gestureColor));  
        //設置還沒未能造成手勢繪製是的顏色(紅色)  
        mDrawGestureView.setUncertainGestureColor(gestureColor(R.color.ungestureColor));  
        //設置手勢的粗細  
        mDrawGestureView.setGestureStrokeWidth(4);  
        /*手勢繪製完成後淡出屏幕的時間間隔,即繪製完手指離開屏幕後相隔多長時間手勢從屏幕上消失; 
         * 能夠理解爲手勢繪製完成手指離開屏幕後到調用onGesturePerformed的時間間隔 
         * 默認值爲420毫秒,這裏設置爲0.5秒 
         */  
        mDrawGestureView.setFadeOffset(500);  
          
        //綁定監聽器  
        mDrawGestureView.addOnGesturePerformedListener(this);  
        //建立保存手勢的手勢庫  
        createStore();  
    }  
      
    private void createStore()  
    {  
        File mStoreFile = null;   
        /*判斷mStoreFile是爲空。 
         * 判斷手機是否插入SD卡,而且應用程序是否具備訪問SD卡的權限 
         */  
        if (mStoreFile == null && Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))  
        {  
            mStoreFile = new File(Environment.getExternalStorageDirectory(), "mygesture");  
        }   
          
        if (sStore == null)  
        {  
            /* 另外三種建立保存手勢文件的方式以下: 
            //保存手勢的文件在手機SD卡中 
            sStore = GestureLibraries.fromFile(Environment.getExternalStorageDirectory().getAbsolutePath() + "mygesture"); 
            sStore = GestureLibraries.fromPrivateFile(this, Environment.getExternalStorageDirectory().getAbsolutePath + "mygesture"); 
            //保存手勢的文件在應用程序的res/raw文件下 
            sStore = GestureLibraries.fromRawResource(this, R.raw.gestures); 
            */    
            sStore = GestureLibraries.fromFile(mStoreFile);  
        }  
        testLoad();  
    }  
      
    //測試保存手勢的文件是否建立成功  
    private void testLoad()  
    {  
        if (sStore.load())  
        {  
            showMessage("手勢文件裝載成功");  
        }  
        else  
        {  
            showMessage("手勢文件裝載失敗");  
        }  
    }  
      
    public static GestureLibrary getStore()  
    {  
        return sStore;  
    }  
      
    //手勢繪製完成時調用  
    @Override  
    public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture)   
    {  
        // TODO Auto-generated method stub  
        creatDialog(gesture);  
    }  
      
    private void creatDialog(final Gesture gesture)  
    {  
        View dialogView = getLayoutInflater().inflate(R.layout.show_gesture, null);  
        //imageView用於顯示繪製的手勢  
        ImageView imageView = (ImageView) dialogView.findViewById(R.id.show);  
        //獲取用戶保存手勢的名字  
        EditText editText = (EditText)dialogView.findViewById(R.id.name);  
        final String name = editText.getText().toString();  
        // 調用Gesture的toBitmap方法造成對應手勢的位圖  
        final Bitmap bitmap = gesture.toBitmap(128, 128, 10, gestureColor(R.color.showColor));  
        imageView.setImageBitmap(bitmap);  
          
        Builder dialogBuider = new AlertDialog.Builder(DrawGestureTest.this);  
        dialogBuider.setView(dialogView);  
        //綁定對話框的確認按鈕監聽事件  
        dialogBuider.setPositiveButton(  
                "保存", new OnClickListener()  
                {  
  
                    @Override  
                    public void onClick(DialogInterface dialog, int which)  
                    {  
                        // 添加手勢  
                        sStore.addGesture(name, gesture);  
                        // 保存添加的手勢  
                        sStore.save();      
                    }  
                });  
        //綁定對話框的取消按鈕監聽事件  
        dialogBuider.setNegativeButton("取消", new OnClickListener()  
                {  
  
                    @Override  
                    public void onClick(DialogInterface dialog, int which)  
                    {  
                        // TODO Auto-generated method stub  
                                                       
                    }  
                });  
        //顯示對話框  
        dialogBuider.show();  
    }  
      
    private int gestureColor(int resId)  
    {  
        return getResources().getColor(resId);  
    }  
      
    private void showMessage(String s)  
    {  
        Toast.makeText(this, s, Toast.LENGTH_SHORT).show();  
    }  
          
    @Override  
    protected void onDestroy()   
    {  
        // TODO Auto-generated method stub  
        super.onDestroy();  
        //移除綁定的監聽器  
        mDrawGestureView.removeOnGesturePerformedListener(this);  
    }  
  
}

main.xml

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    android:orientation="vertical" >  
  
   <android.gesture.GestureOverlayView   
       android:id="@+id/gesture"  
       android:layout_width="fill_parent"  
       android:layout_height="fill_parent"  
       >      
   </android.gesture.GestureOverlayView>  
  
</LinearLayout>

對話框show_gesture.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    
    <LinearLayout 
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
        
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="8dip"
            android:text="@string/set_gesture_name"/>
        <EditText 
            android:id="@+id/name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
          
    </LinearLayout>

    <ImageView 
        android:id="@+id/show"
        android:layout_gravity="center"
        android:layout_width="128dp"
        android:layout_height="128dp"
        android:layout_marginTop="10dp"/>
</LinearLayout>
相關文章
相關標籤/搜索