键盘添加撤销操作
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#import <MJExtension/MJExtension.h>
|
||||
#import "KBBizCode.h"
|
||||
#import "KBBackspaceLongPressHandler.h"
|
||||
#import "KBBackspaceUndoManager.h"
|
||||
|
||||
@interface KBFunctionView () <KBFunctionBarViewDelegate, KBStreamOverlayViewDelegate, KBFunctionTagListViewDelegate>
|
||||
// UI
|
||||
@@ -769,6 +770,7 @@ static void KBULDarwinCallback(CFNotificationCenterRef center, void *observer, C
|
||||
}
|
||||
- (void)onTapDelete {
|
||||
NSLog(@"点击:删除");
|
||||
[[KBBackspaceUndoManager shared] registerNonClearAction];
|
||||
UIInputViewController *ivc = KBFindInputViewController(self);
|
||||
id<UITextDocumentProxy> proxy = ivc.textDocumentProxy;
|
||||
[proxy deleteBackward];
|
||||
@@ -779,6 +781,7 @@ static void KBULDarwinCallback(CFNotificationCenterRef center, void *observer, C
|
||||
}
|
||||
- (void)onTapSend {
|
||||
NSLog(@"点击:发送");
|
||||
[[KBBackspaceUndoManager shared] registerNonClearAction];
|
||||
// 发送:插入换行。大多数聊天类 App 会把回车视为“发送”
|
||||
UIInputViewController *ivc = KBFindInputViewController(self);
|
||||
id<UITextDocumentProxy> proxy = ivc.textDocumentProxy;
|
||||
|
||||
@@ -23,6 +23,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// 点击了右侧设置按钮
|
||||
- (void)keyBoardMainViewDidTapSettings:(KBKeyBoardMainView *)keyBoardMainView;
|
||||
/// 点击了撤销删除按钮
|
||||
- (void)keyBoardMainViewDidTapUndo:(KBKeyBoardMainView *)keyBoardMainView;
|
||||
|
||||
/// emoji 视图里选择了一个表情
|
||||
- (void)keyBoardMainView:(KBKeyBoardMainView *)keyBoardMainView didSelectEmoji:(NSString *)emoji;
|
||||
|
||||
@@ -115,6 +115,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)toolBarDidTapUndo:(KBToolBar *)toolBar {
|
||||
if ([self.delegate respondsToSelector:@selector(keyBoardMainViewDidTapUndo:)]) {
|
||||
[self.delegate keyBoardMainViewDidTapUndo:self];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - KBKeyboardViewDelegate
|
||||
|
||||
- (void)keyboardView:(KBKeyboardView *)keyboard didTapKey:(KBKey *)key {
|
||||
|
||||
@@ -17,6 +17,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (void)toolBar:(KBToolBar *)toolBar didTapActionAtIndex:(NSInteger)index;
|
||||
/// 右侧设置按钮点击
|
||||
- (void)toolBarDidTapSettings:(KBToolBar *)toolBar;
|
||||
/// 右侧撤销删除按钮点击
|
||||
- (void)toolBarDidTapUndo:(KBToolBar *)toolBar;
|
||||
@end
|
||||
|
||||
/// 顶部工具栏:左侧 4 个按钮,右侧 1 个设置按钮。
|
||||
@@ -30,6 +32,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/// 暴露按钮以便外部定制(只读;首次访问时懒加载创建)
|
||||
@property (nonatomic, strong, readonly) NSArray<UIButton *> *leftButtons;
|
||||
@property (nonatomic, strong, readonly) UIButton *settingsButton;
|
||||
@property (nonatomic, strong, readonly) UIButton *undoButton;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -7,12 +7,16 @@
|
||||
|
||||
#import "KBToolBar.h"
|
||||
#import "KBResponderUtils.h" // 查找 UIInputViewController,用于系统切换输入法
|
||||
#import "KBBackspaceUndoManager.h"
|
||||
|
||||
@interface KBToolBar ()
|
||||
@property (nonatomic, strong) UIView *leftContainer;
|
||||
@property (nonatomic, strong) NSArray<UIButton *> *leftButtonsInternal;
|
||||
//@property (nonatomic, strong) UIButton *settingsButtonInternal;
|
||||
@property (nonatomic, strong) UIButton *globeButtonInternal; // 可选:系统“切换输入法”键
|
||||
@property (nonatomic, strong) UIButton *undoButtonInternal; // 右侧撤销删除
|
||||
@property (nonatomic, assign) BOOL kbNeedsInputModeSwitchKey;
|
||||
@property (nonatomic, assign) BOOL kbUndoVisible;
|
||||
@end
|
||||
|
||||
@implementation KBToolBar
|
||||
@@ -22,10 +26,18 @@
|
||||
self.backgroundColor = [UIColor clearColor];
|
||||
_leftButtonTitles = @[KBLocalized(@"Recharge Now")]; // 默认标题
|
||||
[self setupUI];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(kb_undoStateChanged)
|
||||
name:KBBackspaceUndoStateDidChangeNotification
|
||||
object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Public
|
||||
|
||||
@@ -33,6 +45,10 @@
|
||||
return self.leftButtonsInternal;
|
||||
}
|
||||
|
||||
- (UIButton *)undoButton {
|
||||
return self.undoButtonInternal;
|
||||
}
|
||||
|
||||
//- (UIButton *)settingsButton {
|
||||
// return self.settingsButtonInternal;
|
||||
//}
|
||||
@@ -53,6 +69,7 @@
|
||||
[self addSubview:self.leftContainer];
|
||||
// [self addSubview:self.settingsButtonInternal];
|
||||
[self addSubview:self.globeButtonInternal];
|
||||
[self addSubview:self.undoButtonInternal];
|
||||
|
||||
// 右侧设置按钮
|
||||
// [self.settingsButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
@@ -68,14 +85,15 @@
|
||||
make.width.height.mas_equalTo(32);
|
||||
}];
|
||||
|
||||
// 左侧容器占用剩余空间
|
||||
[self.leftContainer mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.globeButtonInternal.mas_right).offset(8);
|
||||
make.right.equalTo(self).offset(-12);
|
||||
// 右侧撤销按钮
|
||||
[self.undoButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.right.equalTo(self.mas_right).offset(-12);
|
||||
make.centerY.equalTo(self.mas_centerY);
|
||||
make.height.mas_equalTo(32);
|
||||
}];
|
||||
|
||||
[self kb_updateLeftContainerConstraints];
|
||||
|
||||
// 在左侧容器中创建按钮(数量 = 标题数量)
|
||||
NSMutableArray<UIButton *> *buttons = [NSMutableArray arrayWithCapacity:_leftButtonTitles.count];
|
||||
UIView *previous = nil;
|
||||
@@ -110,6 +128,7 @@
|
||||
|
||||
// 初始刷新地球键的可见性与事件绑定
|
||||
[self kb_refreshGlobeVisibility];
|
||||
[self kb_updateUndoVisibilityAnimated:NO];
|
||||
}
|
||||
|
||||
- (UIButton *)buildActionButtonAtIndex:(NSInteger)idx {
|
||||
@@ -147,6 +166,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)onUndo {
|
||||
if ([self.delegate respondsToSelector:@selector(toolBarDidTapUndo:)]) {
|
||||
[self.delegate toolBarDidTapUndo:self];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Lazy
|
||||
|
||||
- (UIView *)leftContainer {
|
||||
@@ -182,6 +207,23 @@
|
||||
return _globeButtonInternal;
|
||||
}
|
||||
|
||||
- (UIButton *)undoButtonInternal {
|
||||
if (!_undoButtonInternal) {
|
||||
_undoButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem];
|
||||
_undoButtonInternal.layer.cornerRadius = 16;
|
||||
_undoButtonInternal.layer.masksToBounds = YES;
|
||||
_undoButtonInternal.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9];
|
||||
_undoButtonInternal.titleLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium];
|
||||
[_undoButtonInternal setTitle:@"撤销删除" forState:UIControlStateNormal];
|
||||
[_undoButtonInternal setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
|
||||
_undoButtonInternal.contentEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 10);
|
||||
_undoButtonInternal.hidden = YES;
|
||||
_undoButtonInternal.alpha = 0.0;
|
||||
[_undoButtonInternal addTarget:self action:@selector(onUndo) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
return _undoButtonInternal;
|
||||
}
|
||||
|
||||
#pragma mark - Globe (Input Mode Switch)
|
||||
|
||||
// 根据宿主是否已提供系统切换键,决定是否显示地球按钮;并绑定系统事件。
|
||||
@@ -193,18 +235,9 @@
|
||||
}
|
||||
|
||||
self.globeButtonInternal.hidden = !needSwitchKey;
|
||||
self.kbNeedsInputModeSwitchKey = needSwitchKey;
|
||||
|
||||
// 重新调整 leftContainer 的左约束:若不需要地球键,则贴左边距 12
|
||||
[self.leftContainer mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
if (needSwitchKey) {
|
||||
make.left.equalTo(self.globeButtonInternal.mas_right).offset(8);
|
||||
} else {
|
||||
make.left.equalTo(self.mas_left).offset(12);
|
||||
}
|
||||
make.right.equalTo(self).offset(-12);
|
||||
make.centerY.equalTo(self.mas_centerY);
|
||||
make.height.mas_equalTo(32);
|
||||
}];
|
||||
[self kb_updateLeftContainerConstraints];
|
||||
|
||||
// 绑定系统提供的输入法切换处理(点按切换、长按弹出列表)
|
||||
// 仅在需要时绑定,避免多余的事件转发
|
||||
@@ -220,6 +253,54 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)kb_updateLeftContainerConstraints {
|
||||
[self.leftContainer mas_remakeConstraints:^(MASConstraintMaker *make) {
|
||||
if (self.kbNeedsInputModeSwitchKey) {
|
||||
make.left.equalTo(self.globeButtonInternal.mas_right).offset(8);
|
||||
} else {
|
||||
make.left.equalTo(self.mas_left).offset(12);
|
||||
}
|
||||
if (self.kbUndoVisible) {
|
||||
make.right.equalTo(self.undoButtonInternal.mas_left).offset(-8);
|
||||
} else {
|
||||
make.right.equalTo(self).offset(-12);
|
||||
}
|
||||
make.centerY.equalTo(self.mas_centerY);
|
||||
make.height.mas_equalTo(32);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)kb_undoStateChanged {
|
||||
[self kb_updateUndoVisibilityAnimated:YES];
|
||||
}
|
||||
|
||||
- (void)kb_updateUndoVisibilityAnimated:(BOOL)animated {
|
||||
BOOL visible = [KBBackspaceUndoManager shared].hasUndo;
|
||||
if (self.kbUndoVisible == visible) { return; }
|
||||
self.kbUndoVisible = visible;
|
||||
self.undoButtonInternal.hidden = NO;
|
||||
|
||||
[self kb_updateLeftContainerConstraints];
|
||||
void (^changes)(void) = ^{
|
||||
self.undoButtonInternal.alpha = visible ? 1.0 : 0.0;
|
||||
[self layoutIfNeeded];
|
||||
};
|
||||
void (^finish)(BOOL) = ^(BOOL finished) {
|
||||
self.undoButtonInternal.hidden = !visible;
|
||||
};
|
||||
|
||||
if (animated) {
|
||||
[UIView animateWithDuration:0.18
|
||||
delay:0
|
||||
options:UIViewAnimationOptionCurveEaseInOut
|
||||
animations:changes
|
||||
completion:finish];
|
||||
} else {
|
||||
changes();
|
||||
finish(YES);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didMoveToWindow {
|
||||
[super didMoveToWindow];
|
||||
[self kb_refreshGlobeVisibility];
|
||||
|
||||
Reference in New Issue
Block a user