簡略講授Android開辟中觸摸和點擊事宜的相干編程辦法。本站提示廣大學習愛好者:(簡略講授Android開辟中觸摸和點擊事宜的相干編程辦法)文章只能為提供參考,不一定能成為您想要的結果。以下是簡略講授Android開辟中觸摸和點擊事宜的相干編程辦法正文
在Android上,不止一個門路來偵聽用戶和運用法式之間交互的事宜。關於用戶界面裡的事宜,偵聽辦法就是從與用戶交互的特定視圖對象截獲這些事宜。視圖類供給了響應的手腕。
在各類用來組建結構的視圖類外面,你能夠會留意到一些公共的回調辦法看起來對用戶界面事宜有效。這些辦法在該對象的相干舉措產生時被Android框架挪用。好比,當一個視圖(如一個按鈕)被觸摸時,該對象上的onTouchEvent()辦法會被挪用。不外,為了偵聽這個事宜,你必需擴大這個類偏重寫該辦法。很顯著,擴大每一個你想應用的視圖對象(只是處置一個事宜)是荒謬的。這就是為何視圖類也包括了一個嵌套接口的聚集,這些接口含有完成起來簡略很多的回調函數。這些接口叫干事件偵聽器event listeners,是用來截獲用戶和你的界面交互舉措的"門票"。
當你更加廣泛的應用事宜偵聽器來偵聽用戶舉措時,總有那末一次你能夠得為了創立一個自界說組件而擴大一個視圖類。或許你想擴大按鈕Button類來使某些事更花梢。在這類情形下,你將可以或許使事宜處置器event handlers類來為你的類界說缺省事宜行動。
事宜偵聽器Event Listeners
事宜偵聽器是視圖View類的接口,包括一個零丁的回調辦法。這些辦法將在視圖中注冊的偵聽器被用戶界面操作觸發時由Android框架挪用。上面這些回調辦法被包括在事宜偵聽器接口中:
onClick():包括於View.OnClickListener。當用戶觸摸這個item(在觸摸形式下),或許經由過程閱讀鍵或跟蹤球聚焦在這個item上,然後按下"確認"鍵或許按下跟蹤球時被挪用。
onLongClick():包括於View.OnLongClickListener。當用戶觸摸並掌握住這個item(在觸摸形式下),或許經由過程閱讀鍵或跟蹤球聚焦在這個item上,然後堅持按下"確認"鍵或許按下跟蹤球(一秒鐘)時被挪用。
onFocusChange():包括於View.OnFocusChangeListener。當用戶應用閱讀鍵或跟蹤球閱讀進入或分開這個item時被挪用。
onKey():包括於View.OnKeyListener。當用戶聚焦在這個item上並按下或釋放裝備上的一個按鍵時被挪用。
onTouch():包括於View.OnTouchListener。當用戶履行的舉措被當作一個觸摸事宜時被挪用,包含按下,釋放,或許屏幕上任何的挪動手勢(在這個item的界限內)。
onCreateContextMenu():包括於View.OnCreateContextMenuListener。當正在創立一個高低文菜單的時刻被挪用(作為連續的"長點擊"舉措的成果)。
這些辦法是它們響應接口的獨一"住戶"。要界說這些辦法並處置你的事宜,在你的運動中完成這個嵌套接口或界說它為一個匿名類。然後,傳遞你的完成的一個實例給各自的View.set...Listener() 辦法。(好比,挪用setOnClickListener()並傳遞給它你的OnClickListener完成。)
上面的例子解釋了若何為一個按鈕注冊一個點擊偵聽器:
// Create an anonymous implementation of OnClickListener private OnClickListener mCorkyListener = new OnClickListener() { public void onClick(View v) { // do something when the button is clicked } }; protected void onCreate(Bundle savedValues) { ... // Capture our button from layout Button button = (Button)findViewById(R.id.corky); // Register the onClick listener with the implementation above button.setOnClickListener(mCorkyListener); ... }
你能夠會發明把OnClickListener作為運動的一部門來完成會方便的多。這將防止額定的類加載和對象分派。好比:
public class ExampleActivity extends Activity implements OnClickListener { protected void onCreate(Bundle savedValues) { ... Button button = (Button)findViewById(R.id.corky); button.setOnClickListener(this); } // Implement the OnClickListener callback public void onClick(View v) { // do something when the button is clicked } ... }
留意下面例子中的onClick()回調沒有前往值,然則一些其它事宜偵聽器必需前往一個布爾值。緣由和事宜相干。關於個中一些,緣由以下:
onLongClick() – 前往一個布爾值來指導你能否曾經花費了這個事宜而不該該再進一步處置它。也就是說,前往true 表現你曾經處置了這個事宜並且到此為止;前往false 表現你還沒有處置它和/或這個事宜應當持續交給其他on-click偵聽器。
onKey() –前往一個布爾值來指導你能否曾經花費了這個事宜而不該該再進一步處置它。也就是說,前往true 表現你曾經處置了這個事宜並且到此為止;前往false 表現你還沒有處置它和/或這個事宜應當持續交給其他on-key偵聽器。
onTouch() - 前往一個布爾值來指導你的偵聽器能否曾經花費了這個事宜。主要的是這個事宜可以有多個彼此追隨的舉措。是以,假如當吸收到向下舉措事宜時你前往false,那注解你還沒有花費這個事宜並且對後續舉措也不感興致。那末,你將不會被該事宜中的其他舉措挪用,好比手勢或最初湧現向上舉措事宜。
記住按鍵事宜老是遞交給以後核心地點的視圖。它們從視圖條理的頂層開端被分發,然後順次向下,直到達到適當的目的。假如你的視圖(或許一個子視圖)以後具有核心,那末你可以看到事宜經過dispatchKeyEvent()辦法分發。除從你的視圖截獲按鍵事宜,還有一個可選計劃,你還可以在你的運動中應用onKeyDown() and onKeyUp()來吸收一切的事宜。
留意: Android 將起首挪用事宜處置器,其次是類界說中適合的缺省處置器。如許,從這些工作偵聽器中前往true 將停滯事宜向其它事宜偵聽器流傳而且也會壅塞視圖中的缺事宜處置器的回調函數。是以當你前往true時確認你願望終止這個事宜。
事宜處置器Event Handlers
假如你從視圖創立一個自界說組件,那末你將可以或許界說一些回調辦法被用作缺省的事宜處置器。在創立自界說組件Building Custom Components的文檔中,你將進修到一些用作事宜處置的通用回調函數,包含:
你應當曉得還有一些其它辦法,其實不屬於視圖類的一部門,但可以直接影響你處置事宜的方法。所以,當在一個結構裡治理更龐雜的事宜時,斟酌一下這些辦法:
觸摸形式Touch Mode
當用戶應用偏向鍵或跟蹤球閱讀用戶界面時,有需要給用戶可操作的item(好比按鈕)設置核心,如許用戶可以曉得哪一個item將接收輸出。不外,假如這個裝備有觸摸功效,並且用戶經由過程觸摸來和界面交互,那末就沒需要高亮items,或許設定核心到一個特定的視圖。如許,就有一個交互形式 叫"觸摸形式"。
關於一個具有觸摸功效的裝備,一旦用戶觸摸屏幕,裝備將進入觸摸形式。自此今後,只要isFocusableInTouchMode()為真的視圖才可以被聚焦,好比文本編纂部件。其他可觸摸視圖,如按鈕,在被觸摸時將不會接收核心;它們將只是在被按下時簡略的觸發on-click偵聽器。任什麼時候候用戶按下偏向鍵或轉動跟蹤球,這個裝備將加入觸摸形式,然後找一個視圖來接收核心,用戶或許不會經由過程觸摸屏幕的方法來恢復界面交互。
觸摸形式狀況的保護貫串全部體系(一切窗口和運動)。為了查詢以後狀況,你可以挪用isInTouchMode() 來檢查這個裝備以後能否處於觸摸形式中。
處置核心Handling Focus
框架將依據用戶輸出處置慣例的核心挪動。這包括當視圖刪除或隱蔽,或許新視圖湧現時轉變核心。視圖經由過程isFocusable()辦法注解它們想獲得核心的志願。
要轉變視圖能否可以接收核心,可以挪用setFocusable()。在觸摸形式中,你可以經由過程isFocusableInTouchMode()查詢一個視圖能否許可接收核心。你可以經由過程setFocusableInTouchMode()辦法來轉變它。核心挪動基於一個在給定偏向查找比來鄰人的算法。少有的情形是,缺省算法能夠和開辟者的志願行動不婚配。在這些情形下,你可以經由過程上面結構文件中的XML屬性供給顯式的重寫:nextFocusDown, nextFocusLeft, nextFocusRight, 和nextFocusUp。為掉去核心的視圖增長這些屬性之一。界說屬性值為具有核心的視圖的ID。好比:
<LinearLayout android:orientation="vertical" ... > <Button android:id="@+id/top" android:nextFocusUp="@+id/bottom" ... /> <Button android:id="@+id/bottom" android:nextFocusDown="@+id/top" ... /> </LinearLayout>
平日,在這個豎向結構中,從第一個按鈕向上閱讀或許從第二個按鈕向下都不會挪動到其它處所。如今這個頂部按鈕曾經界說了底部按鈕為nextFocusUp (反之亦然),閱讀核心將從上到下和從下到上輪回挪動。
假如你願望在用戶界面中聲明一個可聚焦的視圖(平日不是如許),可以在你的結構界說中,為這個視圖增長android:focusable XML 屬性。把它的值設置成true。你還可以經由過程android:focusableInTouchMode在觸摸形式下聲明一個視圖為可聚焦。
想要求一個接收核心的特定視圖,挪用requestFocus()。
要偵聽核心事宜(當一個視圖取得或許掉去核心時被告訴到),應用onFocusChange(),如下面事宜偵聽器Event Listeners所描寫的那樣。
觸摸事宜、點擊事宜的差別
針對屏幕上的一個View控件,Android若何辨別應該觸發onTouchEvent,照樣onClick,亦或是onLongClick事宜?
在Android中,一次用戶操作可以被分歧的View順次序分離處置,並將完整呼應了用戶一次UI操作稱之為花費了該事宜(consume),那末Android是按甚麼順序將事宜傳遞的呢?又在甚麼情形下剖斷為花費了該事宜?
弄清晰這些成績關於編寫出能准確呼應UI操作的代碼是很主要的,特別當屏幕上的分歧View須要針對此次UI操作做出各類分歧呼應的時刻更是如斯,一個典范例子就是用戶在桌面上放置了一個Widget,那末當用戶針對widget做各類操作時,桌面自己有的時刻要對用戶的操作做出呼應,有時疏忽。只要弄清晰事宜觸發和傳遞的機制才有能夠包管在界面結構異常龐雜的情形下,UI控件依然能准確呼應用戶操作。
1. onTouchEvent
onTouchEvent中要處置的最經常使用的3個事宜就是:ACTION_DOWN、ACTION_MOVE、ACTION_UP。
這三個事宜標識出了最根本的用戶觸摸屏幕的操作,寄義也很清晰。固然年夜家每天都在用它們,然則有一點請留心,ACTION_DOWN事宜作為肇端事宜,它的主要性是要跨越ACTION_MOVE和ACTION_UP的,假如產生了ACTION_MOVE或許ACTION_UP,那末必定已經產生了ACTION_DOWN。
從Android的源代碼中能看到基於這類分歧主要性的懂得而完成的一些交互機制,SDK中也有明白的說起,例如在ViewGroup的onInterceptTouchEvent辦法中,假如在ACTION_DOWN事宜中前往了true,那末後續的事宜將直接發給onTouchEvent,而不是持續發給onInterceptTouchEvent。
2. onClick、onLongClick與onTouchEvent
已經看過一篇帖子提到,假如在View中處置了onTouchEvent,那末就不消再處置onClick了,由於Android只會觸發個中一個辦法。這個懂得是不太准確的,針對某個view,用戶完成了一次觸碰操作,明顯從傳感器上獲得的旌旗燈號是手指按下和抬起兩個操作,我們可以懂得為一次Click,也能夠懂得為產生了一次ACTION_DOWN和ACTION_UP,那末Android是若何懂得和處置的呢?
在Android中,onClick、onLongClick的觸發是和ACTION_DOWN及ACTION_UP相干的,在時序上,假如我們在一個View中同時覆寫了onClick、onLongClick及onTouchEvent的話,onTouchEvent是最早捕獲到ACTION_DOWN和ACTION_UP事宜的,其次才能夠觸發onClick或許onLongClick。重要的邏輯在View.java中的onTouchEvent辦法中完成的:
case MotionEvent.ACTION_DOWN: mPrivateFlags |= PRESSED; refreshDrawableState(); if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { postCheckForLongClick(); } break; case MotionEvent.ACTION_UP: if ((mPrivateFlags & PRESSED) != 0) { boolean focusTaken = false; if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { focusTaken = requestFocus(); } if (!mHasPerformedLongPress) { if (mPendingCheckForLongPress != null) { removeCallbacks(mPendingCheckForLongPress); } if (!focusTaken) { performClick(); } } … break;
可以看到,Click的觸發是在體系捕獲到ACTION_UP後產生並由performClick()履行的,performClick裡會挪用先前注冊的監聽器的onClick()辦法:
public boolean performClick() { … if (mOnClickListener != null) { playSoundEffect(SoundEffectConstants.CLICK); mOnClickListener.onClick(this); return true; } return false; }
LongClick的觸發則是從ACTION_DOWN開端,由postCheckForLongClick()辦法完成:
private void postCheckForLongClick() { mHasPerformedLongPress = false; if (mPendingCheckForLongPress == null) { mPendingCheckForLongPress = new CheckForLongPress(); } mPendingCheckForLongPress.rememberWindowAttachCount(); postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout()); }
可以看到,在ACTION_DOWN事宜被捕獲後,體系會開端觸發一個postDelayed操作,delay的時光在Eclair2.1上為500ms,500ms後會觸發CheckForLongPress線程的履行:
class CheckForLongPress implements Runnable { … public void run() { if (isPressed() && (mParent != null) && mOriginalWindowAttachCount == mWindowAttachCount) { if (performLongClick()) { mHasPerformedLongPress = true; } } } … }
假如各類前提都知足,那末在CheckForLongPress中履行performLongClick(),在這個辦法中將挪用onLongClick():
public boolean performLongClick() { … if (mOnLongClickListener != null) { handled = mOnLongClickListener.onLongClick(View.this); } … }
從完成中可以看到onClick()和onLongClick()辦法是由ACTION_DOWN和ACTION_UP事宜捕獲後依據各類情形終究肯定能否觸發的,也就是說假如我們在一個Activity或許View中同時監聽或許覆寫了onClick(),onLongClick()和onTouchEvent()辦法,其實不意味著只會產生個中一種。