基于原生能力的鍵盤控制

基于原生能力的鍵盤控制

  • 前言
  • 一、進入頁面TextInput獲焦
    • 1、方案
    • 2、核心代碼
  • 二、點擊按鈕或其他事件觸發TextInput獲焦
    • 1、方案
    • 2、核心代碼
  • 三、鍵盤彈出后只上抬特定的輸入組件
    • 1、方案
    • 2、核心代碼
  • 四、監聽鍵盤高度
    • 1、方案
    • 2、核心代碼
  • 五、設置窗口在鍵盤抬起時的頁面避讓模式為上抬,壓縮
    • 1、方案
    • 2、核心代碼
  • demo代碼
    • Index.ets
    • Login.ets
    • Register.ets


前言

應用通常使用鍵盤的方式,系統鍵盤的彈出收起,獲焦失焦,高度監聽,安全避讓等。

應用經常會遇到如下的業務訴求:

場景一:進入頁面TextInput獲焦,彈出系統鍵盤。

場景二:點擊按鈕或其他事件觸發TextInput獲焦,彈出系統鍵盤。

場景三:鍵盤彈出后只上抬特定的輸入組件。

場景四:監聽鍵盤高度,在鍵盤彈出后讓組件上移,鍵盤收起后讓組件恢復。

場景五:設置窗口在鍵盤抬起時的頁面避讓模式為上抬,壓縮。

一、進入頁面TextInput獲焦

1、方案

通過defaultFocus通用屬性設置,實現第一次進入頁面后彈出鍵盤

2、核心代碼

TextInput({ text: $$this.username, placeholder: '請輸入用戶名' }).placeholderColor('#D4D3D1').backgroundColor(this.isUserNameFocus ? '#80FFFFFF' : '#ffffff').width(260).borderRadius(8).id('username').margin({ top: 10, bottom: 10 }).onFocus(() => {this.isUserNameFocus = true}).onBlur(() => {this.isUserNameFocus = false}).defaultFocus(true)   // 進入頁面默認獲焦

二、點擊按鈕或其他事件觸發TextInput獲焦

1、方案

通過focusControl.requestFocus,實現輸入賬號后,點擊登錄按鈕后,代碼主動設置TextInput獲取焦點

2、核心代碼

Button('登  錄').width(200).height(45).fontSize(28).type(ButtonType.Normal).backgroundColor('#30FFFFFF').border({ width: 1, color: Color.White, radius: 8 }).margin({ top: 50, bottom: 60 }).onClick(() => {let LoginForm: LoginForm = {username: this.username,password: this.password}let requestId = ''if (!LoginForm.username) {requestId = 'username'} else if (!LoginForm.password) {requestId = 'password'} else {promptAction.showToast({ message: 'Login success' })return}let res = focusControl.requestFocus(requestId) // 使選中的this.selectId的組件獲焦,這里要注意獲焦的id要與組件的id保持一致promptAction.showToast({ message: requestId + '不能為空' })})

三、鍵盤彈出后只上抬特定的輸入組件

1、方案

通過expandSafeArea通用屬性設置,實現只上抬紅框圈住的特定組件

2、核心代碼

Column(){// 在頁面跟容器設置安全區域這樣頁面就不會上抬了只有對應的輸入框會進行上抬
}
.expandSafeArea([SafeAreaType.KEYBOARD], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])

四、監聽鍵盤高度

1、方案

先通過expandSafeArea禁止自動鍵盤彈出上移頁面。然后通過window.on(‘avoidAreaChange’)和windowClass.on(‘keyboardHeightChange’),實現監聽鍵盤高度,上抬整個頁面view,讓輸入框(生命周期價值輸入框)組件能顯示在鍵盤上方

2、核心代碼

@State screenHeight: Length = 0onPageShow(): void {// ...window.getLastWindow(getContext(this)).then(currentWindow => {let property = currentWindow.getWindowProperties();let avoidArea = currentWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);// 初始化顯示區域高度this.screenHeight = px2vp(property.windowRect.height - avoidArea.topRect.height - avoidArea.bottomRect.height);// 監視軟鍵盤的彈出和收起currentWindow.on('keyboardHeightChange', async data => {// 這里通過監聽鍵盤高度變化來改變跟容器高度變化this.screenHeight = px2vp(property.windowRect.height - avoidArea.topRect.height - data);})})// ...
}Column() {...
}
.width('100%')
.height(this.screenHeight)
.expandSafeArea([SafeAreaType.KEYBOARD], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])

五、設置窗口在鍵盤抬起時的頁面避讓模式為上抬,壓縮

1、方案

點擊生命周期輸入框,通過windowStage.getMainWindowSync().getUIContext().setKeyboardAvoidMode,實現設置窗口在鍵盤抬起時的頁面避讓模式,這種情況下當鍵盤彈起的時候頁面會自動壓縮

2、核心代碼

onPageShow(): void {// ...this.windowStage.getMainWindowSync().getUIContext().setKeyboardAvoidMode(KeyboardAvoidMode.RESIZE)// 在RESIZE模式下當鍵盤彈起的時候頁面會進行壓縮// ...
}onPageHide(): void {this.windowStage.getMainWindowSync().getUIContext().setKeyboardAvoidMode(KeyboardAvoidMode.OFFSET)// 在OFFSET模式下當鍵盤彈起的時候頁面會進行上抬
}

demo代碼

Index.ets

import { router } from '@kit.ArkUI';@Entry
@Component
struct Index {build() {Row() {Column() {Button('進入頁面獲焦').margin({ top: 10, bottom: 10 }).onClick(() => {router.pushUrl({ url: 'pages/Login', params: { pageId: '1' } })})Button('事件觸發主動獲焦').margin({ top: 10, bottom: 10 }).onClick(() => {router.pushUrl({ url: 'pages/Login', params: { pageId: '2' } })})Button('鍵盤彈出不上移組件').margin({ top: 10, bottom: 10 }).onClick(() => {router.pushUrl({ url: 'pages/Register', params: { pageId: '3' } })})Button('監聽鍵盤高度變化').margin({ top: 10, bottom: 10 }).onClick(() => {router.pushUrl({ url: 'pages/Register', params: { pageId: '4' } })})Button('設置頁面避讓模式').margin({ top: 10, bottom: 10 }).onClick(() => {router.pushUrl({ url: 'pages/Register', params: { pageId: '5' } })})}.width('100%')}.height('100%')}
}

Login.ets

import { promptAction, router } from '@kit.ArkUI'interface LoginForm {username: stringpassword: string
}export interface routerParam {pageId: string
}@Entry
@Component
struct Login {@State username: string = ''@Watch('passwordChange') @State password: string = ''@State isUserNameFocus: boolean = false@State isPasswordFocus: boolean = false@State rememberPassword: boolean = false@State showPasswordIcon: boolean = falseprivate controller: TextInputController = new TextInputController()@State routerParams: routerParam = { pageId: '0' }passwordChange() {this.showPasswordIcon = !!this.password}onPageShow(): void {this.routerParams = router.getParams() as routerParamconsole.log(this.routerParams.pageId)}build() {Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {Row() {Image($r('app.media.avatar')).width(60).height(60)}.borderRadius(50).width(100).height(100).justifyContent(FlexAlign.Center).backgroundColor('#FFFFFF').margin({ bottom: 30 })TextInput({ text: $$this.username, placeholder: '請輸入用戶名', controller: this.controller }).placeholderColor('#D4D3D1').backgroundColor(this.isUserNameFocus ? '#80FFFFFF' : '#ffffff').width(260).borderRadius(8).id('username').margin({ top: 10, bottom: 10 }).onFocus(() => {this.isUserNameFocus = true}).onBlur(() => {this.isUserNameFocus = false}).defaultFocus(this.routerParams.pageId === '1') // 進入頁面默認獲焦TextInput({ text: $$this.password, placeholder: '請輸入密碼', controller: this.controller }).placeholderColor('#D4D3D1').type(InputType.Password).showPasswordIcon(this.showPasswordIcon).backgroundColor(this.isPasswordFocus ? '#80FFFFFF' : '#ffffff').width(260).borderRadius(8).id('password').margin({ top: 10, bottom: 10 }).onFocus(() => {this.isPasswordFocus = true}).onBlur(() => {this.isPasswordFocus = false})Row() {Checkbox().select($$this.rememberPassword).unselectedColor('#ffffff').width(16).borderRadius(8).backgroundColor(Color.White)Text('記住密碼').fontColor('#ffffff').onClick(() => {this.rememberPassword = !this.rememberPassword})}.width(260)Button('登  錄').width(200).height(45).fontSize(28).type(ButtonType.Normal).backgroundColor('#30FFFFFF').border({ width: 1, color: Color.White, radius: 8 }).margin({ top: 50, bottom: 60 }).onClick(() => {let LoginForm: LoginForm = {username: this.username,password: this.password}let requestId = ''// todo: 無法使用for..in遍歷對象if (!LoginForm.username) {requestId = 'username'} else if (!LoginForm.password) {requestId = 'password'} else {promptAction.showToast({ message: 'Login success' })return}focusControl.requestFocus(requestId) // 使選中的this.selectId的組件獲焦promptAction.showToast({ message: requestId + '不能為空' })})Row() {Text('忘記密碼').fontColor(Color.White)Text('注冊').fontColor(Color.White).onClick(() => {router.pushUrl({ url: 'pages/Register', params: { pageId: '3' } })})}.justifyContent(FlexAlign.SpaceBetween).width(260)}.width('100%').height('100%').expandSafeArea([SafeAreaType.SYSTEM, SafeAreaType.KEYBOARD], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM]).backgroundImage($r('app.media.bg')).backgroundImageSize(ImageSize.Cover).onTouch(() => {this.controller.stopEditing()})}
}

Register.ets

import { KeyboardAvoidMode, router, window } from '@kit.ArkUI';
import { routerParam } from './Login'@Entry
@Component
struct Register {@State routerParams: routerParam = { pageId: '0' }@State screenHeight: Length = '100%'private windowStage = AppStorage.get('windowStage') as window.WindowStageonPageShow(): void {this.routerParams = router.getParams() as routerParamif (this.routerParams.pageId == '5') {this.windowStage.getMainWindowSync().getUIContext().setKeyboardAvoidMode(KeyboardAvoidMode.RESIZE)}if (this.routerParams.pageId == '4') {window.getLastWindow(getContext(this)).then(currentWindow => {let property = currentWindow.getWindowProperties();let avoidArea = currentWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM);// 初始化顯示區域高度this.screenHeight = px2vp(property.windowRect.height - avoidArea.topRect.height - avoidArea.bottomRect.height);// 監視軟鍵盤的彈出和收起currentWindow.on('avoidAreaChange', async data => {if (data.type !== window.AvoidAreaType.TYPE_KEYBOARD) {return;}this.screenHeight =px2vp(property.windowRect.height - avoidArea.topRect.height - data.area.bottomRect.height);})})}}onPageHide(): void {this.windowStage.getMainWindowSync().getUIContext().setKeyboardAvoidMode(KeyboardAvoidMode.OFFSET)}build() {Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {Row() {Image($r('app.media.back')).width(24).position({ x: 16, y: 10 }).onClick(() => {router.back()})Text('用戶注冊').fontSize(24).fontWeight(FontWeight.Bold)}.height(45).borderWidth({ bottom: 1 }).borderColor('#EAEEF5').width('100%').justifyContent(FlexAlign.Center)Column() {Image($r('app.media.logo')).width(240)}// 表單主體List({ space: 16 }) {ListItem() {FormItem({ label: '用戶名', placeholder: '請輸入用戶名' })}ListItem() {FormItem({ label: '密碼', placeholder: '請輸入密碼' })}ListItem() {FormItem({ label: '手機號', placeholder: '請輸入手機號' })}ListItem() {FormItem({ label: '郵箱', placeholder: '請輸入郵箱地址' })}ListItem() {Column() {Text('個人簡介').margin({ bottom: 16 })TextArea({ placeholder: '介紹點啥吧...' }).borderRadius(0).borderWidth({ bottom: 1 }).borderColor('#EAEEF5').height(100)}.alignItems(HorizontalAlign.Start)}}.padding(10).layoutWeight(1).edgeEffect(EdgeEffect.None).scrollBar(BarState.Off).expandSafeArea([SafeAreaType.KEYBOARD], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])Row() {Button('提交').type(ButtonType.Normal).fontColor(Color.White).backgroundColor('#59BEB7').width('100%')}.padding(16).shadow({ radius: 20, color: '#30000000' }).width('100%').expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])}.width('100%').height(this.screenHeight).expandSafeArea([SafeAreaType.KEYBOARD], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])}
}@Component
struct FormItem {@Prop label: string@Prop placeholder: string@State value: string = ''build() {Column() {Text(this.label).margin({ bottom: 16 })TextInput({ text: this.value, placeholder: this.placeholder }).backgroundColor(Color.Transparent).borderRadius(0).borderWidth({ bottom: 1 }).borderColor('#EAEEF5')}.alignItems(HorizontalAlign.Start).expandSafeArea([SafeAreaType.KEYBOARD], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM])}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/910291.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/910291.shtml
英文地址,請注明出處:http://en.pswp.cn/news/910291.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

大數據治理域——數據存儲與成本管理

摘要 本文主要探討了數據存儲與成本管理的多種策略。介紹了數據壓縮技術,如MaxCompute的archive壓縮方法,通過RAID file形式存儲數據,可有效節省空間,但恢復時間較長,適用于冷備與日志數據。還詳細闡述了數據生命周期…

國產Linux銀河麒麟操作系統上使用自帶openssh遠程工具SSH方式登陸華為交換機或服務器

在Windows和Linux Debian系統上我一直使用electerm遠程工具訪問服務器或交換機, 一、 electerm簡介 簡介:electerm是一款開源免費的SSH工具,具有良好的跨平臺兼容性,適用于Windows、macOS、Linux以及麒麟操作系統。特點&#xf…

Logback 在java中的使用

Logback 是 Java 應用中廣泛使用的日志框架&#xff0c;以下是其核心使用方法及最佳實踐&#xff1a; 1. 引入依賴 在 Maven 或 Gradle 項目中添加 Logback 及 SLF4J 依賴&#xff1a; <!-- Maven --> <dependency><groupId>ch.qos.logback</groupId>…

Axure應用交互設計:中繼器—整行、條件行、當前行賦值

親愛的小伙伴,如有幫助請訂閱專欄!跟著老師每課一練,系統學習Axure交互設計課程! Axure產品經理精品視頻課https://edu.csdn.net/course/detail/40420 課程主題:對中繼器中:整行、符合某種條件的任意行、當前行的賦值操作 課程視頻:

ToolsSet之:TTS及Morse編解碼

ToolsSet是微軟商店中的一款包含數十種實用工具數百種細分功能的工具集合應用&#xff0c;應用基本功能介紹可以查看以下文章&#xff1a; Windows應用ToolsSet介紹https://blog.csdn.net/BinField/article/details/145898264其中Text菜單中的TTS & Morse可用于將文本轉換…

【C++】編碼傳輸:創建零拷貝幀對象4:shared_ptr轉unique_ptr給到rtp打包

【C++】編碼傳輸:創建零拷貝幀對象3: dll api轉換內部的共享內存根本原因 你想要的是基于 packet 指向的那個已有對象,拷貝(或移動)出一個新的 VideoDataPacket3 實例,因此需要把那個對象本身傳進去——也就是 *packet。copilot的原因分析與gpt一致 The issue is with t…

基于UDP的套接字通信

udp是一個面向無連接的&#xff0c;不安全的&#xff0c;報式傳輸層協議&#xff0c;udp的通信過程默認也是阻塞的。使用UDP進行通信&#xff0c;服務器和客戶端的處理步驟比TCP要簡單很多&#xff0c;并且兩端是對等的 &#xff08;通信的處理流程幾乎是一樣的&#xff09;&am…

華為CE交換機抓包

capture-packet interface 100GE1/0/5 destination file 001.cap packet-len 64 注&#xff1a;早期版本&#xff08;disp device&#xff09;可能在系統視圖下&#xff08;sys&#xff09; 抓完包后可以看到對應文件&#xff08;早期版本在根目錄下&#xff09;&#xff1a;…

Python 數據分析與可視化 Day 3 - Pandas 數據篩選與排序操作

&#x1f3af; 今日目標 掌握 DataFrame 的條件篩選&#xff08;布爾索引&#xff09;學會多條件篩選、邏輯運算熟練使用排序&#xff08;sort_values&#xff09;提升數據組織力結合列選擇進行數據提取分析 &#x1f9ea; 一、列選擇與基本篩選 ? 選擇單列 / 多列 df[&quo…

Vite項目初始化與配置

下面,我們來系統的梳理關于 Vite 項目初始化與配置 的基本知識點: 一、Vite 核心概念與優勢 1.1 什么是 Vite? Vite(法語意為 “快速”)是新一代的前端構建工具,由 Vue.js 作者尤雨溪開發。它解決了傳統構建工具(如 Webpack)在開發環境中的性能瓶頸問題。 1.2 Vite …

Transformer中的核心問題 知識點匯總

Transformer架構圖 transformer整體架構 1. Transformer 的參數配置 Transformer 的Encoder層和Decoder層都使用6個注意力模塊&#xff0c;所有的子網絡的輸出維度均為512維&#xff0c;多頭注意力部分使用了8個注意力頭。 2. 歸一化的方式 歸一化的方式為LayerNorm&#xff0c…

python web開發-Flask數據庫集成

Flask 數據庫集成完全指南&#xff1a;Flask-SQLAlchemy 實踐 1. 引言 數據庫是現代Web應用的核心組件&#xff0c;Flask通過Flask-SQLAlchemy擴展提供了強大的數據庫集成能力。本文將全面介紹如何在Flask應用中使用Flask-SQLAlchemy進行數據庫操作&#xff0c;涵蓋從基礎配置…

一站式用AI編程神奇Cursor/Trae(VScode環境)開發運行Scala應用

平時開發時&#xff0c;我們常用 IDEA 搭配 Scala 來開發 Spark 或 Flink 等大數據應用。但如今像 Cursor 這樣的編程神器層出不窮&#xff0c;它們只支持 VSCode。要是 Scala 應用能在 VSCode 環境下便捷運行&#xff0c;我們就無需在 VSCode 開發、卻在 IDEA 運行&#xff0c…

【Django開發】django美多商城項目完整開發4.0第2篇:項目準備,配置【附代碼文檔】

教程總體簡介&#xff1a;美多商城 商業模式介紹 1.B2B--企業對企業 2.C2C--個人對個人 5.O2O--線上到線下 開發流程 說明&#xff1a; 需求分析 1. 用戶部分 注冊 登錄 個人信息 地址管理 修改密碼 3. 購物車部分 購物車管理 項目架構 創建工程 1. 在git平臺創建工程 2. 添加前…

基于 OpenCV 的圖像亮度、對比度與銳度調節

圖像亮度、對比度和銳度是圖像質量感知的重要參數&#xff0c;調節這些屬性常用于圖像增強、圖像美化或圖像分析的預處理階段。本文將基于 OpenCV 實現這三項基礎圖像處理功能&#xff0c;并提供滑動條交互界面與直方圖可視化分析&#xff0c;方便調試和理解效果。 亮度調整 圖…

WAF(web應用防火墻)的簡單了解

WAF稱之為Web應用防火墻&#xff0c;是一種專門設計用于保護web應用程序免受惡意攻擊的安全設備&#xff0c;能實時監控過濾和攔截可能對網站造成危害的網絡流量&#xff0c;從而避免網絡服務器被惡意入侵導致性能異常、數據泄露、服務中斷這些問題 (WAF是通過執行一系列針對HT…

跟著AI學習C# Day28

&#x1f4c5; Day 28&#xff1a;C# 源生成器&#xff08;Source Generators&#xff09;與編譯時元編程 ? 學習目標&#xff1a; 理解什么是 源生成器&#xff08;Source Generator&#xff09;&#xff1b;掌握如何在 編譯階段生成 C# 代碼&#xff0c;而不是運行時動態處…

設計模式精講 Day 4:建造者模式(Builder Pattern)

【設計模式精講 Day 4】建造者模式&#xff08;Builder Pattern&#xff09; 文章簡述&#xff1a; 在軟件開發中&#xff0c;對象的構造過程往往復雜且容易出錯&#xff0c;尤其是在對象包含多個可選參數或構建步驟時。建造者模式&#xff08;Builder Pattern&#xff09;正是…

如何輕松地將聯系人從 iPhone 轉移到 iPhone?

也許您升級到最新的 iPhone 型號&#xff0c;或者需要切換到另一部 iPhone 來工作。無論如何&#xff0c;您不能錯過您的聯系人&#xff0c;這對每個人來說都是最重要的數據。因此&#xff0c;今天我們將分享 5 種如何將聯系人從 iPhone 轉移到 iPhone 的方法&#xff0c;幫助您…

【51單片機簡單的流水燈程序問題】2022-5-24

1.利用單片機的P2口接8個發光二極管。簡單的流水燈程序問題-編程語言-CSDN問答 2&#xff0e;發光二極管自由閃爍&#xff08;自己設計兩種模式&#xff09;。 3&#xff0e;可通過按鍵實現暫停、啟動以及不用模式的切換。 4. 利用Proteus繪制電路原理圖 5. 元件選型&#xff1…