diff --git a/CustomKeyboard/KeyboardViewController.m b/CustomKeyboard/KeyboardViewController.m index e018f82..91832a5 100644 --- a/CustomKeyboard/KeyboardViewController.m +++ b/CustomKeyboard/KeyboardViewController.m @@ -28,27 +28,12 @@ static CGFloat KEYBOARDHEIGHT = 256; - (void)viewDidLoad { [super viewDidLoad]; -// -// // Perform custom UI setup here -// self.nextKeyboardButton = [UIButton buttonWithType:UIButtonTypeSystem]; -// -// [self.nextKeyboardButton setTitle:NSLocalizedString(@"Next Keyboard", @"Title for 'Next Keyboard' button") forState:UIControlStateNormal]; -// [self.nextKeyboardButton sizeToFit]; -// self.nextKeyboardButton.translatesAutoresizingMaskIntoConstraints = NO; -// -// [self.nextKeyboardButton addTarget:self action:@selector(handleInputModeListFromView:withEvent:) forControlEvents:UIControlEventAllTouchEvents]; -// -// [self.view addSubview:self.nextKeyboardButton]; -// -// [self.nextKeyboardButton.leftAnchor constraintEqualToAnchor:self.view.leftAnchor].active = YES; -// [self.nextKeyboardButton.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor].active = YES; [self setupUI]; } - (void)setupUI { -// self.view.translatesAutoresizingMaskIntoConstraints = NO; // 固定键盘整体高度 [self.view.heightAnchor constraintEqualToConstant:KEYBOARDHEIGHT].active = YES; @@ -74,38 +59,15 @@ static CGFloat KEYBOARDHEIGHT = 256; } -- (void)viewWillLayoutSubviews -{ - self.nextKeyboardButton.hidden = !self.needsInputModeSwitchKey; - [super viewWillLayoutSubviews]; -} - -- (void)textWillChange:(id)textInput { - // 文档内容即将变化,可在此做准备 -} - -- (void)textDidChange:(id)textInput { - // 文档内容刚发生变化,环境已更新 - - UIColor *textColor = nil; - if (self.textDocumentProxy.keyboardAppearance == UIKeyboardAppearanceDark) { - textColor = [UIColor whiteColor]; - } else { - textColor = [UIColor blackColor]; - } - [self.nextKeyboardButton setTitleColor:textColor forState:UIControlStateNormal]; -} - #pragma mark - KBToolBarDelegate - (void)toolBar:(KBToolBar *)toolBar didTapActionAtIndex:(NSInteger)index { // 可根据业务透传或处理。示例:插入占位标记 [A1]..[A4] - NSString *placeholder = [NSString stringWithFormat:@"[A%ld]", (long)index+1]; - [self.textDocumentProxy insertText:placeholder]; +// NSString *placeholder = [NSString stringWithFormat:@"[A%ld]", (long)index+1]; + } - (void)toolBarDidTapSettings:(KBToolBar *)toolBar { - // 通常可通过 openURL 或宿主处理打开设置页。 // 这里示例仅插入一个标记。 [self.textDocumentProxy insertText:@"[settings]"]; } diff --git a/CustomKeyboard/View/KBFunctionBarView.h b/CustomKeyboard/View/KBFunctionBarView.h new file mode 100644 index 0000000..ef6e1a8 --- /dev/null +++ b/CustomKeyboard/View/KBFunctionBarView.h @@ -0,0 +1,27 @@ +// +// KBFunctionBarView.h +// CustomKeyboard +// +// Created by Mac on 2025/10/28. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// 功能区顶部的Bar:左侧4个按钮,右侧3个按钮 +@interface KBFunctionBarView : UIView + +/// 左侧4个按钮(懒加载创建,等宽水平排布) +@property (nonatomic, strong, readonly) NSArray *leftButtons; + +/// 右侧3个按钮(懒加载创建,等宽水平排布,靠右) +@property (nonatomic, strong, readonly) NSArray *rightButtons; + +/// 配置按钮标题(可选) +@property (nonatomic, copy) NSArray *leftTitles; // 默认 @[@"帮回", @"会说", @"话术", @"更多"] +@property (nonatomic, copy) NSArray *rightTitles; // 默认 @[@"❤", @"收藏", @"宫格"] + +@end + +NS_ASSUME_NONNULL_END diff --git a/CustomKeyboard/View/KBFunctionBarView.m b/CustomKeyboard/View/KBFunctionBarView.m new file mode 100644 index 0000000..316fdc1 --- /dev/null +++ b/CustomKeyboard/View/KBFunctionBarView.m @@ -0,0 +1,142 @@ +// +// KBFunctionBarView.m +// CustomKeyboard +// +// Created by Mac on 2025/10/28. +// 功能 - barview + +#import "KBFunctionBarView.h" +#import "Masonry.h" + +@interface KBFunctionBarView () +@property (nonatomic, strong) UIView *leftContainer; // 左侧按钮容器 +@property (nonatomic, strong) UIView *rightContainer; // 右侧按钮容器 +@property (nonatomic, strong) NSArray *leftButtonsInternal; +@property (nonatomic, strong) NSArray *rightButtonsInternal; +@end + +@implementation KBFunctionBarView + +- (instancetype)initWithFrame:(CGRect)frame{ + if (self = [super initWithFrame:frame]) { + self.backgroundColor = [UIColor clearColor]; + _leftTitles = @[@"帮回", @"会说", @"话术", @"更多"]; + _rightTitles = @[@"❤", @"收藏", @"宫格"]; + [self buildUI]; + } + return self; +} + +#pragma mark - Public + +- (NSArray *)leftButtons { return self.leftButtonsInternal; } +- (NSArray *)rightButtons { return self.rightButtonsInternal; } + + +#pragma mark - UI + +- (void)buildUI { + // 左右两个容器,方便分别布局 + [self addSubview:self.leftContainer]; + [self addSubview:self.rightContainer]; + + [self.rightContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.mas_right).offset(-12); + make.centerY.equalTo(self.mas_centerY); + make.height.mas_equalTo(36); + }]; + + [self.leftContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.mas_left).offset(12); + make.right.equalTo(self.rightContainer.mas_left).offset(-12); + make.centerY.equalTo(self.mas_centerY); + make.height.mas_equalTo(36); + }]; + + // 左侧4个等宽按钮 + NSMutableArray *leftBtns = [NSMutableArray arrayWithCapacity:4]; + UIView *prev = nil; + for (NSInteger i = 0; i < 4; i++) { + UIButton *btn = [self buildButtonWithTitle:(i < self.leftTitles.count ? self.leftTitles[i] : [NSString stringWithFormat:@"L%ld", (long)i])]; + btn.tag = 100 + i; + [self.leftContainer addSubview:btn]; + [btn mas_makeConstraints:^(MASConstraintMaker *make) { + if (prev) { + make.left.equalTo(prev.mas_right).offset(8); + make.width.equalTo(prev); + } else { + make.left.equalTo(self.leftContainer.mas_left); + } + make.top.bottom.equalTo(self.leftContainer); + }]; + prev = btn; + [leftBtns addObject:btn]; + } + [prev mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.leftContainer.mas_right); + }]; + self.leftButtonsInternal = leftBtns.copy; + + // 右侧3个等宽按钮(靠右) + NSMutableArray *rightBtns = [NSMutableArray arrayWithCapacity:3]; + UIView *next = nil; + for (NSInteger i = 0; i < 3; i++) { + UIButton *btn = [self buildButtonWithTitle:(i < self.rightTitles.count ? self.rightTitles[i] : [NSString stringWithFormat:@"R%ld", (long)i])]; + btn.tag = 200 + i; + [self.rightContainer addSubview:btn]; + [rightBtns addObject:btn]; + } + + // 从右往左排,保证整体靠右 + UIButton *r0 = rightBtns.count > 0 ? rightBtns[0] : nil; + UIButton *r1 = rightBtns.count > 1 ? rightBtns[1] : nil; + UIButton *r2 = rightBtns.count > 2 ? rightBtns[2] : nil; + if (r0 && r1 && r2) { + [r2 mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.rightContainer.mas_right); + make.top.bottom.equalTo(self.rightContainer); + }]; + [r1 mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(r2.mas_left).offset(-8); + make.top.bottom.equalTo(self.rightContainer); + make.width.equalTo(r2); + }]; + [r0 mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(r1.mas_left).offset(-8); + make.top.bottom.equalTo(self.rightContainer); + make.width.equalTo(r1); + make.left.greaterThanOrEqualTo(self.rightContainer.mas_left); // 内容撑开 + }]; + } + + self.rightButtonsInternal = rightBtns.copy; +} + +- (UIButton *)buildButtonWithTitle:(NSString *)title { + UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem]; + btn.layer.cornerRadius = 18; + btn.layer.masksToBounds = YES; + btn.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9]; + btn.titleLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium]; + [btn setTitle:title forState:UIControlStateNormal]; + [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + return btn; +} + +#pragma mark - Lazy + +- (UIView *)leftContainer { + if (!_leftContainer) { + _leftContainer = [[UIView alloc] init]; + } + return _leftContainer; +} + +- (UIView *)rightContainer { + if (!_rightContainer) { + _rightContainer = [[UIView alloc] init]; + } + return _rightContainer; +} + +@end diff --git a/CustomKeyboard/View/KBFunctionPasteView.h b/CustomKeyboard/View/KBFunctionPasteView.h new file mode 100644 index 0000000..c4c5d2b --- /dev/null +++ b/CustomKeyboard/View/KBFunctionPasteView.h @@ -0,0 +1,23 @@ +// +// KBFunctionPasteView.h +// CustomKeyboard +// +// Created by Mac on 2025/10/28. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// 粘贴提示输入框区域(左侧图标+占位文案,圆角白底) +@interface KBFunctionPasteView : UIView + +/// 左侧图标 +@property (nonatomic, strong, readonly) UIImageView *iconView; + +/// 提示文案,例如:点击粘贴TA的话 +@property (nonatomic, strong, readonly) UILabel *placeholderLabel; + +@end + +NS_ASSUME_NONNULL_END diff --git a/CustomKeyboard/View/KBFunctionPasteView.m b/CustomKeyboard/View/KBFunctionPasteView.m new file mode 100644 index 0000000..61caa7b --- /dev/null +++ b/CustomKeyboard/View/KBFunctionPasteView.m @@ -0,0 +1,75 @@ +// +// KBFunctionPasteView.m +// CustomKeyboard +// +// Created by Mac on 2025/10/28. +// 粘贴View + +#import "KBFunctionPasteView.h" +#import "Masonry.h" + +@interface KBFunctionPasteView () +@property (nonatomic, strong) UIImageView *iconViewInternal; +@property (nonatomic, strong) UILabel *placeholderLabelInternal; +@end + +@implementation KBFunctionPasteView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + // 白底圆角容器 + self.backgroundColor = [UIColor colorWithWhite:1 alpha:0.95]; + self.layer.cornerRadius = 12.0; + self.layer.masksToBounds = YES; + + [self addSubview:self.iconViewInternal]; + [self addSubview:self.placeholderLabelInternal]; + + [self.iconViewInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.mas_left).offset(12); + make.centerY.equalTo(self.mas_centerY); + make.width.height.mas_equalTo(20); + }]; + [self.placeholderLabelInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.iconViewInternal.mas_right).offset(8); + make.right.equalTo(self.mas_right).offset(-12); + make.centerY.equalTo(self.mas_centerY); + }]; + } + return self; +} + +#pragma mark - Lazy + +- (UIImageView *)iconViewInternal { + if (!_iconViewInternal) { + _iconViewInternal = [[UIImageView alloc] init]; + // 用简单的系统表情代替资源图(项目可替换成实际图片) + UILabel *emoji = [[UILabel alloc] init]; + emoji.text = @"📋"; // 粘贴/剪贴板含义 + emoji.font = [UIFont systemFontOfSize:18]; + emoji.textAlignment = NSTextAlignmentCenter; + [_iconViewInternal addSubview:emoji]; + [emoji mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(_iconViewInternal); + }]; + } + return _iconViewInternal; +} + +- (UILabel *)placeholderLabelInternal { + if (!_placeholderLabelInternal) { + _placeholderLabelInternal = [[UILabel alloc] init]; + _placeholderLabelInternal.text = @"点击粘贴TA的话"; + _placeholderLabelInternal.textColor = [UIColor colorWithRed:0.20 green:0.64 blue:0.54 alpha:1.0]; + _placeholderLabelInternal.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; + } + return _placeholderLabelInternal; +} + +#pragma mark - Expose + +- (UIImageView *)iconView { return self.iconViewInternal; } +- (UILabel *)placeholderLabel { return self.placeholderLabelInternal; } + +@end diff --git a/CustomKeyboard/View/KBFunctionTagCell.h b/CustomKeyboard/View/KBFunctionTagCell.h new file mode 100644 index 0000000..e4c00f7 --- /dev/null +++ b/CustomKeyboard/View/KBFunctionTagCell.h @@ -0,0 +1,23 @@ +// +// KBFunctionTagCell.h +// CustomKeyboard +// +// Created by Codex on 2025/10/28. +// 话术标签Cell:左图标+右标题,圆角灰白底 + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface KBFunctionTagCell : UICollectionViewCell + +/// 标题 +@property (nonatomic, strong, readonly) UILabel *titleLabel; + +/// 头像/图标 +@property (nonatomic, strong, readonly) UIImageView *iconView; + +@end + +NS_ASSUME_NONNULL_END + diff --git a/CustomKeyboard/View/KBFunctionTagCell.m b/CustomKeyboard/View/KBFunctionTagCell.m new file mode 100644 index 0000000..06df6b3 --- /dev/null +++ b/CustomKeyboard/View/KBFunctionTagCell.m @@ -0,0 +1,73 @@ +// +// KBFunctionTagCell.m +// CustomKeyboard +// +// Created by Codex on 2025/10/28. +// + +#import "KBFunctionTagCell.h" +#import "Masonry.h" + +@interface KBFunctionTagCell () +@property (nonatomic, strong) UILabel *titleLabelInternal; +@property (nonatomic, strong) UIImageView *iconViewInternal; +@end + +@implementation KBFunctionTagCell + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.contentView.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9]; + self.contentView.layer.cornerRadius = 12; + self.contentView.layer.masksToBounds = YES; + + [self.contentView addSubview:self.iconViewInternal]; + [self.contentView addSubview:self.titleLabelInternal]; + + [self.iconViewInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.contentView.mas_left).offset(10); + make.centerY.equalTo(self.contentView.mas_centerY); + make.width.height.mas_equalTo(24); + }]; + [self.titleLabelInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.iconViewInternal.mas_right).offset(6); + make.right.equalTo(self.contentView.mas_right).offset(-10); + make.centerY.equalTo(self.contentView.mas_centerY); + }]; + } + return self; +} + +#pragma mark - Lazy + +- (UIImageView *)iconViewInternal { + if (!_iconViewInternal) { + _iconViewInternal = [[UIImageView alloc] init]; + UILabel *emoji = [[UILabel alloc] init]; + emoji.text = @"🙂"; // 占位图标 + emoji.textAlignment = NSTextAlignmentCenter; + emoji.font = [UIFont systemFontOfSize:20]; + [_iconViewInternal addSubview:emoji]; + [emoji mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(_iconViewInternal); + }]; + } + return _iconViewInternal; +} + +- (UILabel *)titleLabelInternal { + if (!_titleLabelInternal) { + _titleLabelInternal = [[UILabel alloc] init]; + _titleLabelInternal.font = [UIFont systemFontOfSize:15 weight:UIFontWeightSemibold]; + _titleLabelInternal.textColor = [UIColor blackColor]; + } + return _titleLabelInternal; +} + +#pragma mark - Expose + +- (UILabel *)titleLabel { return self.titleLabelInternal; } +- (UIImageView *)iconView { return self.iconViewInternal; } + +@end + diff --git a/CustomKeyboard/View/KBFunctionView.h b/CustomKeyboard/View/KBFunctionView.h new file mode 100644 index 0000000..5f9aea1 --- /dev/null +++ b/CustomKeyboard/View/KBFunctionView.h @@ -0,0 +1,30 @@ +// +// KBFunctionView.h +// CustomKeyboard +// +// Created by Mac on 2025/10/28. +// + +#import +@class KBFunctionBarView, KBFunctionPasteView; + +NS_ASSUME_NONNULL_BEGIN + +/// 整个功能面板视图:顶部Bar + 粘贴区 + 标签列表 + 右侧操作按钮 +@interface KBFunctionView : UIView + +@property (nonatomic, strong, readonly) UICollectionView *collectionView; // 话术分类/标签列表 +@property (nonatomic, strong, readonly) NSArray *items; // 简单数据源(演示用) + +// 子视图暴露,便于外部接入事件 +@property (nonatomic, strong, readonly) KBFunctionBarView *barView; +@property (nonatomic, strong, readonly) KBFunctionPasteView *pasteView; + +@property (nonatomic, strong, readonly) UIButton *pasteButton; // 右侧-粘贴 +@property (nonatomic, strong, readonly) UIButton *deleteButton; // 右侧-删除 +@property (nonatomic, strong, readonly) UIButton *clearButton; // 右侧-清空 +@property (nonatomic, strong, readonly) UIButton *sendButton; // 右侧-发送 + +@end + +NS_ASSUME_NONNULL_END diff --git a/CustomKeyboard/View/KBFunctionView.m b/CustomKeyboard/View/KBFunctionView.m new file mode 100644 index 0000000..8cdcb69 --- /dev/null +++ b/CustomKeyboard/View/KBFunctionView.m @@ -0,0 +1,263 @@ +// +// KBFunctionView.m +// CustomKeyboard +// +// Created by Mac on 2025/10/28. +// + +#import "KBFunctionView.h" +#import "KBFunctionBarView.h" +#import "KBFunctionPasteView.h" +#import "KBFunctionTagCell.h" +#import "Masonry.h" + +static NSString * const kKBFunctionTagCellId = @"KBFunctionTagCellId"; + +@interface KBFunctionView () +// UI +@property (nonatomic, strong) KBFunctionBarView *barViewInternal; +@property (nonatomic, strong) KBFunctionPasteView *pasteViewInternal; +@property (nonatomic, strong) UICollectionView *collectionViewInternal; +@property (nonatomic, strong) UIView *rightButtonContainer; // 右侧竖排按钮容器 +@property (nonatomic, strong) UIButton *pasteButtonInternal; +@property (nonatomic, strong) UIButton *deleteButtonInternal; +@property (nonatomic, strong) UIButton *clearButtonInternal; +@property (nonatomic, strong) UIButton *sendButtonInternal; + +// Data +@property (nonatomic, strong) NSArray *itemsInternal; +@end + +@implementation KBFunctionView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + // 整体绿色背景(接近截图效果,项目可自行替换素材) + self.backgroundColor = [UIColor colorWithRed:0.77 green:0.93 blue:0.82 alpha:1.0]; + + [self setupUI]; + [self reloadDemoData]; + } + return self; +} + +#pragma mark - UI + +- (void)setupUI { + // 1. 顶部 Bar + [self addSubview:self.barViewInternal]; + [self.barViewInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.right.equalTo(self); + make.top.equalTo(self.mas_top).offset(6); + make.height.mas_equalTo(48); + }]; + + // 右侧竖排按钮容器 + [self addSubview:self.rightButtonContainer]; + [self.rightButtonContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.mas_right).offset(-12); + make.top.equalTo(self.barViewInternal.mas_bottom).offset(8); + make.bottom.equalTo(self.mas_bottom).offset(-10); + make.width.mas_equalTo(72); + }]; + + // 右侧四个按钮 + [self.rightButtonContainer addSubview:self.pasteButtonInternal]; + [self.rightButtonContainer addSubview:self.deleteButtonInternal]; + [self.rightButtonContainer addSubview:self.clearButtonInternal]; + [self.rightButtonContainer addSubview:self.sendButtonInternal]; + + // 竖向排布:粘贴、删除、清空为等高,发送略高 + CGFloat smallH = 44; + CGFloat bigH = 56; + CGFloat vSpace = 10; + [self.pasteButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.rightButtonContainer.mas_top); + make.left.right.equalTo(self.rightButtonContainer); + make.height.mas_equalTo(smallH); + }]; + [self.deleteButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.pasteButtonInternal.mas_bottom).offset(vSpace); + make.left.right.equalTo(self.rightButtonContainer); + make.height.equalTo(self.pasteButtonInternal); + }]; + [self.clearButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.deleteButtonInternal.mas_bottom).offset(vSpace); + make.left.right.equalTo(self.rightButtonContainer); + make.height.equalTo(self.pasteButtonInternal); + }]; + [self.sendButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.clearButtonInternal.mas_bottom).offset(vSpace); + make.left.right.equalTo(self.rightButtonContainer); + make.height.mas_equalTo(bigH); + make.bottom.lessThanOrEqualTo(self.rightButtonContainer.mas_bottom); // 底部可伸缩 + }]; + + // 2. 粘贴区(位于右侧按钮左侧) + [self addSubview:self.pasteViewInternal]; + [self.pasteViewInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.mas_left).offset(12); + make.right.equalTo(self.rightButtonContainer.mas_left).offset(-12); + make.top.equalTo(self.barViewInternal.mas_bottom).offset(8); + make.height.mas_equalTo(48); + }]; + + // 3. CollectionView + [self addSubview:self.collectionViewInternal]; + [self.collectionViewInternal mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self.mas_left).offset(12); + make.right.equalTo(self.rightButtonContainer.mas_left).offset(-12); + make.top.equalTo(self.pasteViewInternal.mas_bottom).offset(10); + make.bottom.equalTo(self.mas_bottom).offset(-10); + }]; +} + +#pragma mark - Data + +- (void)reloadDemoData { + // 演示数据(可由外部替换) + self.itemsInternal = @[@"高情商", @"暖味拉扯", @"风趣幽默", @"撩女生", @"社交惬匿", @"情场高手", @"一枚暖男", @"聊天搭子", @"表达爱意", @"更多话术"]; + [self.collectionViewInternal reloadData]; +} + +#pragma mark - UICollectionView + +- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { + return self.itemsInternal.count; +} + +- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { + KBFunctionTagCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kKBFunctionTagCellId forIndexPath:indexPath]; + cell.titleLabel.text = self.itemsInternal[indexPath.item]; + return cell; +} + +- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + // 三列等宽 + CGFloat totalW = collectionView.bounds.size.width; + CGFloat space = 10.0; + NSInteger columns = 3; + CGFloat width = floor((totalW - space * (columns - 1)) / columns); + return CGSizeMake(width, 48); +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { + return 10.0; +} + +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { + return 12.0; +} + +#pragma mark - Button Actions + +- (void)onTapPaste { NSLog(@"点击:粘贴"); } +- (void)onTapDelete { NSLog(@"点击:删除"); } +- (void)onTapClear { NSLog(@"点击:清空"); } +- (void)onTapSend { NSLog(@"点击:发送"); } + +#pragma mark - Lazy + +- (KBFunctionBarView *)barViewInternal { + if (!_barViewInternal) { + _barViewInternal = [[KBFunctionBarView alloc] init]; + } + return _barViewInternal; +} + +- (KBFunctionPasteView *)pasteViewInternal { + if (!_pasteViewInternal) { + _pasteViewInternal = [[KBFunctionPasteView alloc] init]; + } + return _pasteViewInternal; +} + +- (UICollectionView *)collectionViewInternal { + if (!_collectionViewInternal) { + UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; + layout.sectionInset = UIEdgeInsetsZero; // 外边距交由约束控制 + _collectionViewInternal = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; + _collectionViewInternal.backgroundColor = [UIColor clearColor]; + _collectionViewInternal.dataSource = self; + _collectionViewInternal.delegate = self; + [_collectionViewInternal registerClass:[KBFunctionTagCell class] forCellWithReuseIdentifier:kKBFunctionTagCellId]; + } + return _collectionViewInternal; +} + +- (UIView *)rightButtonContainer { + if (!_rightButtonContainer) { + _rightButtonContainer = [[UIView alloc] init]; + _rightButtonContainer.backgroundColor = [UIColor clearColor]; + } + return _rightButtonContainer; +} + +- (UIButton *)buildRightButtonWithTitle:(NSString *)title color:(UIColor *)color { + UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem]; + btn.backgroundColor = color; + btn.layer.cornerRadius = 12.0; + btn.layer.masksToBounds = YES; + btn.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + [btn setTitle:title forState:UIControlStateNormal]; + [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + return btn; +} + +- (UIButton *)pasteButtonInternal { + if (!_pasteButtonInternal) { + _pasteButtonInternal = [self buildRightButtonWithTitle:@"粘贴" color:[UIColor colorWithRed:0.13 green:0.73 blue:0.60 alpha:1.0]]; + [_pasteButtonInternal addTarget:self action:@selector(onTapPaste) forControlEvents:UIControlEventTouchUpInside]; + } + return _pasteButtonInternal; +} + +- (UIButton *)deleteButtonInternal { + if (!_deleteButtonInternal) { + // 浅灰底深色文字,更接近截图里“删除”样式 + _deleteButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem]; + _deleteButtonInternal.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1.0]; + _deleteButtonInternal.layer.cornerRadius = 12.0; + _deleteButtonInternal.layer.masksToBounds = YES; + _deleteButtonInternal.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + [_deleteButtonInternal setTitle:@"删除" forState:UIControlStateNormal]; + [_deleteButtonInternal setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [_deleteButtonInternal addTarget:self action:@selector(onTapDelete) forControlEvents:UIControlEventTouchUpInside]; + } + return _deleteButtonInternal; +} + +- (UIButton *)clearButtonInternal { + if (!_clearButtonInternal) { + _clearButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem]; + _clearButtonInternal.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1.0]; + _clearButtonInternal.layer.cornerRadius = 12.0; + _clearButtonInternal.layer.masksToBounds = YES; + _clearButtonInternal.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + [_clearButtonInternal setTitle:@"清空" forState:UIControlStateNormal]; + [_clearButtonInternal setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [_clearButtonInternal addTarget:self action:@selector(onTapClear) forControlEvents:UIControlEventTouchUpInside]; + } + return _clearButtonInternal; +} + +- (UIButton *)sendButtonInternal { + if (!_sendButtonInternal) { + _sendButtonInternal = [self buildRightButtonWithTitle:@"发送" color:[UIColor colorWithRed:0.13 green:0.73 blue:0.60 alpha:1.0]]; + [_sendButtonInternal addTarget:self action:@selector(onTapSend) forControlEvents:UIControlEventTouchUpInside]; + } + return _sendButtonInternal; +} + +#pragma mark - Expose + +- (UICollectionView *)collectionView { return self.collectionViewInternal; } +- (NSArray *)items { return self.itemsInternal; } +- (KBFunctionBarView *)barView { return self.barViewInternal; } +- (KBFunctionPasteView *)pasteView { return self.pasteViewInternal; } +- (UIButton *)pasteButton { return self.pasteButtonInternal; } +- (UIButton *)deleteButton { return self.deleteButtonInternal; } +- (UIButton *)clearButton { return self.clearButtonInternal; } +- (UIButton *)sendButton { return self.sendButtonInternal; } + +@end diff --git a/CustomKeyboard/View/KBToolBar.h b/CustomKeyboard/View/KBToolBar.h index 44934d1..8286c46 100644 --- a/CustomKeyboard/View/KBToolBar.h +++ b/CustomKeyboard/View/KBToolBar.h @@ -2,7 +2,7 @@ // KBToolBar.h // CustomKeyboard // -// Created by Mac on 2025/10/27. +// Created by Mac on 2025/10/28. // #import diff --git a/CustomKeyboard/View/KBToolBar.m b/CustomKeyboard/View/KBToolBar.m index bd27167..ab1a602 100644 --- a/CustomKeyboard/View/KBToolBar.m +++ b/CustomKeyboard/View/KBToolBar.m @@ -2,7 +2,7 @@ // KBToolBar.m // CustomKeyboard // -// Created by Mac on 2025/10/27. +// Created by Mac on 2025/10/28. // #import "KBToolBar.h" diff --git a/keyBoard.xcodeproj/project.pbxproj b/keyBoard.xcodeproj/project.pbxproj index b71ed3c..7833142 100644 --- a/keyBoard.xcodeproj/project.pbxproj +++ b/keyBoard.xcodeproj/project.pbxproj @@ -32,6 +32,10 @@ 04FC95672EB0546C007BD342 /* KBKey.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95652EB0546C007BD342 /* KBKey.m */; }; 04FC956A2EB05497007BD342 /* KBKeyButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95692EB05497007BD342 /* KBKeyButton.m */; }; 04FC956D2EB054B7007BD342 /* KBKeyboardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC956C2EB054B7007BD342 /* KBKeyboardView.m */; }; + 04FC95702EB09516007BD342 /* KBFunctionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC956F2EB09516007BD342 /* KBFunctionView.m */; }; + 04FC95732EB09570007BD342 /* KBFunctionBarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95722EB09570007BD342 /* KBFunctionBarView.m */; }; + 04FC95762EB095DE007BD342 /* KBFunctionPasteView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95752EB095DE007BD342 /* KBFunctionPasteView.m */; }; + A1B2C3D42EB0A0A100000001 /* KBFunctionTagCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D32EB0A0A100000001 /* KBFunctionTagCell.m */; }; 7A36414DFDA5BEC9B7D2E318 /* Pods_CustomKeyboard.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C1092FB2B452F95B15D4263 /* Pods_CustomKeyboard.framework */; }; ECC9EE02174D86E8D792472F /* Pods_keyBoard.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 967065BB5230E43F293B3AF9 /* Pods_keyBoard.framework */; }; /* End PBXBuildFile section */ @@ -113,6 +117,14 @@ 04FC95692EB05497007BD342 /* KBKeyButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBKeyButton.m; sourceTree = ""; }; 04FC956B2EB054B7007BD342 /* KBKeyboardView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBKeyboardView.h; sourceTree = ""; }; 04FC956C2EB054B7007BD342 /* KBKeyboardView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBKeyboardView.m; sourceTree = ""; }; + 04FC956E2EB09516007BD342 /* KBFunctionView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFunctionView.h; sourceTree = ""; }; + 04FC956F2EB09516007BD342 /* KBFunctionView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFunctionView.m; sourceTree = ""; }; + 04FC95712EB09570007BD342 /* KBFunctionBarView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFunctionBarView.h; sourceTree = ""; }; + 04FC95722EB09570007BD342 /* KBFunctionBarView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFunctionBarView.m; sourceTree = ""; }; + 04FC95742EB095DE007BD342 /* KBFunctionPasteView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFunctionPasteView.h; sourceTree = ""; }; + 04FC95752EB095DE007BD342 /* KBFunctionPasteView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFunctionPasteView.m; sourceTree = ""; }; + A1B2C3D22EB0A0A100000001 /* KBFunctionTagCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFunctionTagCell.h; sourceTree = ""; }; + A1B2C3D32EB0A0A100000001 /* KBFunctionTagCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFunctionTagCell.m; sourceTree = ""; }; 2C1092FB2B452F95B15D4263 /* Pods_CustomKeyboard.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CustomKeyboard.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 51FE7C4C42C2255B3C1C4128 /* Pods-keyBoard.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-keyBoard.release.xcconfig"; path = "Target Support Files/Pods-keyBoard/Pods-keyBoard.release.xcconfig"; sourceTree = ""; }; 727EC7532EAF848B00B36487 /* keyBoard.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = keyBoard.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -183,6 +195,14 @@ 04FC95692EB05497007BD342 /* KBKeyButton.m */, 04FC956B2EB054B7007BD342 /* KBKeyboardView.h */, 04FC956C2EB054B7007BD342 /* KBKeyboardView.m */, + 04FC956E2EB09516007BD342 /* KBFunctionView.h */, + 04FC956F2EB09516007BD342 /* KBFunctionView.m */, + 04FC95712EB09570007BD342 /* KBFunctionBarView.h */, + 04FC95722EB09570007BD342 /* KBFunctionBarView.m */, + 04FC95742EB095DE007BD342 /* KBFunctionPasteView.h */, + 04FC95752EB095DE007BD342 /* KBFunctionPasteView.m */, + A1B2C3D22EB0A0A100000001 /* KBFunctionTagCell.h */, + A1B2C3D32EB0A0A100000001 /* KBFunctionTagCell.m */, ); path = View; sourceTree = ""; @@ -420,10 +440,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks.sh\"\n"; @@ -459,7 +483,10 @@ buildActionMask = 2147483647; files = ( 04C6EADD2EAF8CEB0089C901 /* KBToolBar.m in Sources */, + 04FC95732EB09570007BD342 /* KBFunctionBarView.m in Sources */, 04C6EAD82EAF870B0089C901 /* KeyboardViewController.m in Sources */, + 04FC95762EB095DE007BD342 /* KBFunctionPasteView.m in Sources */, + A1B2C3D42EB0A0A100000001 /* KBFunctionTagCell.m in Sources */, 04FC956A2EB05497007BD342 /* KBKeyButton.m in Sources */, 04FC95582EAFAF51007BD342 /* MASConstraintMaker.m in Sources */, 04FC95592EAFAF51007BD342 /* MASViewConstraint.m in Sources */, @@ -467,6 +494,7 @@ 04FC955B2EAFAF51007BD342 /* NSArray+MASAdditions.m in Sources */, 04FC955C2EAFAF51007BD342 /* View+MASAdditions.m in Sources */, 04FC955D2EAFAF51007BD342 /* MASCompositeConstraint.m in Sources */, + 04FC95702EB09516007BD342 /* KBFunctionView.m in Sources */, 04FC956D2EB054B7007BD342 /* KBKeyboardView.m in Sources */, 04FC95672EB0546C007BD342 /* KBKey.m in Sources */, 04FC955E2EAFAF51007BD342 /* MASConstraint.m in Sources */,