欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

android按鍵,android按鍵處理流程

Android TV 按鍵焦點(diǎn)事件分發(fā)流程詳解

DecorView →PhoneWindow →Activity→ViewGroup→view

創(chuàng)新互聯(lián)專注于望江企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站建設(shè),商城網(wǎng)站制作。望江網(wǎng)站建設(shè)公司,為望江等地區(qū)提供建站服務(wù)。全流程定制網(wǎng)站,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

下面我們根據(jù)按鍵事件的分發(fā)流程,抽絲剝繭,逐一分析。

private int processKeyEvent(QueuedInputEvent q)

1、DecorView.java

2、Activity.java

3、ViewGroup.java

4、View.java

通過(guò)該方法,接收器receiver的onKeyDown、onKeyUp、onKeyLongPress、onKeyMultiple等方法將被回調(diào)。

在上述按鍵事件的入口中提到的ViewRootImpl中

如果mView.dispatchKeyEvent(event)返回true,則結(jié)束事件分發(fā);

如果返回false,則調(diào)用如下方法

繼續(xù)執(zhí)行后續(xù)的焦點(diǎn)導(dǎo)航流程。

焦點(diǎn)導(dǎo)航的總體流程就是:

1、View focused = mView.findFocus();//從視圖樹(shù)的頂層,即DecorView一層一層的遞歸查找當(dāng)前獲得焦點(diǎn)的view

2、View v = focused.focusSearch(direction);根據(jù)導(dǎo)航的方向查找下一個(gè)可獲取焦點(diǎn)的view

3、v.requestFocus(direction, mTempRect)請(qǐng)求獲取焦點(diǎn)

4、v.requestFocus(direction,mTempRect)內(nèi)部,調(diào)用mParent.requestChildFocus(this, focused)逐層遞歸向上級(jí)通知

ViewRootImpl.java

mView即DecorView,從DecorView開(kāi)始,一層一層的向下遞歸查找當(dāng)前獲得焦點(diǎn)的view

找到了當(dāng)前獲得焦點(diǎn)的focused,調(diào)用該焦點(diǎn)view的focusSearch(direction)方法查找direction方向上下一個(gè)將要獲取焦點(diǎn)的view。

focused.focusSearch(direction)實(shí)際上會(huì)調(diào)用mParent.focusSearch(this, direction)方法,層層遞歸,直到調(diào)用到DecorView的focusSearch(this, direction)方法。

而DecorView繼承ViewGroup,實(shí)際上最終會(huì)調(diào)用到FocusFinder.getInstance().findNextFocus(this, focused, direction),this 就是DecorView對(duì)象。

最終會(huì)調(diào)用到DecorView父類ViewGroup中的FocusFinder.getInstance().findNextFocus(this, focused, direction);

ViewGroup.java

FocusFinder.java

搜索到下一個(gè)獲取焦點(diǎn)的view后,調(diào)用該view.requestFocus(direction, mTempRect)方法

注意:調(diào)用requestFocus(direction, mTempRect)需要區(qū)分調(diào)用者。

如果是ViewGroup,則會(huì)更加焦點(diǎn)獲取策略,實(shí)現(xiàn)父View和子View之間獲取焦點(diǎn)的優(yōu)先級(jí)。

如下是ViewGroup.java 和View.java 中requestFocus方法是實(shí)現(xiàn):

ViewGroup.java

View.java

View獲取到焦點(diǎn)后,會(huì)調(diào)用mParent.requestChildFocus(this, focused)逐層遞歸向上級(jí)通知

ViewGroup.java

Android自定義軟鍵盤(pán)

Android自定義鍵盤(pán)的使用

1、新建一個(gè)xml文件夾放在res目錄下面,然后新建xml文件:money_keyboard.xml

2、然后在XML文件中添加按鈕布局,這個(gè)布局就是鍵盤(pán)的樣子了

3 屬性介紹:

Keyboard:

存儲(chǔ)鍵盤(pán)以及按鍵相關(guān)信息。

android:horizontalGap

按鍵之間默認(rèn)的水平間距。

android:verticalGap

按鍵之間默認(rèn)的垂直間距。

android:keyHeight

按鍵的默認(rèn)高度,以像素或顯示高度的百分比表示。

android:keyWidth:

按鍵的默認(rèn)寬度,以像素或顯示寬度的百分比表示。

Row:

為包含按鍵的容器。

Key:

用于描述鍵盤(pán)中單個(gè)鍵的位置和特性。

android:codes

該鍵輸出的unicode值。

android:codes 官網(wǎng)介紹是說(shuō)這個(gè)是該鍵的unicode 值或者逗號(hào)分隔值,當(dāng)然我們也可以設(shè)置成我們想要的值,在源碼中提供了幾個(gè)特定的值

對(duì)照表:

android:isRepeatable

這個(gè)屬性如果設(shè)置為true,那么當(dāng)長(zhǎng)按該鍵時(shí)就會(huì)重復(fù)接受到該鍵上的動(dòng)作,在 刪除鍵鍵 和 空格鍵 上通常設(shè)為true。

android:keyLabel

顯示在按鍵上的文字。

android:keyIcon 與 keyLabel

是二選一關(guān)系,它會(huì)代替文字以圖標(biāo)的形式顯示在鍵上。

android:keyWidth="33.33333%p"

每一個(gè)按鈕的寬度,可以設(shè)置百分比

android:keyHeight="10%p"

每一個(gè)按鈕高度,可以設(shè)置百分比

KeyboardView是一個(gè)渲染虛擬鍵盤(pán)的View。 它處理鍵的渲染和檢測(cè)按鍵和觸摸動(dòng)作。

顯然我們需要KeyboardView來(lái)對(duì)Keyboard里的數(shù)據(jù)進(jìn)行渲染并呈現(xiàn)給我們以及相關(guān)的點(diǎn)擊事件做處理。 1)//設(shè)置keyboard與KeyboardView相關(guān)聯(lián)的方法。

public void setKeyboard(Keyboard keyboard)

2)//設(shè)置虛擬鍵盤(pán)事件的監(jiān)聽(tīng),此方法必須設(shè)置,不然會(huì)報(bào)錯(cuò)。

public void setOnKeyboardActionListener(OnKeyboardActionListener listener) 步驟上呢,做完第一步的關(guān)聯(lián),并設(shè)置第二步的事件,調(diào)用KeyboardView.setVisible(true);鍵盤(pán)就可以顯示出來(lái)了, 是不是很簡(jiǎn)單。不過(guò)到這里還沒(méi)有結(jié)束哦,接下來(lái)我們?yōu)榱耸褂蒙系谋憷M(jìn)行相應(yīng)的封裝。 封裝 這里我們通過(guò)繼承EditText來(lái)對(duì)Keyboard與KeyboardView進(jìn)行封裝。

attr.xml文件,這里我們需要通過(guò)一個(gè)xml類型的自定義屬性引入我們的鍵盤(pán)描述文件。

1、新建一個(gè)類,我取名叫KeyUtils然后在里面新建三個(gè)屬性。KeyBoard用處可大了,他才是本體,可以通過(guò)設(shè)置他來(lái)切換鍵盤(pán)。

2、構(gòu)造函數(shù),初始下三個(gè)參數(shù)。

3、先說(shuō)下預(yù)覽圖吧,就是效果圖上的預(yù)覽圖,需要預(yù)覽圖的話的將setPreviewEnabled設(shè)置為true,不過(guò)還得在布局文件中的android.inputmethodservice.KeyboardView標(biāo)簽對(duì)立面設(shè)置預(yù)覽布局。否則,不會(huì)有字。至于設(shè)置的布局,一個(gè)TextView就好了~

onPress: 按下觸發(fā)。

onRelease:松開(kāi)觸發(fā)。

onKey : 松開(kāi)觸發(fā),在OnRelease之前觸發(fā)。

swipeLeft : 左滑動(dòng),其他同理。哈哈~就這么懶。

onText :需要在 鍵盤(pán)xml,也就是我此時(shí)的number.xml里面中key標(biāo)簽對(duì)里添加一個(gè)

Android framework添加按鍵

對(duì)應(yīng)android6.1,framework添加按鍵

首先看 KeyEvent 里的一段注釋

\frameworks\base\core\java\android\view\KeyEvent.java

可以看到修改涉及到的文件:

frameworks/native/include/android/keycodes.h

frameworks/native/include/input/InputEventLabels.h

frameworks/base/core/res/res/values/attrs.xml

以及KeyEvent.java

另外還有一個(gè)文件是

\frameworks\base\data\keyboards\Generic.kl

手機(jī)里的位置為

/system/usr/keylayout/Generic.kl

PS : ?從android4.0開(kāi)始使用Generic.kl 替換了?qwerty.kl,后續(xù)版本不再使用qwerty.kl。

接下來(lái)以添加新按鍵為例:

假設(shè)驅(qū)動(dòng)已添加對(duì)應(yīng)按鍵0x2f8

1. \frameworks\base\data\keyboards\Generic.kl

添加新鍵值和對(duì)應(yīng)字符串

其中0x2f8 是驅(qū)動(dòng)上報(bào)的掃描鍵值,?CHARG_STATUS 是我們自己定義的唯一字符串

2. frameworks/native/include/input/InputEventLabels.h

在?KEYCODES[] 中添加

其中DEFINE_KEYCODE是一個(gè)宏定義

將上面的宏展開(kāi)就是?{ CHARG_STATUS,?AKEYCODE_CHARG_STATUS }

其中CHARG_STATUS對(duì)應(yīng)上面定制的字符串

3. frameworks/native/include/android/keycodes.h

在該文件定義新的鍵值

注意鍵值的名字跟上一步步添加的宏展開(kāi)后的名字一致,值280就是應(yīng)用層接收到的keycode

4. 若有需要可重寫(xiě) KeyEvent.java 中的方法,以及 attrs.xml

從上述文件可以猜到鍵值轉(zhuǎn)化流程:

0x2f8----CHARG_STATUS---AKEYCODE_CHARG_STATUS (280)

PS :

1.調(diào)試可打開(kāi)以下庫(kù)文件的開(kāi)關(guān)

\frameworks\native\libs\input

\frameworks\native\services\inputflinger

2. ?adb shell dumpsys input 查看現(xiàn)有輸入系統(tǒng)

3. ?adb shell getevent 可查看現(xiàn)有的輸入事件

4.在/system/usr/keylayout中還有很多Vendor_xxxx_Product_xxxx.kl 之類的配置文件,但是我們沒(méi)有配置對(duì)應(yīng)的vend id等,所以一直使用默認(rèn)的Generic.kl。

android手機(jī)長(zhǎng)按home鍵能起什么作用?

android手機(jī)長(zhǎng)按home鍵能起作用的作用有以下幾類:

Home鍵可以說(shuō)是我們每天使用最多的功能之一,一般我們使用這個(gè)按鍵多數(shù)是用于返回主頁(yè)或調(diào)出語(yǔ)音助手等等。

各個(gè)版本的安卓,常按home鍵,屏幕會(huì)出現(xiàn)最近是用過(guò)的app程序圖標(biāo)。

對(duì)于安卓4.1來(lái)說(shuō),則更加明細(xì),即不僅會(huì)出現(xiàn)最近用過(guò)的aop還會(huì)出現(xiàn),正在后臺(tái)運(yùn)行的程序,一個(gè)簡(jiǎn)單的小窗口即可迅速切換到后臺(tái)程序。

簡(jiǎn)單的理解就是,手機(jī)home鍵就是菜單鍵和主鍵。

android物理鍵

* Android常用的物理按鍵及其觸發(fā)事件

* KEYCODE_POWER 電源鍵

* KEYCODE_MENU 菜單鍵

* KEYCODE_BACK 后退鍵

* KEYCODE_HOME Home鍵

* KEYCODE_CAMERA 相機(jī)鍵

* KEYCODE_SEARCH 查找鍵

* KEYCODE_VOLUME_UP 音量鍵+

* KEYCODE_VOLUME_DOWN 音量鍵-

* KEYCODE_VOLUME_MUTE 靜音

* 方向鍵

* KEYCODE_DPAD_CENTER

* KEYCODE_DPAD_UP

* KEYCODE_DPAD_DOWN

* KEYCODE_DPAD_LEFT

* KEYCODE_DPAD_RIGHT

* 鍵盤(pán)鍵

* 數(shù)字0~9 字母A~Z

* KEYCODE_0 ~ KEYCODE_9

* KEYCODE_A ~ KEYCODE_Z

* 提供的回調(diào)方法有

* onKeyUp()、OnKeyDown()、onKeyLongPress()

*

* @author Administrator

*

*/

public class MainActivity extends Activity {

private Button btnClose = null;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

btnClose = (Button) findViewById(R.id.btnClose);

btnClose.setOnClickListener(new closelistener());

}

class closelistener implements OnClickListener {

@Override

public void onClick(View v) {

// TODO Auto-generated method stub

finish();

}

}

/**

* 重寫(xiě)onKeyDown方法可以攔截系統(tǒng)默認(rèn)的處理

*/

@Override

public boolean onKeyDown(int keyCode, KeyEvent event) {

// TODO Auto-generated method stub

if (keyCode == KeyEvent.KEYCODE_BACK) {

Toast.makeText(this, "后退鍵", Toast.LENGTH_SHORT).show();

return true;

} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {

Toast.makeText(this, "聲音+", Toast.LENGTH_SHORT).show();

return false;

} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {

Toast.makeText(this, "聲音-", Toast.LENGTH_SHORT).show();

return false;

} else if (keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {

Toast.makeText(this, "靜音", Toast.LENGTH_SHORT).show();

return false;

} else if (keyCode == KeyEvent.KEYCODE_HOME) {

Toast.makeText(this, "Home", Toast.LENGTH_SHORT).show();

return true;

}

return super.onKeyDown(keyCode, event);

}

/**

* 重寫(xiě)onTouchEvent方法可以處理Touch事件

*/

@Override

public boolean onTouchEvent(MotionEvent event) {

// TODO Auto-generated method stub

if (event.getAction() == MotionEvent.ACTION_MOVE) {

Toast.makeText(this, "ACTION_MOVE", Toast.LENGTH_SHORT).show();

} else if (event.getAction() == MotionEvent.ACTION_UP) {

Toast.makeText(this, "ACTION_MOVE", Toast.LENGTH_SHORT).show();

} else if (event.getAction() == MotionEvent.ACTION_DOWN) {

Toast.makeText(this, "ACTION_MOVE", Toast.LENGTH_SHORT).show();

}

return super.onTouchEvent(event);

}

}

更多的事件可以參考SDK文檔的MotionEvent、KeyEvent兩個(gè)類,在KeyEvent中如果處理了KeyEvent.KEYCODE_BACK事件,那就不會(huì)執(zhí)行默認(rèn)的操作,比如收到KeyEvent.KEYCODE_BACK事件后默認(rèn)是退出,如果直接return那就不會(huì)處理退出了。

Android TV按鍵焦點(diǎn)原理淺談

原文鏈接: Android TV按鍵焦點(diǎn)原理淺談

本篇主要閱讀 Android 源碼講解 TV 的按鍵事件分發(fā)原理和焦點(diǎn)查找原理,源碼基于 Android9.0 ,首先思考幾個(gè)問(wèn)題:

帶著這些問(wèn)題,我們一起來(lái)擼 Android 源碼吧!了解了系統(tǒng)是如何處理的有便于我們解決 TV 上一些按鍵和焦點(diǎn)的問(wèn)題。

首先我們看下按鍵事件的入口 ViewRootImpl 類中的 ViewPostImeInputStage 內(nèi)部類:

可以看到注釋1,2,3,4分別判斷不同事件執(zhí)行不同方法,本篇主要討論的TV焦點(diǎn)事件,主要看下 processKeyEvent 方法:

可以看到在該方法中執(zhí)行了 mView.dispatchKeyEvent 方法,這里的 View 其實(shí)是 DecorView ,接著看下該方法:

上面首先判斷了如果是第一次按下則處理panel的快捷鍵,如果處理了則不往下走,否則繼續(xù)判斷當(dāng)窗口未銷毀且回調(diào)非空則回調(diào)處理,如果處理了則不往下走,否則讓 PhoneWindow 對(duì)應(yīng)的 onKeyDown , onKeyUp 方法來(lái)處理。

接下來(lái)我們按照這個(gè)派發(fā)順序依次來(lái)看看相關(guān)方法的實(shí)現(xiàn),這里先看看 Activity 的 dispatchKeyEvent 實(shí)現(xiàn):

我們看第1點(diǎn) superDispatchKeyEvent 方法,可以看到該方法為一個(gè)抽象方法,而它的實(shí)現(xiàn)是實(shí)現(xiàn)它的子類 PhoneWindow :

該方法又回調(diào)用 DecorView 中的 superDispatchKeyEvent 方法:

此時(shí),再來(lái)看下 ViewGroup 的 dispatchKeyEvent 方法:

接著看下 View 的 dispatchKeyEvent 方法:

該方法主要是判斷如果有給 View 設(shè)置 OnKeyListener 事件且 View 為可用狀態(tài),則優(yōu)先處理監(jiān)聽(tīng)事件,其次調(diào)用 KeyEvent 的 dispatch 方法,接下來(lái)我們看下該方法:

該方法主要處理了按下、彈起事件,其中按下如果 mRepeatCount 重復(fù)次數(shù)大于0判斷為長(zhǎng)按,則執(zhí)行長(zhǎng)按事件。

我們繼續(xù)看下 View 的 onKeyDown 方法:

按下事件判斷了如果為確認(rèn)相關(guān)的按鍵才到下一步處理,判斷點(diǎn)擊或長(zhǎng)按條件滿足,執(zhí)行按下 View 正中心坐標(biāo),然后執(zhí)行 checkForLongClick 檢查長(zhǎng)按方法,看下該方法如下:

我們經(jīng)常會(huì)遇到電視按遙控器時(shí)長(zhǎng)按會(huì)執(zhí)行一次 onKeyDown 、 onKeyUp ,之后才是一直 onKeyDown ,松開(kāi)后才執(zhí)行 onKeyUp ,原因就在于這個(gè)檢查長(zhǎng)按方法是延遲的。 delayOffset 傳進(jìn)來(lái)的是0,所以延遲時(shí)間為 ViewConfiguration.getLongPressTimeout() ,即該類中定義的 DEFAULT_LONG_PRESS_TIMEOUT 常量。

同樣的如果是觸摸屏,可以看下 View 類中的 onTouchEvent 方法在按下操作的時(shí)候會(huì)開(kāi)啟 CheckForTap 線程檢查是否是長(zhǎng)按,該線程同樣是延遲的,時(shí)間為 ViewConfiguration.getTapTimeout() ,即該類中的 TAP_TIMEOUT 常量,知道了這個(gè)你就知道如果寫(xiě)腳本或插件模擬長(zhǎng)按應(yīng)該間隔多長(zhǎng)時(shí)間了,是不是一下你的模擬長(zhǎng)按插件速度又可以更加準(zhǔn)確快速的實(shí)現(xiàn)了。

不同版本系統(tǒng)定義的延遲時(shí)間有可能不一樣,比如Google API 28 的 DEFAULT_LONG_PRESS_TIMEOUT 是500, TAP_TIMEOUT 是100,而 API 30 的 DEFAULT_LONG_PRESS_TIMEOUT 是400, TAP_TIMEOUT 也是100。

接下來(lái)再看下 Activity 的 onKeyDown :

回到 Decorview 中的 dispatchKeyEvent 方法看看 PhoneWindow 的 onKeyDown 方法:

onKeyUp 方法也可以自己再看下,以上就是淺談按鍵事件的分發(fā)流程了。

總結(jié):

上面講解了按鍵事件分發(fā)流程,當(dāng)上面分發(fā)完所有都沒(méi)消費(fèi)的時(shí)候,就會(huì)繼續(xù)走 ViewRootImpl 的焦點(diǎn)導(dǎo)航流程,接下來(lái)看下 performFocusNavigation 方法:

首先我們看 mView.findFocus() ,該方法實(shí)際是調(diào)用了 ViewGroup 的 findFocus 方法:

該方法很簡(jiǎn)單,就是向下遞歸查找在當(dāng)前頁(yè)面已經(jīng)獲取焦點(diǎn)的 View ,繼續(xù)看 focused.focusSearch(direction) 調(diào)用了 View 的 focusSearch 方法:

該方法向上遞歸查找,調(diào)用 ViewGroup 的 focusSearch 方法:

如果是根命名空間,則調(diào)用 FocusFinder 的 findNextFocus 方法查找焦點(diǎn),否則繼續(xù)往上查找。繼續(xù)看 FocusFinder 的 findNextFocus 方法:

可以看到該方法首先查找用戶指定的下一個(gè)獲取焦點(diǎn)的 view ,如果找到了直接返回該 view ,如果沒(méi)找到繼續(xù)下面先添加 effectiveRoot 下的所有 view 到 focusables 集合中去,然后調(diào)用 findNextFocus 方法查找系統(tǒng)可獲取下一個(gè)焦點(diǎn)的最近 view 。

我們先看下 findNextUserSpecifiedFocus 方法的實(shí)現(xiàn):

通過(guò)用戶指定焦點(diǎn)方式不是本篇的重點(diǎn),這里就不貼出內(nèi)部細(xì)節(jié)源碼了。該方法實(shí)際就是調(diào)用 View 的 findUserSetNextFocus 方法來(lái)查找用戶設(shè)置的下一個(gè)可獲取焦點(diǎn)的 view ,然后在 while 循環(huán)中判斷如果找到的是可以獲取焦點(diǎn)并且可見(jiàn)的并且不是 InTouchNode 模式,則返回該焦點(diǎn),否則繼續(xù)循環(huán)查找直到找了一個(gè)循環(huán)沒(méi)有找到可以獲取焦點(diǎn)的或者 userSetNextFocus 為 null 跳出循環(huán)返回 null 。

再來(lái)看下系統(tǒng)就近原則查找的 findNextFocus 方法:

該方法主要通過(guò) findNextFocusInRelativeDirection 在相對(duì)方向上找下一個(gè)焦點(diǎn),該方法內(nèi)部邏輯比較簡(jiǎn)單,這里就不貼出來(lái)了,進(jìn)去看下就知道其實(shí)就是先給 focusables 排序,然后從中找到 focused 在其中的后一個(gè)或前一個(gè) view ,如果沒(méi)找到并且 focusables 不為空則返回 focusables 的第一個(gè)。

接下來(lái)我們重點(diǎn)看下 findNextFocusInAbsoluteDirection 方法:

再看下 isBetterCandidate 方法,該方法很關(guān)鍵,內(nèi)部包含一系列邏輯如何成為最佳候選者:

該方法英文注釋很直觀,就不中文翻譯了,首先看下成為候選人的 isCandidate 方法:

該方法判斷了目標(biāo)Rect如果在源Rect的方向一側(cè)且不在內(nèi)部的話,則為候選者,如第一個(gè) destRect 左側(cè)應(yīng)在 srcRect 左側(cè)左邊, destRect 右側(cè)應(yīng)在 srcRect 右側(cè)左邊,其他方向同理。

接下來(lái)看下 beamBeats 方法:

網(wǎng)站名稱:android按鍵,android按鍵處理流程
分享路徑:http://chinadenli.net/article14/dseihge.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供定制網(wǎng)站網(wǎng)站設(shè)計(jì)搜索引擎優(yōu)化面包屑導(dǎo)航虛擬主機(jī)網(wǎng)站改版

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁(yè)設(shè)計(jì)