Flutter 再论编辑器的键盘处理
·3 min read
Flutter 编辑器键盘处理
简介
| 不能说终极版吧 | 比网易,讯飞AI 的编辑器处理得更好
主要逻辑
// 这里差点意思,不能和屏幕刷新同频,不太自然
// 最好还是借助 animation 来处理,但互相干扰,处理比较麻烦
// menubar 滑入
void slideinMenubar(int x) {
double m = maxToolbarHeight ?? ui.windowHeight * 0.382;
toolbarHeight = toolbarHeight + x;
if (toolbarHeight>=m-10) {
toolbarHeight = m;
setStatus();
}
else {
setStatus();
Future.delayed(const Duration(milliseconds: 1), (){
slideinMenubar(x);
});
}
}
// menubar 滑出
void slideoutMenubar(int x) {
toolbarHeight = toolbarHeight - x;
if (toolbarHeight<=10) {
toolbarHeight = 0;
setStatus();
}
else {
setStatus();
Future.delayed(const Duration(milliseconds: 1), (){
slideoutMenubar(x);
});
}
}
// 切换 menuLabel
void changeMenuLabel(BuildContext context, int choiceMenuLabel) {
currentMenuLabel = choiceMenuLabel;
// 菜单在底部
if (toolbarHeight<=0) {
isLockKeyboardBottom = selectedMenuLabel= true;
slideinMenubar(10);
}
// 菜单已弹起
else {
isLockKeyboardBottom = true;
selectedMenuLabel = false;
SystemChannels.textInput.invokeMethod<void>(
keyboardHeight<=0 ? 'TextInput.show' : 'TextInput.hide'
);
}
setStatus();
}
// 切换 返回
void onPopInvoked<T>(bool didPop, T? result) {
// 键盘&菜单在底部
if (toolbarHeight<=0) {
if (!didPop) {
saveThenExit();
}
}
// 键盘在底部, 菜单弹起
else if(keyboardHeight<=0) {
isLockKeyboardBottom = selectedMenuLabel = false;
setStatus();
slideoutMenubar(10);
}
// 键盘弹起, 菜单弹起
else {
isLockKeyboardBottom = false;
SystemChannels.textInput.invokeMethod<void>('TextInput.hide');
}
}
Duration? frameCallTime;
double lastKeyboardHeight = 0;
BuildContext? editContext;
void frameCallback(Duration callTime) {
if (editContext==null || (frameCallTime!=null && frameCallTime!.compareTo(callTime)==0)) {
return;
}
keyboardHeight = MediaQuery.of(editContext!).viewInsets.bottom;
// show begin
if (keyboardHeight > lastKeyboardHeight && lastKeyboardHeight <= 0) {
keyboardStatus = KeyboardStatus.showing;
selectedMenuLabel = false;
Future.delayed(const Duration(milliseconds: 270), (){
keyboardStatus = KeyboardStatus.show;
isLockKeyboardBottom = selectedMenuLabel = false;
toolbarHeight = keyboardHeight;
cacheMaxToolbarHeight(keyboardHeight);
setStatus();
});
}
// hide end
else if (keyboardHeight <= 0 && keyboardHeight < lastKeyboardHeight) {
keyboardStatus = KeyboardStatus.hide;
// 键盘在底部,说明是为了展示子菜单
selectedMenuLabel = isLockKeyboardBottom;
}
// 剩下的就是 hiding 和 sliding ( 软键盘切换形态使得高度变化 ) 了
else {
keyboardStatus = KeyboardStatus.sliding;
}
if (isLockKeyboardBottom==false || toolbarHeight<keyboardHeight) {
toolbarHeight = keyboardHeight;
}
lastKeyboardHeight = keyboardHeight;
frameCallTime = callTime;
setStatus();
}