From 2435d760e8684ebb7e430d50a9f86d2ca944ba83 Mon Sep 17 00:00:00 2001 From: CodeST <694468528@qq.com> Date: Wed, 26 Nov 2025 21:16:56 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=94=AE=E7=9B=98=E5=8A=9F?= =?UTF-8?q?=E8=83=BDviewUI=E6=94=B9=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kb_del_icon.imageset/Contents.json | 22 ++++ .../kb_del_icon.imageset/kb_del_icon@2x.png | Bin 0 -> 1115 bytes .../kb_del_icon.imageset/kb_del_icon@3x.png | Bin 0 -> 2087 bytes .../kb_zt_icon.imageset/Contents.json | 22 ++++ .../kb_zt_icon.imageset/kb_zt_icon@2x.png | Bin 0 -> 1014 bytes .../kb_zt_icon.imageset/kb_zt_icon@3x.png | Bin 0 -> 1860 bytes CustomKeyboard/KeyboardViewController.m | 15 +++ .../View/Function/KBFunctionTagListView.m | 9 +- CustomKeyboard/View/KBFunctionBarView.h | 14 ++- CustomKeyboard/View/KBFunctionBarView.m | 119 ++++++------------ CustomKeyboard/View/KBFunctionPasteView.m | 57 +++++---- CustomKeyboard/View/KBFunctionTagCell.m | 51 +++++--- CustomKeyboard/View/KBFunctionView.h | 2 + CustomKeyboard/View/KBFunctionView.m | 73 +++++------ .../Localization/en.lproj/Localizable.strings | 2 + .../zh-Hans.lproj/Localizable.strings | 2 + keyBoard/AppDelegate.m | 8 +- 17 files changed, 229 insertions(+), 167 deletions(-) create mode 100644 CustomKeyboard/KeyboardAssets.xcassets/kb_del_icon.imageset/Contents.json create mode 100644 CustomKeyboard/KeyboardAssets.xcassets/kb_del_icon.imageset/kb_del_icon@2x.png create mode 100644 CustomKeyboard/KeyboardAssets.xcassets/kb_del_icon.imageset/kb_del_icon@3x.png create mode 100644 CustomKeyboard/KeyboardAssets.xcassets/kb_zt_icon.imageset/Contents.json create mode 100644 CustomKeyboard/KeyboardAssets.xcassets/kb_zt_icon.imageset/kb_zt_icon@2x.png create mode 100644 CustomKeyboard/KeyboardAssets.xcassets/kb_zt_icon.imageset/kb_zt_icon@3x.png diff --git a/CustomKeyboard/KeyboardAssets.xcassets/kb_del_icon.imageset/Contents.json b/CustomKeyboard/KeyboardAssets.xcassets/kb_del_icon.imageset/Contents.json new file mode 100644 index 0000000..d4b1584 --- /dev/null +++ b/CustomKeyboard/KeyboardAssets.xcassets/kb_del_icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "kb_del_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "kb_del_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/CustomKeyboard/KeyboardAssets.xcassets/kb_del_icon.imageset/kb_del_icon@2x.png b/CustomKeyboard/KeyboardAssets.xcassets/kb_del_icon.imageset/kb_del_icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3f365328740b9a7111e7d6ea3d31ec25240a8746 GIT binary patch literal 1115 zcmV-h1f=_kP)n06j(%N^ zNS6K8+J}usW0%I9e1B()!{*z-P`1*2;2C(E&AU(tLs>vQDWzKdcYTi~WA=o01#jy^ z2Hvi(*MCxZB6A0LwwTQ^n-4%5gi%~Wp2X4t?ub37kZBV6W@CNhHSfxI2Z`~2g_AM}-&QSXHJ{Dbt8^tZt++p`*KED?XTxwiQaB}{-xrOdL}M}PM` z@2P&n;253JKbYxf)tl?5m$W?w_q?O}LOBg@2NHagbTIT9mByA3UDXhkBS)6qC)@&c zCA4YmU4o8~T=RYZ?=F>rA7gNGob$|ViFt7lZ|}V=XmRT`00E36>VO9{+O)5zI+Yd& zFX^~I%TU>13e{*?t!yj6$661Z8k|3C?P-#_%5zR+ zzs+W|Q-?O(V_>{gI0zTwKISv|1P4j1+w}uzjnh8@R7fgV9@OHJ0G|0-=P`R_l<+Zl zwYvGI-gPf1OIlKC9Q!IJ&t1@U1)j&6)_8s0gi%?~hg}V~FE~f+*Hol5jUdI~up=p1 z(7H(^r}O!lr&Ugxts~BrJx>F=1mOL_>+zi@oR8s&=RI*R?)ME-x542dy<9D-XRO#1 zJ|dCbW3$KRnCPVFl2A`~K<^vyS2usr8GT)!n+*7(H<}|~4aWJF2|iH)#>+{)zOlCP z7g2OdPsC^L^|adQ$hEcF4?!4~)H!GTihr%6^AHbhk7H~@Pe3)i2w4X3dUd7#T|5>8 z4=A`QS66Fa9H5f8s{nuymu9H;;Q literal 0 HcmV?d00001 diff --git a/CustomKeyboard/KeyboardAssets.xcassets/kb_del_icon.imageset/kb_del_icon@3x.png b/CustomKeyboard/KeyboardAssets.xcassets/kb_del_icon.imageset/kb_del_icon@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..5cc16ee9ae38a7802d6076ea30c707d6d2a5b675 GIT binary patch literal 2087 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 @property (nonatomic, strong) UICollectionView *collectionViewInternal; @@ -54,13 +55,13 @@ static NSString * const kKBFunctionTagCellId2 = @"KBFunctionTagCellId2"; } - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { - CGFloat totalW = collectionView.bounds.size.width; CGFloat space = 10.0; NSInteger columns = 3; + CGFloat totalW = collectionView.bounds.size.width; CGFloat space = kKBItemSpace; NSInteger columns = 3; CGFloat width = floor((totalW - space * (columns - 1)) / columns); - return CGSizeMake(width, 48); + return CGSizeMake(width, 41); } -- (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; } +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { return kKBItemSpace; } +- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { return kKBItemSpace; } - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { if ([self.delegate respondsToSelector:@selector(tagListView:didSelectIndex:title:)]) { diff --git a/CustomKeyboard/View/KBFunctionBarView.h b/CustomKeyboard/View/KBFunctionBarView.h index e422613..cf3a12a 100644 --- a/CustomKeyboard/View/KBFunctionBarView.h +++ b/CustomKeyboard/View/KBFunctionBarView.h @@ -9,7 +9,9 @@ NS_ASSUME_NONNULL_BEGIN -/// 功能区顶部的Bar:左侧4个按钮,右侧3个按钮 +/// 功能区顶部的 Bar: +/// 左侧:App 图标按钮(点击可回到主 App 或打开更多功能) +/// 右侧:升级 VIP 按钮 @class KBFunctionBarView; @protocol KBFunctionBarViewDelegate @@ -24,15 +26,15 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, weak, nullable) id delegate; -/// 左侧4个按钮(懒加载创建,等宽水平排布) +/// 左侧按钮(当前只有一个:App 图标) @property (nonatomic, strong, readonly) NSArray *leftButtons; -/// 右侧3个按钮(懒加载创建,等宽水平排布,靠右) +/// 右侧按钮(当前只有一个:升级 VIP) @property (nonatomic, strong, readonly) NSArray *rightButtons; -/// 配置按钮标题(可选) -@property (nonatomic, copy) NSArray *leftTitles; // 默认 @[@"帮回", @"会说", @"话术", @"更多"] -@property (nonatomic, copy) NSArray *rightTitles; // 默认 @[@"❤", @"收藏", @"宫格"] +/// 预留的标题配置(目前按钮主要以图片为主,可选) +@property (nonatomic, copy) NSArray *leftTitles; +@property (nonatomic, copy) NSArray *rightTitles; @end diff --git a/CustomKeyboard/View/KBFunctionBarView.m b/CustomKeyboard/View/KBFunctionBarView.m index 1121e45..27ba738 100644 --- a/CustomKeyboard/View/KBFunctionBarView.m +++ b/CustomKeyboard/View/KBFunctionBarView.m @@ -22,8 +22,9 @@ - (instancetype)initWithFrame:(CGRect)frame{ if (self = [super initWithFrame:frame]) { self.backgroundColor = [UIColor clearColor]; - _leftTitles = @[@"ABC"]; - _rightTitles = @[@"Upgrade VIP"]; + // 标题字段暂时不用,预留给后续可能的文案按钮 + _leftTitles = @[]; + _rightTitles = @[]; [self buildUI]; } return self; @@ -38,91 +39,60 @@ #pragma mark - UI - (void)buildUI { - // 左右两个容器,方便分别布局 - [self addSubview:self.leftContainer]; + // 左右容器 + 可选地球键 [self addSubview:self.globeButtonInternal]; + [self addSubview:self.leftContainer]; [self addSubview:self.rightContainer]; + // 右侧:升级 VIP 按钮(使用资源图 upgrad_vip_icon,设计尺寸 115x35) [self.rightContainer mas_makeConstraints:^(MASConstraintMaker *make) { - make.right.equalTo(self.mas_right).offset(-12); + make.right.equalTo(self.mas_right).offset(-6); make.centerY.equalTo(self.mas_centerY); - make.height.mas_equalTo(36); + make.width.mas_equalTo(115); + make.height.mas_equalTo(35); }]; - // 左侧地球键(按需显示) + UIButton *vipButton = [UIButton buttonWithType:UIButtonTypeCustom]; + vipButton.tag = 200; // 右侧 index = 0 + UIImage *vipImage = [UIImage imageNamed:@"upgrad_vip_icon"]; + [vipButton setImage:vipImage forState:UIControlStateNormal]; + vipButton.imageView.contentMode = UIViewContentModeScaleAspectFit; + vipButton.adjustsImageWhenHighlighted = YES; + [vipButton addTarget:self action:@selector(onRightTap:) forControlEvents:UIControlEventTouchUpInside]; + [self.rightContainer addSubview:vipButton]; + [vipButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.rightContainer); + }]; + self.rightButtonsInternal = @[vipButton]; + + // 左侧地球键(按需显示,由 kb_refreshGlobeVisibility 控制是否展示) [self.globeButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.mas_left).offset(12); make.centerY.equalTo(self.mas_centerY); make.width.height.mas_equalTo(32); }]; + // 左侧:App 图标按钮(使用资源图 App_icon,图标 34x34,按钮容器 36x36) [self.leftContainer mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.equalTo(self.globeButtonInternal.mas_right).offset(8); - make.right.equalTo(self.rightContainer.mas_left).offset(-12); make.centerY.equalTo(self.mas_centerY); + make.width.mas_equalTo(36); make.height.mas_equalTo(36); + make.left.equalTo(self.mas_left).offset(12); // 具体偏移在 kb_refreshGlobeVisibility 中会根据地球键重新设置 }]; - // 左侧4个等宽按钮 - NSMutableArray *leftBtns = [NSMutableArray arrayWithCapacity:4]; - UIView *prev = nil; - for (NSInteger i = 0; i < self.leftTitles.count; i++) { - UIButton *btn = [self buildButtonWithTitle:(i < self.leftTitles.count ? self.leftTitles[i] : [NSString stringWithFormat:@"L%ld", (long)i])]; - btn.tag = 100 + i; - [btn addTarget:self action:@selector(onLeftTap:) forControlEvents:UIControlEventTouchUpInside]; - [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); + UIButton *appButton = [UIButton buttonWithType:UIButtonTypeCustom]; + appButton.tag = 100; // 左侧 index = 0 + UIImage *appImage = [UIImage imageNamed:@"App_icon"]; + [appButton setImage:appImage forState:UIControlStateNormal]; + appButton.imageView.contentMode = UIViewContentModeScaleAspectFit; + appButton.adjustsImageWhenHighlighted = YES; + [appButton addTarget:self action:@selector(onLeftTap:) forControlEvents:UIControlEventTouchUpInside]; + [self.leftContainer addSubview:appButton]; + [appButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.center.equalTo(self.leftContainer); + make.width.height.mas_equalTo(34); // 设计图尺寸 }]; - self.leftButtonsInternal = leftBtns.copy; - - // 右侧N个按钮(靠右、两两等宽) - NSMutableArray *rightBtns = [NSMutableArray arrayWithCapacity:3]; - for (NSInteger i = 0; i < self.rightTitles.count; 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]; - [btn addTarget:self action:@selector(onRightTap:) forControlEvents:UIControlEventTouchUpInside]; - [rightBtns addObject:btn]; - } - - // 从右往左链式布局,保证整体靠右;支持 1/2/3... 任意数量 - UIView *prevRight = nil; // 指向右侧已布局的按钮 - for (NSInteger i = rightBtns.count - 1; i >= 0; i--) { - UIButton *btn = rightBtns[i]; - [btn mas_makeConstraints:^(MASConstraintMaker *make) { - if (!prevRight) { - // 最右侧按钮贴右 - make.right.equalTo(self.rightContainer.mas_right); - } else { - // 其余按钮紧挨左侧兄弟,且与其等宽 - make.right.equalTo(prevRight.mas_left).offset(-8); - make.width.equalTo(prevRight); - } - make.top.bottom.equalTo(self.rightContainer); - }]; - prevRight = btn; - } - // 最左侧一个不超出容器左边(允许根据内容自然宽度收缩) - if (prevRight) { - [prevRight mas_makeConstraints:^(MASConstraintMaker *make) { - make.left.greaterThanOrEqualTo(self.rightContainer.mas_left); - }]; - } - - self.rightButtonsInternal = rightBtns.copy; + self.leftButtonsInternal = @[appButton]; // 初始刷新地球键可见性与事件绑定 [self kb_refreshGlobeVisibility]; @@ -144,17 +114,6 @@ } } -- (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 { @@ -201,8 +160,8 @@ } else { make.left.equalTo(self.mas_left).offset(12); } - make.right.equalTo(self.rightContainer.mas_left).offset(-12); make.centerY.equalTo(self.mas_centerY); + make.width.mas_equalTo(36); make.height.mas_equalTo(36); }]; diff --git a/CustomKeyboard/View/KBFunctionPasteView.m b/CustomKeyboard/View/KBFunctionPasteView.m index 93b8f8c..ebdcf73 100644 --- a/CustomKeyboard/View/KBFunctionPasteView.m +++ b/CustomKeyboard/View/KBFunctionPasteView.m @@ -7,10 +7,13 @@ #import "KBFunctionPasteView.h" #import "Masonry.h" +#import "KBFont.h" @interface KBFunctionPasteView () @property (nonatomic, strong) UIImageView *iconViewInternal; @property (nonatomic, strong) UILabel *placeholderLabelInternal; +@property (nonatomic, strong) UIButton *pasBtn; + @end @implementation KBFunctionPasteView @@ -22,19 +25,24 @@ self.layer.cornerRadius = 12.0; self.layer.masksToBounds = YES; - [self addSubview:self.iconViewInternal]; - [self addSubview:self.placeholderLabelInternal]; +// [self addSubview:self.iconViewInternal]; +// [self addSubview:self.placeholderLabelInternal]; + [self addSubview:self.pasBtn]; + [self.pasBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self); + }]; - [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); - }]; +// [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; } @@ -44,15 +52,7 @@ - (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); - }]; + _iconViewInternal.image = [UIImage imageNamed:@"kb_zt_icon"]; } return _iconViewInternal; } @@ -60,13 +60,26 @@ - (UILabel *)placeholderLabelInternal { if (!_placeholderLabelInternal) { _placeholderLabelInternal = [[UILabel alloc] init]; - _placeholderLabelInternal.text = KBLocalized(@"Tap to paste their message"); + // 文案改为更贴近设计稿 + _placeholderLabelInternal.text = KBLocalized(@"Paste Ta's Words"); _placeholderLabelInternal.textColor = [UIColor colorWithRed:0.20 green:0.64 blue:0.54 alpha:1.0]; _placeholderLabelInternal.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; } return _placeholderLabelInternal; } +- (UIButton *)pasBtn{ + if (!_pasBtn) { + _pasBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + [_pasBtn setImage:[UIImage imageNamed:@"kb_zt_icon"] forState:UIControlStateNormal]; + [_pasBtn setTitle:KBLocalized(@" Paste Ta's Words") forState:UIControlStateNormal]; + [_pasBtn setTitleColor:[UIColor colorWithHex:0x02BEAC] forState:UIControlStateNormal]; + _pasBtn.titleLabel.font = [KBFont medium:13]; + _pasBtn.backgroundColor = [UIColor whiteColor]; + } + return _pasBtn; +} + #pragma mark - Expose - (UIImageView *)iconView { return self.iconViewInternal; } diff --git a/CustomKeyboard/View/KBFunctionTagCell.m b/CustomKeyboard/View/KBFunctionTagCell.m index d848f63..976a488 100644 --- a/CustomKeyboard/View/KBFunctionTagCell.m +++ b/CustomKeyboard/View/KBFunctionTagCell.m @@ -22,26 +22,38 @@ self.contentView.layer.cornerRadius = 12; self.contentView.layer.masksToBounds = YES; - [self.contentView addSubview:self.iconViewInternal]; - [self.contentView addSubview:self.titleLabelInternal]; + // 小菊花:默认隐藏,放在整体内容右侧偏内的位置 + [self.contentView addSubview:self.loadingView]; + [self.loadingView mas_makeConstraints:^(MASConstraintMaker *make) { + make.center.equalTo(self.contentView); + make.width.height.mas_equalTo(16); + }]; + + // 中心容器:将 icon + title 组合整体水平居中 + UIView *centerContainer = [[UIView alloc] init]; + centerContainer.backgroundColor = [UIColor clearColor]; + [self.contentView addSubview:centerContainer]; + [centerContainer mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.equalTo(self.contentView.mas_centerX); + make.centerY.equalTo(self.contentView.mas_centerY); + make.left.greaterThanOrEqualTo(self.contentView.mas_left).offset(6); + make.right.lessThanOrEqualTo(self.contentView).offset(-6); + }]; + + [centerContainer addSubview:self.iconViewInternal]; + [centerContainer 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.left.equalTo(centerContainer.mas_left); + make.centerY.equalTo(centerContainer.mas_centerY); + // 留出一点余量,避免 emoji 字形在右侧被裁剪 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); - }]; - - // 小菊花:默认隐藏,放在标题右侧 - [self.contentView addSubview:self.loadingView]; - [self.loadingView mas_makeConstraints:^(MASConstraintMaker *make) { - make.centerY.equalTo(self.contentView); - make.right.equalTo(self.contentView.mas_right).offset(-10); - make.width.height.mas_equalTo(16); + make.left.equalTo(self.iconViewInternal.mas_right).offset(3); + make.top.equalTo(centerContainer.mas_top); + make.bottom.equalTo(centerContainer.mas_bottom); + make.right.equalTo(centerContainer.mas_right); }]; } return self; @@ -56,6 +68,8 @@ emoji.text = @"🙂"; // 占位图标 emoji.textAlignment = NSTextAlignmentCenter; emoji.font = [UIFont systemFontOfSize:20]; + emoji.adjustsFontSizeToFitWidth = YES; + emoji.minimumScaleFactor = 0.8; [_iconViewInternal addSubview:emoji]; [emoji mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.equalTo(_iconViewInternal); @@ -67,8 +81,11 @@ - (UILabel *)titleLabelInternal { if (!_titleLabelInternal) { _titleLabelInternal = [[UILabel alloc] init]; - _titleLabelInternal.font = [UIFont systemFontOfSize:15 weight:UIFontWeightSemibold]; - _titleLabelInternal.textColor = [UIColor blackColor]; + _titleLabelInternal.font = [KBFont medium:10]; + _titleLabelInternal.textColor = [UIColor colorWithHex:0x1B1F1A]; + // 最多两行,文本过长时末尾截断 + _titleLabelInternal.numberOfLines = 2; + _titleLabelInternal.lineBreakMode = NSLineBreakByTruncatingTail; } return _titleLabelInternal; } diff --git a/CustomKeyboard/View/KBFunctionView.h b/CustomKeyboard/View/KBFunctionView.h index 958461a..6266c07 100644 --- a/CustomKeyboard/View/KBFunctionView.h +++ b/CustomKeyboard/View/KBFunctionView.h @@ -11,6 +11,8 @@ @protocol KBFunctionViewDelegate @optional - (void)functionView:(KBFunctionView *_Nullable)functionView didTapToolActionAtIndex:(NSInteger)index; +- (void)functionView:(KBFunctionView *_Nullable)functionView didRightTapToolActionAtIndex:(NSInteger)index; + @end NS_ASSUME_NONNULL_BEGIN diff --git a/CustomKeyboard/View/KBFunctionView.m b/CustomKeyboard/View/KBFunctionView.m index 2f78e9b..b4a99c7 100644 --- a/CustomKeyboard/View/KBFunctionView.m +++ b/CustomKeyboard/View/KBFunctionView.m @@ -106,16 +106,16 @@ [self.barViewInternal mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.equalTo(self); make.top.equalTo(self.mas_top).offset(6); - make.height.mas_equalTo(48); + make.height.mas_equalTo(52); }]; // 右侧竖排按钮容器 [self addSubview:self.rightButtonContainer]; [self.rightButtonContainer mas_makeConstraints:^(MASConstraintMaker *make) { - make.right.equalTo(self.mas_right).offset(-6); - make.top.equalTo(self.barViewInternal.mas_bottom).offset(8); + make.right.equalTo(self.mas_right).offset(-4); + make.top.equalTo(self.barViewInternal.mas_bottom).offset(0); make.bottom.equalTo(self.mas_bottom).offset(-10); - make.width.mas_equalTo(72); + make.width.mas_equalTo(60); }]; // 右侧四个按钮 @@ -125,10 +125,10 @@ [self.rightButtonContainer addSubview:self.sendButtonInternal]; // 竖向排布:粘贴、删除、清空为等高;发送优先更高,但允许在空间不足时压缩 - CGFloat smallH = 44; + CGFloat smallH = 41; CGFloat bigH = 56; // 原 10 在键盘总高度 276 下容易超出容器,改为 8 以避免 AutoLayout 冲突 - CGFloat vSpace = 8; + CGFloat vSpace = 4; [self.pasteButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.rightButtonContainer.mas_top); make.left.right.equalTo(self.rightButtonContainer); @@ -156,18 +156,18 @@ // 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); + make.left.equalTo(self.mas_left).offset(vSpace); + make.right.equalTo(self.rightButtonContainer.mas_left).offset(-vSpace); + make.top.equalTo(self.barViewInternal.mas_bottom).offset(0); + make.height.mas_equalTo(smallH); }]; // 3. Tag List View [self addSubview:self.tagListView]; [self.tagListView 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.left.equalTo(self.pasteViewInternal); + make.right.equalTo(self.rightButtonContainer.mas_left).offset(-vSpace); + make.top.equalTo(self.pasteViewInternal.mas_bottom).offset(vSpace); make.bottom.equalTo(self.mas_bottom).offset(-10); }]; } @@ -176,13 +176,13 @@ - (void)reloadDemoData { // 演示数据(可由外部替换) - self.itemsInternal = @[KBLocalized(@"高情商"), - KBLocalized(@"暖味拉扯"), - KBLocalized(@"风趣幽默"), - KBLocalized(@"撩女生"), - KBLocalized(@"社交惬匿"), - KBLocalized(@"情场高手"), - KBLocalized(@"一枚暖男"), + self.itemsInternal = @[KBLocalized(@"Warm hearted man"), + KBLocalized(@"Warm2 hearted man"), + KBLocalized(@"Warm3 hearted man"), + KBLocalized(@"撩女生啊u发顺丰大师傅"), + KBLocalized(@"Warm = man"), + KBLocalized(@"Warm hearted man"), + KBLocalized(@"一枚暖男发放"), KBLocalized(@"聊天搭子"), KBLocalized(@"表达爱意"), KBLocalized(@"更多话术")]; @@ -537,6 +537,9 @@ static void KBULDarwinCallback(CFNotificationCenterRef center, void *observer, C - (void)functionBarView:(KBFunctionBarView *)bar didTapRightAtIndex:(NSInteger)index { // 右侧按钮点击,如收藏/宫格等,按需继续向外抛出(这里暂不定义单独协议方法,可在此内部处理或扩展) + if ([self.delegate respondsToSelector:@selector(functionView:didRightTapToolActionAtIndex:)]) { + [self.delegate functionView:self didRightTapToolActionAtIndex:index]; + } } - (KBFunctionPasteView *)pasteViewInternal { @@ -563,11 +566,11 @@ static void KBULDarwinCallback(CFNotificationCenterRef center, void *observer, C } - (UIButton *)buildRightButtonWithTitle:(NSString *)title color:(UIColor *)color { - UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem]; + UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; btn.backgroundColor = color; - btn.layer.cornerRadius = 12.0; + btn.layer.cornerRadius = 8.0; btn.layer.masksToBounds = YES; - btn.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + btn.titleLabel.font = [KBFont medium:13]; [btn setTitle:title forState:UIControlStateNormal]; [btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; return btn; @@ -583,14 +586,12 @@ static void KBULDarwinCallback(CFNotificationCenterRef center, void *observer, C - (UIButton *)deleteButtonInternal { if (!_deleteButtonInternal) { - // 浅灰底深色文字,更接近截图里“删除”样式 - _deleteButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem]; - _deleteButtonInternal.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1.0]; - _deleteButtonInternal.layer.cornerRadius = 12.0; + _deleteButtonInternal = [UIButton buttonWithType:UIButtonTypeCustom]; + _deleteButtonInternal.backgroundColor = [UIColor colorWithHex:0xB9BDC8]; + _deleteButtonInternal.layer.cornerRadius = 8.0; _deleteButtonInternal.layer.masksToBounds = YES; - _deleteButtonInternal.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; - [_deleteButtonInternal setTitle:KBLocalized(@"Delete") forState:UIControlStateNormal]; - [_deleteButtonInternal setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; + [_deleteButtonInternal setImage:[UIImage imageNamed:@"kb_del_icon"] forState:UIControlStateNormal]; + [_deleteButtonInternal addTarget:self action:@selector(onTapDelete) forControlEvents:UIControlEventTouchUpInside]; } return _deleteButtonInternal; @@ -598,11 +599,11 @@ static void KBULDarwinCallback(CFNotificationCenterRef center, void *observer, C - (UIButton *)clearButtonInternal { if (!_clearButtonInternal) { - _clearButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem]; - _clearButtonInternal.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1.0]; - _clearButtonInternal.layer.cornerRadius = 12.0; + _clearButtonInternal = [UIButton buttonWithType:UIButtonTypeCustom]; + _clearButtonInternal.backgroundColor = [UIColor colorWithHex:0xB9BDC8]; + _clearButtonInternal.layer.cornerRadius = 8.0; _clearButtonInternal.layer.masksToBounds = YES; - _clearButtonInternal.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold]; + _clearButtonInternal.titleLabel.font = [KBFont medium:13]; [_clearButtonInternal setTitle:KBLocalized(@"Clear") forState:UIControlStateNormal]; [_clearButtonInternal setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [_clearButtonInternal addTarget:self action:@selector(onTapClear) forControlEvents:UIControlEventTouchUpInside]; @@ -610,9 +611,9 @@ static void KBULDarwinCallback(CFNotificationCenterRef center, void *observer, C return _clearButtonInternal; } - - (UIButton *)sendButtonInternal { +- (UIButton *)sendButtonInternal { if (!_sendButtonInternal) { - _sendButtonInternal = [self buildRightButtonWithTitle:KBLocalized(@"Send") color:[UIColor colorWithRed:0.13 green:0.73 blue:0.60 alpha:1.0]]; + _sendButtonInternal = [self buildRightButtonWithTitle:KBLocalized(@"Send") color:[UIColor colorWithHex:0x02BEAC]]; [_sendButtonInternal addTarget:self action:@selector(onTapSend) forControlEvents:UIControlEventTouchUpInside]; } return _sendButtonInternal; diff --git a/Shared/Localization/en.lproj/Localizable.strings b/Shared/Localization/en.lproj/Localizable.strings index 078ec6b..b74895d 100644 --- a/Shared/Localization/en.lproj/Localizable.strings +++ b/Shared/Localization/en.lproj/Localizable.strings @@ -110,6 +110,8 @@ "Gender" = "Gender"; "User ID" = "User ID"; +" Paste Ta's Words" = " Paste Ta's Words"; + // Search & history "Clear history" = "Clear history"; diff --git a/Shared/Localization/zh-Hans.lproj/Localizable.strings b/Shared/Localization/zh-Hans.lproj/Localizable.strings index 96b32af..8e09c28 100644 --- a/Shared/Localization/zh-Hans.lproj/Localizable.strings +++ b/Shared/Localization/zh-Hans.lproj/Localizable.strings @@ -111,6 +111,8 @@ "Gender" = "性别"; "User ID" = "用户ID"; +" Paste Ta's Words" = " 粘贴TA的话"; + // 搜索与历史(英文 key) "Clear history" = "清空历史"; "Delete all history?" = "是否删除所有历史记录?"; diff --git a/keyBoard/AppDelegate.m b/keyBoard/AppDelegate.m index e7340ef..565e703 100644 --- a/keyBoard/AppDelegate.m +++ b/keyBoard/AppDelegate.m @@ -23,6 +23,7 @@ #import "FGIAPManager.h" #import "KBSexSelVC.h" #import "KBKeyboardPermissionManager.h" +#import "KBVipPay.h" // 注意:用于判断系统已启用本输入法扩展的 bundle id 需与扩展 target 的 // PRODUCT_BUNDLE_IDENTIFIER 完全一致。 @@ -140,7 +141,8 @@ NULL, NULL, true); if ([entry isEqualToString:@"recharge"]) { // 充值入口:拉起主 App 后进入充值相关页面(目前先做占位提示) - [KBHUD showInfo:@"去充值"]; +// [KBHUD showInfo:@"去充值"]; + } else { // 默认逻辑:登录 [self kb_presentLoginSheetIfNeeded]; @@ -171,7 +173,9 @@ return YES; }else if ([host isEqualToString:@"recharge"]) { // kbkeyboard://settings // [self kb_openAppSettings]; - [KBHUD showInfo:@"去充值"]; +// [KBHUD showInfo:@"去充值"]; + KBVipPay *vc = [[KBVipPay alloc] init]; + [KB_CURRENT_NAV pushViewController:vc animated:true]; return YES; } return NO;