碼迷,mamicode.com
首頁 > 移動開發 > 詳細

Android系統編程入門系列之界面Activity交互響應

時間:2021-07-19 16:30:37      閱讀:0      評論:0      收藏:0      [點我收藏+]

標簽:而且   其他   啟動界面   click   將不   右上角   系統   簡單   google   

上篇文章中已經了解到界面Activity的繪制完全依賴其加載的視圖組件View,不僅如此,用戶的每次觸摸操作都可以在界面Activity內接收并響應,也可以直接傳遞給其中的某個視圖View響應。本文將針對這兩種用戶交互方式分別展開介紹。

界面內交互

界面響應

說到界面交互,很容易想到用戶在設備屏幕上的觸摸操作??墒瞧聊荒敲创笠趺创_定用戶觸摸的位置呢?Android系統定義了一套屏幕坐標規則,該規則不僅適用于當前的屏幕交互,在后文提及的動畫繪制及其他屏幕相關操作等都同樣適用。該規則將屏幕的左上角作為屏幕坐標的原點,從左上角往右上角延伸的方向作為屏幕坐標的x軸,從左上角往左下角延伸的方向作為屏幕坐標的y軸。

比如針對一款 1024x512 尺寸的TV設備,其左下角的屏幕坐標值為 (0, 512),右下角的屏幕坐標值為 (1024, 512),右上角的屏幕坐標值為 (1024, 0),左上角的屏幕坐標值為 (0, 0)。

對屏幕的觸摸位置有了衡量標準,是不是就可以根據不同的位置做觸摸操作了呢?說到觸摸操作,也需要細化之后單獨處理。Android系統將用戶操作行為,大致分為三種:按下行為,滑動行為,抬起釋放行為。這樣系統就可以根據每一個操作行為做單獨的響應處理了。

另外,用戶的操作對象,除了上文提到的硬件設備屏幕以外,還有硬件設備的按鍵(包括硬件按鍵和虛擬按鍵)。只不過對按鍵的操作行為只有按下行為抬起釋放行為兩種,而且按鍵的操作不需要用到屏幕坐標相關內容。

基于上文的介紹,可以在界面Activity中可以分別重寫下邊三個方法對用戶的界面操作交互做出響應。

  • boolean onTouchEvent(MotionEvent event)
    在子視圖沒有處理的情況下,用戶對硬件設備屏幕的每一個操作,都會回調一次該方法。

    其參數android.view.MotionEvent事件類的實例化對象event。
    event.getAction()方法可以獲取當前事件行為,包括MotionEvent.ACTION_DOWN按下行為、MotionEvent.ACTION_MOVE滑動行為、MotionEvent.ACTION_UP抬起釋放行為等。
    event.getX()方法獲取當前操作的屏幕坐標x軸值。
    同理event.getY()方法獲取當前操作的屏幕坐標y軸值。

  • boolean onKeyDown(int keyCode, KeyEvent event)
    在子視圖沒有處理的情況下,用戶對硬件設備按鍵的每一次按下行為,都會回調一次該方法。

    參數一int類型的keyCode指定按鍵類型,一般其值與參數二event.getKeyCode()相等。
    參數二android.view.KeyEvent類的實例化對象event。
    event.getAction()方法同樣可以獲取當前事件行為,只有KeyEvent.ACTION_DOWN按下行為KeyEvent.ACTION_UP抬起釋放行為兩個行為值。
    event.getKeyCode()方法可以獲取觸發當前事件的按鍵類型,其值包括KeyEvent.KEYCODE_HOMEHOME鍵,KeyEvent.KEYCODE_POWER電源鍵,KEYCODE_VOLUME_UP音量增加鍵等。

  • boolean onKeyUp(int keyCode, KeyEvent event)
    在子視圖沒有處理的情況下,用戶對硬件設備按鍵的每一次抬起釋放行為,都會回調一次該方法。其兩個參數與上述onKeyDown()中的兩個參數類似。

視圖響應

相對來說,界面內的視圖響應要繁瑣一些,而能實現的效果也更多樣化。當把視圖View作為用戶的操作對象時,仍然可以重寫上述界面響應的三個方法,但是系統視圖往往也封裝了一層更加簡單粗暴的響應方法。

在視圖中重寫界面響應的三個方法后,如果返回的結果為true,則上文界面響應中的三個方法將不會被回調。

為什么需要封裝一層響應方法呢?用戶對視圖的操作,往往就是點擊(短時間內執行按下行為抬起釋放行為),長按(在執行按下行為后等待一段時間再執行抬起釋放行為),拖拽(在執行按下行為后執行一段滑動行為之后再執行抬起釋放行為)這些固定操作類型。如果每個視圖都要細分用戶的操作行為,就會有大量冗余的操作類型判斷代碼,所以AndroidSDK定義了一系列接口分別對應用戶的操作類型。視圖如果需要響應某個操作,只需要設置其操作類型接口的實例化對象,并在該對象中實現相關方法即可。而這些接口主要有以下三個。

  • View.OnClickListener接口
    需要實現onClick(View view)方法,在該方法內響應響應視圖View被用戶點擊后的代碼邏輯。
  • View.OnLongClickListener接口
    需要實現onLongClick(View view)方法,在該方法內響應響應視圖View被用戶長按后的代碼邏輯。
  • View.OnDragListener接口
    需要實現onDrag(View v, DragEvent event)方法,在該方法內響應視圖View被用戶拖拽后的代碼邏輯。

另外,不同的系統視圖也可能有單獨設置的響應方法,或者自定義視圖也會提供單獨的響應方法,例如列表視圖中的某一行數據被單獨點擊后如何響應,這些都要根據具體的視圖類查找并使用對應的響應方法,這里不再贅述。

事件傳遞機制

在上文界面響應的三個方法中,關于他們被回調的時機,有個前提是子視圖沒有處理,即子視圖的界面響應方法返回結果為false。這就涉及到Android系統的事件傳遞機制了。
我們知道界面Activity在創建之后會調用setContentView(int layoutId)加載根視圖View,而根視圖里邊則可以內嵌一層層的子視圖。那么,如果用戶將手指觸摸到屏幕上,會觸發按下行為,該行為作為事件首先傳遞到根視圖中,之后根視圖再將該事件傳遞給子視圖,子視圖再將該事件傳遞給子視圖的子視圖,這樣按照加載時的嵌套順序一層層傳遞事件,稱之為事件分發。
直到該事件傳遞到最后一層子視圖,或者某一層視圖不再繼續傳遞該事件,那么該事件將在最后傳遞到的這層視圖中被首先處理。而每層視圖在收到傳遞進來的事件后,都有兩條路可以選擇,要么將該事件繼續傳遞給子視圖,要么自己處理該事件,如果選擇第二條路不再繼續傳遞子視圖而是自己處理該事件,稱之為事件攔截。
一旦某層視圖處理了該事件,那么其父層視圖將繼續處理該事件,之后是父層的父層視圖處理該事件,事件被這樣一層層處理,直到根視圖處理該事件結束,稱之為事件處理。
在經歷了事件分發事件處理之后,這樣的一個事件傳遞機制就算完成了。而上文提到的每一個事件,都是如此。

上述過程在代碼中的實現,只需要針對事件分發、事件攔截事件處理分別定義一個可重寫的方法即可。能夠重寫該方法的位置主要是android.app.Acitivtyandroid.view.View中,由于事件攔截只會發生在子視圖的傳遞過程中,在界面中并不需要,所以事件攔截對應的方法只在android.view.GroupView中重寫。

  • boolean dispatchTouchEvent (MotionEvent event)
    當某個事件被分發到該視圖時,系統回調視圖中的該方法。返回結果表示當前事件是否被處理。
  • boolean onInterceptTouchEvent(MotionEvent event)
    當某個事件被分發到該視圖后,系統會回調視圖中的該方法,根據其返回結果判斷是否攔截該事件交由當前視圖處理。默認返回結果為false,表示不攔截該事件,將會繼續回調子視圖的dispatchTouchEvent()。返回結果為true時,表示攔截該事件,將會回調當前視圖的onTouchEvent().
  • boolean onTouchEvent (MotionEvent event)
    當某個事件輪到該視圖被處理時,系統會回調視圖中的該方法。返回結果表示當前事件是否被處理。

界面間交互

上文介紹了針對一個界面Activity的交互響應,那么兩個界面Activity之間如何交互呢?這就用到在加載界面一文中啟動Activity所使用的android.content.Intent意圖類了。不同于用戶與界面的交互,界面間交互主要是變量數據的共享,所以通過Intent支持的交互數據類型是有限的。

發送數據界面

在啟動一個界面Activity之前要先創建意圖對象,在該意圖對象調用putExtras(Bundle bundle)方法,可以將要發送的數據打包成android.os.Bundle類型的實例存入。

而該Bundle對象可以存儲的數據類型支持包括boolean、char、byte、short、int、float、double、long八種基本數據類型,String類型和實現Parcelable接口的任意類型,及其[]數組或ArrayList數組,和其他一些不常用類型。這些數據都是以key-value鍵值對的形式保存在Bundle對象中。對于要保存的不同數據類型,分別調用對應的putT(String key, T value)系列方法即可以參數一key和參數二value的形式存入,同樣可以調用對應的getT(String key)系列方法取出指定參數一key對應的value數據,這里的T泛指支持的不同數據類型。
另外也可以在創建的意圖對象中直接調用putExtra(String key, T value)系列方法,將要發送的數據直接以key-value鍵值對的形式存入,同樣也可以使用getTExtra(String key)系列方法取出指定參數一key對應的value數據,這里的T同樣泛指Bundle可支持的不同數據類型。

在打包所有的數據后,就可以在當前界面Activity中繼續調用startActivity(Intent intent)系列方法啟動Intent意圖參數中指定的另一界面Activity了。
這里的startActivity(Intent)方法是最簡單的啟動方法,另外還有startActivity(Intent, Bundle)在啟動時將要發送的數據打包作為參數二傳入。
或者startActivityForResult(Intent intent, int requestCode)在啟動時傳入一個唯一值作為參數二,以區分啟動不同界面的意圖,在啟動的界面Activity返回后,系統會調用當前界面Activity中的onActivityResult(int requestCode, int resultCode, Intent data)方法,因此可以重寫該方法。并根據參數一的唯一性對之前啟動的不同界面意圖做區分處理。參數二是根據啟動界面不同關閉狀態所返回的結果值,默認為android.app.Activity.RESULT_CANCELED,另外也可以為android.app.Activity.RESULT_FIRST_USERandroid.app.Activity.RESULT_OK,其值需要在啟動界面返回時設置。參數三是從啟動界面返回的Intent類型,主要使用其中的Bundle打包數據類型對象,同樣其值可以在啟動界面返回時設置。

接收數據界面

作為接收數據的啟動界面Activity,在其綁定上下文環境之后,一般是在onCreate(Bundle savedInstanceState)方法中,可以使用getIntent()方法獲取傳遞進來的Intent意圖對象,獲取該對象之后自然就可以通過getBExtras()或一系列getTExtra(String key)獲取到打包的數據,這樣在啟動界面中就可以使用在啟動之前上一個界面Activtiy中的變量數據了。

而當啟動界面Activity在被用戶操作返回時,系統將回調該啟動界面的onBackPressed()方法,之后將該Activity從棧中移出并銷毀。所以可以重寫onBackPressed()方法,在該方法中調用setResult(int resultCode, Intent data)設置上文提到的返回時參數。
或者在啟動界面Activity代碼中也可以主動調用finish()方法,以關閉當前界面。因此在調用finish()方法之前先調用setResult(int resultCode, Intent data)設置返回參數即可。

Android系統編程入門系列之界面Activity交互響應

標簽:而且   其他   啟動界面   click   將不   右上角   系統   簡單   google   

原文地址:https://www.cnblogs.com/BobGo/p/15004013.html

(0)
(0)
   
舉報
評論 一句話評論(0
登錄后才能評論!
? 2014 mamicode.com 版權所有  聯系我們:gaon5@hotmail.com
迷上了代碼!
4399在线看MV_久久99精品久久久久久久久久_成人又黄又爽又刺激视频_能收黄台的app不收费