鍵鼠事件

2024-02-07 12:46 更新

鍵鼠事件指鍵盤,鼠標(biāo)外接設(shè)備的輸入事件。

鼠標(biāo)事件

支持的鼠標(biāo)事件包含通過外設(shè)鼠標(biāo)、觸控板觸發(fā)的事件。

鼠標(biāo)事件可觸發(fā)以下回調(diào):

名稱

描述

onHover(event: (isHover: boolean) => void)

鼠標(biāo)進(jìn)入或退出組件時(shí)觸發(fā)該回調(diào)。

isHover:表示鼠標(biāo)是否懸浮在組件上,鼠標(biāo)進(jìn)入時(shí)為true, 退出時(shí)為false。

onMouse(event: (event?: MouseEvent) => void)

當(dāng)前組件被鼠標(biāo)按鍵點(diǎn)擊時(shí)或者鼠標(biāo)在組件上懸浮移動(dòng)時(shí),觸發(fā)該回調(diào),event返回值包含觸發(fā)事件時(shí)的時(shí)間戳、鼠標(biāo)按鍵、動(dòng)作、鼠標(biāo)位置在整個(gè)屏幕上的坐標(biāo)和相對于當(dāng)前組件的坐標(biāo)。

當(dāng)組件綁定onHover回調(diào)時(shí),可以通過hoverEffect屬性設(shè)置該組件的鼠標(biāo)懸浮態(tài)顯示效果。

圖1 鼠標(biāo)事件數(shù)據(jù)流

鼠標(biāo)事件傳遞到ArkUI之后,會(huì)先判斷鼠標(biāo)事件是否是左鍵的按下/抬起/移動(dòng),然后做出不同響應(yīng):

  • 是:鼠標(biāo)事件先轉(zhuǎn)換成相同位置的觸摸事件,執(zhí)行觸摸事件的碰撞測試、手勢判斷和回調(diào)響應(yīng)。接著去執(zhí)行鼠標(biāo)事件的碰撞測試和回調(diào)響應(yīng)。
  • 否:事件僅用于執(zhí)行鼠標(biāo)事件的碰撞測試和回調(diào)響應(yīng)。
說明

所有單指可響應(yīng)的觸摸事件/手勢事件,均可通過鼠標(biāo)左鍵來操作和響應(yīng)。例如當(dāng)我們需要開發(fā)單擊Button跳轉(zhuǎn)頁面的功能、且需要支持手指點(diǎn)擊和鼠標(biāo)左鍵點(diǎn)擊,那么只綁定一個(gè)點(diǎn)擊事件(onClick)就可以實(shí)現(xiàn)該效果。若需要針對手指和鼠標(biāo)左鍵的點(diǎn)擊實(shí)現(xiàn)不一樣的效果,可以在onClick回調(diào)中,使用回調(diào)參數(shù)中的source字段即可判斷出當(dāng)前觸發(fā)事件的來源是手指還是鼠標(biāo)。

onHover

  1. onHover(event: (isHover?: boolean) => void)

鼠標(biāo)懸浮事件回調(diào)。參數(shù)isHover類型為boolean,表示鼠標(biāo)進(jìn)入組件或離開組件。該事件不支持自定義冒泡設(shè)置,默認(rèn)父子冒泡。

若組件綁定了該接口,當(dāng)鼠標(biāo)指針從組件外部進(jìn)入到該組件的瞬間會(huì)觸發(fā)事件回調(diào),參數(shù)isHover等于true;鼠標(biāo)指針離開組件的瞬間也會(huì)觸發(fā)該事件回調(diào),參數(shù)isHover等于false。

說明

事件冒泡:在一個(gè)樹形結(jié)構(gòu)中,當(dāng)子節(jié)點(diǎn)處理完一個(gè)事件后,再將該事件交給它的父節(jié)點(diǎn)處理。

  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct MouseExample {
  5. @State isHovered: boolean = false;
  6. build() {
  7. Column() {
  8. Button(this.isHovered ? 'Hovered!' : 'Not Hover')
  9. .width(200).height(100)
  10. .backgroundColor(this.isHovered ? Color.Green : Color.Gray)
  11. .onHover((isHover: boolean) => { // 使用onHover接口監(jiān)聽鼠標(biāo)是否懸浮在Button組件上
  12. this.isHovered = isHover;
  13. })
  14. }.width('100%').height('100%').justifyContent(FlexAlign.Center)
  15. }
  16. }

該示例創(chuàng)建了一個(gè)Button組件,初始背景色為灰色,內(nèi)容為“Not Hover”。示例中的Button組件綁定了onHover回調(diào),在該回調(diào)中將this.isHovered變量置為回調(diào)參數(shù):isHover。

當(dāng)鼠標(biāo)從Button外移動(dòng)到Button內(nèi)的瞬間,回調(diào)響應(yīng),isHover值等于true,isHovered的值變?yōu)閠rue,將組件的背景色改成Color.Green,內(nèi)容變?yōu)椤癏overed!”。

當(dāng)鼠標(biāo)從Button內(nèi)移動(dòng)到Button外的瞬間,回調(diào)響應(yīng),isHover值等于false,又將組件變成了初始的樣式。

onMouse

  1. onMouse(event: (event?: MouseEvent) => void)

鼠標(biāo)事件回調(diào)。綁定該API的組件每當(dāng)鼠標(biāo)指針在該組件內(nèi)產(chǎn)生行為(MouseAction)時(shí),觸發(fā)事件回調(diào),參數(shù)為MouseEvent對象,表示觸發(fā)此次的鼠標(biāo)事件。該事件支持自定義冒泡設(shè)置,默認(rèn)父子冒泡。常見用于開發(fā)者自定義的鼠標(biāo)行為邏輯處理。

開發(fā)者可以通過回調(diào)中的MouseEvent對象獲取觸發(fā)事件的坐標(biāo)(screenX/screenY/x/y)、按鍵(MouseButton)、行為(MouseAction)、時(shí)間戳(timestamp)、交互組件的區(qū)域(EventTarget)、事件來源(SourceType)等。MouseEvent的回調(diào)函數(shù)stopPropagation用于設(shè)置當(dāng)前事件是否阻止冒泡。

說明

按鍵(MouseButton)的值:Left/Right/Middle/Back/Forward 均對應(yīng)鼠標(biāo)上的實(shí)體按鍵,當(dāng)這些按鍵被按下或松開時(shí)觸發(fā)這些按鍵的事件。None表示無按鍵,會(huì)出現(xiàn)在鼠標(biāo)沒有按鍵按下或松開的狀態(tài)下,移動(dòng)鼠標(biāo)所觸發(fā)的事件中。

  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct MouseExample {
  5. @State isHovered: boolean = false;
  6. @State buttonText: string = '';
  7. @State columnText: string = '';
  8. build() {
  9. Column() {
  10. Button(this.isHovered ? 'Hovered!' : 'Not Hover')
  11. .width(200)
  12. .height(100)
  13. .backgroundColor(this.isHovered ? Color.Green : Color.Gray)
  14. .onHover((isHover: boolean) => {
  15. this.isHovered = isHover
  16. })
  17. .onMouse((event: MouseEvent) => { // 給Button組件設(shè)置onMouse回調(diào)
  18. this.buttonText = 'Button onMouse:\n' + '' +
  19. 'button = ' + event.button + '\n' +
  20. 'action = ' + event.action + '\n' +
  21. 'x,y = (' + event.x + ',' + event.y + ')' + '\n' +
  22. 'screenXY=(' + event.screenX + ',' + event.screenY + ')';
  23. })
  24. Divider()
  25. Text(this.buttonText).fontColor(Color.Green)
  26. Divider()
  27. Text(this.columnText).fontColor(Color.Red)
  28. }
  29. .width('100%')
  30. .height('100%')
  31. .justifyContent(FlexAlign.Center)
  32. .borderWidth(2)
  33. .borderColor(Color.Red)
  34. .onMouse((event: MouseEvent) => { // 給Column組件設(shè)置onMouse回調(diào)
  35. this.columnText = 'Column onMouse:\n' + '' +
  36. 'button = ' + event.button + '\n' +
  37. 'action = ' + event.action + '\n' +
  38. 'x,y = (' + event.x + ',' + event.y + ')' + '\n' +
  39. 'screenXY=(' + event.screenX + ',' + event.screenY + ')';
  40. })
  41. }
  42. }

在onHover示例的基礎(chǔ)上,給Button綁定onMouse接口。在回調(diào)中,打印出鼠標(biāo)事件的button/action等回調(diào)參數(shù)值。同時(shí),在外層的Column容器上,也做相同的設(shè)置。整個(gè)過程可以分為以下兩個(gè)動(dòng)作:

  1. 移動(dòng)鼠標(biāo):當(dāng)鼠標(biāo)從Button外部移入Button的過程中,僅觸發(fā)了Column的onMouse回調(diào);當(dāng)鼠標(biāo)移入到Button內(nèi)部后,由于onMouse事件默認(rèn)是冒泡的,所以此時(shí)會(huì)同時(shí)響應(yīng)Column的onMouse回調(diào)和Button的onMouse回調(diào)。此過程中,由于鼠標(biāo)僅有移動(dòng)動(dòng)作沒有點(diǎn)擊動(dòng)作,因此打印信息中的button均為0(MouseButton.None的枚舉值)、action均為3(MouseAction.Move的枚舉值)。
  2. 點(diǎn)擊鼠標(biāo):鼠標(biāo)進(jìn)入Button后進(jìn)行了2次點(diǎn)擊,分別是左鍵點(diǎn)擊和右鍵點(diǎn)擊。

    左鍵點(diǎn)擊時(shí):button = 1(MouseButton.Left的枚舉值),按下時(shí) action = 1(MouseAction.Press的枚舉值),抬起時(shí) action = 2(MouseAction.Release的枚舉值)。

    右鍵點(diǎn)擊時(shí):button = 2(MouseButton.Right的枚舉值),按下時(shí) action = 1(MouseAction.Press的枚舉值),抬起時(shí) action = 2(MouseAction.Release的枚舉值)。

如果需要阻止鼠標(biāo)事件冒泡,可以通過調(diào)用stopPropagation()方法進(jìn)行設(shè)置。

  1. Button(this.isHovered ? 'Hovered!' : 'Not Hover')
  2. .width(200)
  3. .height(100)
  4. .backgroundColor(this.isHovered ? Color.Green : Color.Gray)
  5. .onHover((isHover: boolean) => {
  6. this.isHovered = isHover;
  7. })
  8. .onMouse((event: MouseEvent) => {
  9. event.stopPropagation(); // 在Button的onMouse事件中設(shè)置阻止冒泡
  10. this.buttonText = 'Button onMouse:\n' + '' +
  11. 'button = ' + event.button + '\n' +
  12. 'action = ' + event.action + '\n' +
  13. 'x,y = (' + event.x + ',' + event.y + ')' + '\n' +
  14. 'screenXY=(' + event.screenX + ',' + event.screenY + ')';
  15. })

在子組件(Button)的onMouse中,通過回調(diào)參數(shù)event調(diào)用stopPropagation回調(diào)方法(如下)即可阻止Button子組件的鼠標(biāo)事件冒泡到父組件Column上。

  1. event.stopPropagation()

效果是:當(dāng)鼠標(biāo)在Button組件上操作時(shí),僅Button的onMouse回調(diào)會(huì)響應(yīng),Column的onMouse回調(diào)不會(huì)響應(yīng)。

hoverEffect

  1. hoverEffect(value: HoverEffect)

鼠標(biāo)懸浮態(tài)效果設(shè)置的通用屬性。參數(shù)類型為HoverEffect,HoverEffect提供的Auto、Scale、Highlight效果均為固定效果,開發(fā)者無法自定義設(shè)置效果參數(shù)。

表1 HoverEffect說明

HoverEffect枚舉值

效果說明

Auto

組件默認(rèn)提供的懸浮態(tài)效果,由各組件定義。

Scale

動(dòng)畫播放方式,鼠標(biāo)懸浮時(shí):組件大小從100%放大至105%,鼠標(biāo)離開時(shí):組件大小從105%縮小至100%。

Highlight

動(dòng)畫播放方式,鼠標(biāo)懸浮時(shí):組件背景色疊加一個(gè)5%透明度的白色,視覺效果是組件的原有背景色變暗,鼠標(biāo)離開時(shí):組件背景色恢復(fù)至原有樣式。

None

禁用懸浮態(tài)效果

  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct HoverExample {
  5. build() {
  6. Column({ space: 10 }) {
  7. Button('Auto')
  8. .width(170).height(70)
  9. Button('Scale')
  10. .width(170).height(70)
  11. .hoverEffect(HoverEffect.Scale)
  12. Button('Highlight')
  13. .width(170).height(70)
  14. .hoverEffect(HoverEffect.Highlight)
  15. Button('None')
  16. .width(170).height(70)
  17. .hoverEffect(HoverEffect.None)
  18. }.width('100%').height('100%').justifyContent(FlexAlign.Center)
  19. }
  20. }

Button默認(rèn)的懸浮態(tài)效果就是縮放效果,因此Auto和Scale的效果一樣,Highlight會(huì)使背板顏色變暗,None會(huì)禁用懸浮態(tài)效果。

按鍵事件

圖2 按鍵事件數(shù)據(jù)流

按鍵事件由外設(shè)鍵盤等設(shè)備觸發(fā),經(jīng)驅(qū)動(dòng)和多模處理轉(zhuǎn)換后發(fā)送給當(dāng)前獲焦的窗口。窗口獲取到事件后,會(huì)先給輸入法分發(fā)(輸入法會(huì)消費(fèi)按鍵用作輸入),若輸入法未消費(fèi)該按鍵事件,才會(huì)將事件發(fā)給ArkUI框架。因此,當(dāng)某輸入框組件獲焦,且打開了輸入法,此時(shí)大部分按鍵事件均會(huì)被輸入法消費(fèi),例如字母鍵會(huì)被輸入法用來往輸入框中輸入對應(yīng)字母字符、方向鍵會(huì)被輸入法用來切換選中備選詞。

按鍵事件到ArkUI框架之后,會(huì)先找到完整的父子節(jié)點(diǎn)獲焦鏈。從葉子節(jié)點(diǎn)到根節(jié)點(diǎn),逐一發(fā)送按鍵事件。

onKeyEvent

  1. onKeyEvent(event: (event?: KeyEvent) => void)

按鍵事件回調(diào),當(dāng)綁定該方法的組件處于獲焦?fàn)顟B(tài)下,外設(shè)鍵盤的按鍵事件會(huì)觸發(fā)該API的回調(diào)響應(yīng),回調(diào)參數(shù)為KeyEvent,可由該參數(shù)獲得當(dāng)前按鍵事件的按鍵行為(KeyType)、鍵碼(keyCode)、按鍵英文名稱(keyText)、事件來源設(shè)備類型(KeySource)、事件來源設(shè)備id(deviceId)、元鍵按壓狀態(tài)(metaKey)、時(shí)間戳(timestamp)、阻止冒泡設(shè)置(stopPropagation)。

  1. // xxx.ets
  2. @Entry
  3. @Component
  4. struct KeyEventExample {
  5. @State buttonText: string = '';
  6. @State buttonType: string = '';
  7. @State columnText: string = '';
  8. @State columnType: string = '';
  9. build() {
  10. Column() {
  11. Button('onKeyEvent')
  12. .width(140).height(70)
  13. .onKeyEvent((event: KeyEvent) => { // 給Button設(shè)置onKeyEvent事件
  14. if (event.type === KeyType.Down) {
  15. this.buttonType = 'Down';
  16. }
  17. if (event.type === KeyType.Up) {
  18. this.buttonType = 'Up';
  19. }
  20. this.buttonText = 'Button: \n' +
  21. 'KeyType:' + this.buttonType + '\n' +
  22. 'KeyCode:' + event.keyCode + '\n' +
  23. 'KeyText:' + event.keyText;
  24. })
  25. Divider()
  26. Text(this.buttonText).fontColor(Color.Green)
  27. Divider()
  28. Text(this.columnText).fontColor(Color.Red)
  29. }.width('100%').height('100%').justifyContent(FlexAlign.Center)
  30. .onKeyEvent((event: KeyEvent) => { // 給父組件Column設(shè)置onKeyEvent事件
  31. if (event.type === KeyType.Down) {
  32. this.columnType = 'Down';
  33. }
  34. if (event.type === KeyType.Up) {
  35. this.columnType = 'Up';
  36. }
  37. this.columnText = 'Column: \n' +
  38. 'KeyType:' + this.buttonType + '\n' +
  39. 'KeyCode:' + event.keyCode + '\n' +
  40. 'KeyText:' + event.keyText;
  41. })
  42. }
  43. }

上述示例中給組件Button和其父容器Column綁定onKeyEvent。應(yīng)用打開頁面加載后,組件樹上第一個(gè)可獲焦的非容器組件自動(dòng)獲焦,該應(yīng)用只有一個(gè)Button組件,因此該組件會(huì)自動(dòng)獲焦,由于Button是Column的子節(jié)點(diǎn),Button獲焦也同時(shí)意味著Column獲焦。獲焦機(jī)制見焦點(diǎn)事件。

打開應(yīng)用后,依次在鍵盤上按這些按鍵:“空格、回車、左Ctrl、左Shift、字母A、字母Z”。

  1. 由于onKeyEvent事件默認(rèn)是冒泡的,所以Button和Column的onKeyEvent都可以響應(yīng)。
  2. 每個(gè)按鍵都有2次回調(diào),分別對應(yīng)KeyType.Down和KeyType.Up,表示按鍵被按下、然后抬起。

如果要阻止冒泡,即僅Button響應(yīng)鍵盤事件,Column不響應(yīng),在Button的onKeyEvent回調(diào)中加入event.stopPropagation()方法即可,如下:

  1. Button('onKeyEvent')
  2. .width(140).height(70)
  3. .onKeyEvent((event: KeyEvent) => {
  4. // 通過stopPropagation阻止事件冒泡
  5. event.stopPropagation();
  6. if (event.type === KeyType.Down) {
  7. this.buttonType = 'Down';
  8. }
  9. if (event.type === KeyType.Up) {
  10. this.buttonType = 'Up';
  11. }
  12. this.buttonText = 'Button: \n' +
  13. 'KeyType:' + this.buttonType + '\n' +
  14. 'KeyCode:' + event.keyCode + '\n' +
  15. 'KeyText:' + event.keyText;
  16. })

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號