用户3096723
用户3096723
  • 发布:2026-07-23 11:37
  • 更新:2026-07-23 11:37
  • 阅读:15

如何实现键盘上方自定义工具栏

分类:uni-app x

问题现象
跟随键盘的工具栏如何实现?

背景知识
自定义弹窗(CustomDialog):通过CustomDialogController类显示自定义弹窗。使用弹窗组件时,优先考虑自定义弹窗,便于弹窗样式与内容的自定义。
defaultFocus:设置当前组件是否为当前页面上的默认焦点。
on('keyboardHeightChange'):开启固定态软键盘高度变化的监听,当软键盘由本窗口唤出并存在重叠区域时通知键盘高度变化。
Stack:堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。
alignContent:设置子组件在容器内的对齐方式。该属性与通用属性align同时设置时,后设置的属性生效。
解决方案
针对跟随键盘的工具栏,可采用以下两种实现方案:

方案一:使用CustomDialog组件自定义工具栏。以下示例通过点击文本组件使弹窗自动获焦,设置弹窗从底部弹出,并为弹窗添加弹出与关闭时的过渡动画,以实现跟随键盘的动画效果。
// 自定义对话框组件,用于显示输入框
@CustomDialog
@Component
export struct Dialog {
dialogController: CustomDialogController;

build() {
Column() {
TextInput({ text: '', placeholder: 'input your word...' })
.type(InputType.Normal)
.defaultFocus(true) // 设置为默认聚焦状态
.onBlur(() => {
// 输入框失去焦点时关闭对话框
this.dialogController.close();
})
.height('50%')
.margin({ top: 25, left: 16, right: 16 });
}
.height(100)
.backgroundColor(Color.White);
}
}

@Entry
@Component
struct Index {
message: string = 'Hello World';
// 自定义对话框控制器,配置对话框的显示参数
customDialogController: CustomDialogController = new CustomDialogController({
builder: Dialog(), // 设置对话框内容组件
alignment: DialogAlignment.Bottom, // 对话框从底部弹出
cornerRadius: 0,
customStyle: true,
openAnimation: { duration: 0.001, tempo: 0 }, // 打开弹窗时动画设置
closeAnimation: { duration: 0.001, tempo: 0 }, // 关闭弹窗时动画设置
});

build() {
Column() {
// 点击按钮打开对话框
Text(this.message)
.onClick(() => {
this.customDialogController.open(); // 触发对话框显示
})
.id('HelloWorld')
.fontSize(50)
.fontWeight(FontWeight.Bold);
}
.height('100%')
.width('100%');
}
}
效果预览:

点击放大

方案二:自定义工具栏组件,借助堆叠容器Stack进行页面布局,将组件设置为底部横向居中。定义状态变量isVisible以控制自定义工具栏的显示与隐藏:在TextInput组件聚焦时显示,失焦时隐藏。同时,通过on('keyboardHeightChange')方法监听软键盘高度变化,依据键盘高度动态调整自定义工具栏的位置,使其紧贴于键盘上方。
import { window } from '@kit.ArkUI';

@Entry
@Component
struct Index {
message: string = '图文信息区域';
// 控制自定义工具栏组件可见性
@State isVisible: Visibility = Visibility.Hidden;
// 存储键盘高度信息
@State keyboardHeight: string = '0px';
controller: RichEditorController = new RichEditorController();

// 页面加载时监听键盘高度变化
aboutToAppear(): void {
window.getLastWindow(this.getUIContext().getHostContext()).then((win) => {
win.on('keyboardHeightChange', (height) => {
console.info('height' + height.toString());
if (height) {
this.keyboardHeight = height.toString() + 'px'; // 保存键盘高度
this.isVisible = Visibility.Visible; // 显示自定义组件
} else {
this.isVisible = Visibility.Hidden; // 隐藏自定义组件
}
});
});
}

build() {
// 使用Stack布局,底部对齐
Stack({ alignContent: Alignment.Bottom }) {
Column() {
Text(this.message)
.fontSize(52)
.height('90%')
.width('100%')
.textAlign(TextAlign.Center)
.fontColor(Color.Black);
// 操作按钮行
Row() {
Text('点击拉起键盘')
.fontColor(Color.White)
.width('90%')
.height('40')
.backgroundColor('#ff1a73f8')
.borderRadius(20)
.textAlign(TextAlign.Center)
.margin({ left: 16, right: 16 })
.onClick(() => {
this.isVisible = Visibility.Visible; // 显示自定义组件
setTimeout(() => {
focusControl.requestFocus('textArea'); // 焦点切换到输入框
}, 10);
});
}.height('10%').width('100%');
}
.expandSafeArea([SafeAreaType.KEYBOARD], [SafeAreaEdge.BOTTOM]); // 适配键盘区域

  // 遮罩层(点击隐藏自定义)  
  Column()  
    .width('100%')  
    .height('120%')  
    .opacity(0.5)  
    .backgroundColor('rgba(0,0,0,0.5)')  
    .onClick(() => {  
      this.isVisible = Visibility.Hidden; // 隐藏自定义组件  
    })  
    .visibility(this.isVisible)  
    .expandSafeArea([SafeAreaType.KEYBOARD], [SafeAreaEdge.BOTTOM, SafeAreaEdge.TOP]);  
  // 动态加载自定义组件  
  CommentComponent({ isVisible: this.isVisible, keyboardHeight: this.keyboardHeight });  
};  

}

// 页面卸载时隐藏自定义组件
aboutToDisappear(): void {
this.isVisible = Visibility.Hidden;
}
}

// 自定义工具栏组件
@Component
struct CommentComponent {
controller: RichEditorController = new RichEditorController();
@Link isVisible: Visibility;
@Link keyboardHeight: string;

build() {
Flex({ direction: FlexDirection.ColumnReverse, justifyContent: FlexAlign.Start, alignItems: ItemAlign.Stretch }) {
Row() {
RichEditor({ controller: this.controller })
.id('textArea') // 设置输入框ID用于焦点控制
.placeholder('喜欢就评论一下吧~', { fontColor: Color.Gray, font: { size: 16, weight: FontWeight.Normal } })
.width('65%');
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.End, alignItems: ItemAlign.Stretch }) {
Image($r('app.media.startIcon')).height(20).constraintSize({ minWidth: 20, maxWidth: 20 });
}
.width(110);
}
.margin({
top: 10,
bottom: this.keyboardHeight, // 根据键盘高度设置动态调整底部边距
left: 10,
right: 10
})
.border({ width: 1 })
.borderRadius(50);
}
.width('100%')
.height(380)
.expandSafeArea([SafeAreaType.KEYBOARD], [SafeAreaEdge.BOTTOM, SafeAreaEdge.TOP]) // 适配键盘区域
.backgroundColor(Color.White)
.visibility(this.isVisible);
}
}
https://pastebin.com/6KBPeVqL
https://pastebin.com/bN1ddiZp
https://pastebin.com/gtYW43NW
https://pastebin.com/eJcix7ad
https://pastebin.com/HcrRQFtA
https://pastebin.com/XgyPuxHD
https://pastebin.com/263D2tG3
https://pastebin.com/VFXnShya
https://pastebin.com/JcCfedC7
https://pastebin.com/XgiWLKtb
https://pastebin.com/SnA9AdtL
https://pastebin.com/gXXg0rwX
https://pastebin.com/6JGUtchA
https://pastebin.com/ZbTwd0Ua
https://pastebin.com/0s559jyS
https://pastebin.com/FF4bCbp7
https://pastebin.com/rbJciCS7
https://pastebin.com/fMBrbeYx
https://pastebin.com/3ZzHtZqE
https://pastebin.com/xgZc6Wpx
https://pastebin.com/q9MHz0sP
https://pastebin.com/7BGqgqgb
https://pastebin.com/762Emz0H
https://pastebin.com/KS7UgY63
https://pastebin.com/E0CUmHyN
https://pastebin.com/RaxmNbrv
https://pastebin.com/sWGhM2xB
https://pastebin.com/q4USiCDw
https://pastebin.com/XBjfa0Jv
https://pastebin.com/5R6CQqw3
https://pastebin.com/Q7C1fgyH
https://pastebin.com/fBtA7KM6
https://pastebin.com/dZHaQ1uQ
https://pastebin.com/YEKBNnfc
https://pastebin.com/T3fNdkNE
https://pastebin.com/r2YxuAHc
https://pastebin.com/Y1Fzshsu
https://pastebin.com/KJvxU2vN
https://pastebin.com/57egjdLv
https://pastebin.com/VxNKdCta
https://pastebin.com/3YsNKCSd
https://pastebin.com/Wk06JeP9
https://pastebin.com/T2pGjSNZ
https://pastebin.com/M0kVVxRE
https://pastebin.com/7kAYYh9u
https://pastebin.com/uiKRsuLh
https://pastebin.com/XLg7wEiV
https://pastebin.com/Uk7dPXfC
https://pastebin.com/HXaxi2bh
https://pastebin.com/2stztMET
https://pastebin.com/RxKisB4V
https://pastebin.com/ig8KqDGg
https://pastebin.com/cRQ0yb3J
https://pastebin.com/4hR7SdmD
https://pastebin.com/EwmMgWdr
https://pastebin.com/4b5AFeRk
https://pastebin.com/3CFxLac5
https://pastebin.com/mKn2fjXp
https://pastebin.com/BSa8L13Z
https://pastebin.com/NAtqrReY
https://pastebin.com/34KDinEG
https://pastebin.com/YaXZqyZQ
https://pastebin.com/j2MhC6kw
https://pastebin.com/c1n5dn5T
https://pastebin.com/weATT6j7
https://pastebin.com/zV5bp85z
https://pastebin.com/isfmyWk7
https://pastebin.com/S86UAeMg
https://pastebin.com/XkUgvZQW
https://pastebin.com/v9j6jg3T
https://pastebin.com/3ip0M9T8
https://pastebin.com/W9c1w8Xb
https://pastebin.com/jtcypgTt
https://pastebin.com/tgPhxe2L
https://pastebin.com/bs9jzpuL
https://pastebin.com/W8sLLPtk
https://pastebin.com/gJTGQYCL
https://pastebin.com/Qh2u2nkn
https://pastebin.com/EPEHmxwS
https://pastebin.com/y41haJUr
https://pastebin.com/J6cevDf0
https://pastebin.com/24RSFBR0
https://pastebin.com/KZsSaA18
https://pastebin.com/21egpH32
https://pastebin.com/wDziwJnn
https://pastebin.com/QeQvkA9r
https://pastebin.com/icJRn8VJ
https://pastebin.com/WsvP4LwZ
https://pastebin.com/H8nZikEJ
https://pastebin.com/rn2gyWiP
https://pastebin.com/tfehkve3
https://pastebin.com/kn7dX8Fh
https://pastebin.com/Dn1ZfNEV
https://pastebin.com/yy811Lis
https://pastebin.com/QcqL3CXH
https://pastebin.com/QbMe6xXP
https://pastebin.com/NpR2Ra0H
https://pastebin.com/DeevkS6j
https://pastebin.com/yhumdvyC
https://pastebin.com/mHjSzVib
https://pastebin.com/F2wyRKNJ
https://pastebin.com/cc96TLXV
https://pastebin.com/2U1qwTrS
https://pastebin.com/n6hYfTdQ
https://pastebin.com/rhAFXjq6
https://pastebin.com/Hmj59VVm
https://pastebin.com/YmrAxXMU
https://pastebin.com/JBF9n5PL
https://pastebin.com/f21MNNJt
https://pastebin.com/D1hn89Qa
https://pastebin.com/xqdaxD0A
https://pastebin.com/tm2zPQbn
https://pastebin.com/8j3PBMNW
https://pastebin.com/3LcqrmTu
https://pastebin.com/GY4abWzw
https://pastebin.com/9LnRRWuk
https://pastebin.com/N5HJByTK
https://pastebin.com/aaSvnC3j
https://pastebin.com/UYFUHSWk
https://pastebin.com/fcvPwAqU
https://pastebin.com/fS9cgSGG
https://pastebin.com/NP5mQWhJ
https://pastebin.com/em54RVwp
https://pastebin.com/FhSzXrRD
https://pastebin.com/EaU2AmjN
https://pastebin.com/86fScibj
https://pastebin.com/rgPcewwp
https://pastebin.com/FAhu2G96
https://pastebin.com/fU6un6pq
https://pastebin.com/Fmpvt6K9
https://pastebin.com/DMJHzHuW
https://pastebin.com/F39T4W12
https://pastebin.com/9wGgKwMC
https://pastebin.com/xJXUSDnS
https://pastebin.com/FqUGuWTV
https://pastebin.com/Z3ppjriB
https://pastebin.com/A2AQwvEd
https://pastebin.com/tqBWPMe7
https://pastebin.com/LQ3LFEHs
https://pastebin.com/qgkbKhDs
https://pastebin.com/vNvhLWpB
https://pastebin.com/BYu5Twtq
https://pastebin.com/9MapWu1K
https://pastebin.com/DUS2V33c
https://pastebin.com/WSuFmrmW
https://pastebin.com/vKwBpE8f
https://pastebin.com/ARLCtkJy
https://pastebin.com/R0eRbYXX
https://pastebin.com/vzusjTqP
https://pastebin.com/6xQWzuPp
https://pastebin.com/XZsLs6N3
https://pastebin.com/ccCGb1c1
https://pastebin.com/GbxBPVJ6
https://pastebin.com/c6rWM7yT
https://pastebin.com/0fhv7SWU
https://pastebin.com/LCXSxwqu
https://pastebin.com/UKiEaw1b
https://pastebin.com/rR7WFgRd
https://pastebin.com/GMr8Uit3
https://pastebin.com/EeUAEUzt
https://pastebin.com/iMdgtEvx
https://pastebin.com/M54w1AB8
https://pastebin.com/NBenUCdx
https://pastebin.com/gcYXCccc
https://pastebin.com/VKbbyQWT
https://pastebin.com/AjjbCsHT
https://pastebin.com/95MGXGGW
https://pastebin.com/MGSQGvHt
https://pastebin.com/8vVDgwEX
https://pastebin.com/xg8NhUUu
https://pastebin.com/ejAPdK9h
https://pastebin.com/HC44DqUE
https://pastebin.com/AAERa624
https://pastebin.com/TrqEhKJ0
https://pastebin.com/PhRqJLQH
https://pastebin.com/s10g8uCx
https://pastebin.com/a3RKhwkq
https://pastebin.com/PEsA2ngB

0 关注 分享

要回复文章请先登录注册