添加指引
This commit is contained in:
@@ -31,6 +31,10 @@
|
||||
04FC95D22EB1E7AE007BD342 /* MyVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95D12EB1E7AE007BD342 /* MyVC.m */; };
|
||||
04FC95D72EB1EA16007BD342 /* BaseTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95D62EB1EA16007BD342 /* BaseTableView.m */; };
|
||||
04FC95D82EB1EA16007BD342 /* BaseCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95D42EB1EA16007BD342 /* BaseCell.m */; };
|
||||
04FC95DD2EB202A3007BD342 /* KBGuideVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95DC2EB202A3007BD342 /* KBGuideVC.m */; };
|
||||
04FC97002EB30A00007BD342 /* KBGuideTopCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC96FF2EB30A00007BD342 /* KBGuideTopCell.m */; };
|
||||
04FC97032EB30A00007BD342 /* KBGuideKFCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97022EB30A00007BD342 /* KBGuideKFCell.m */; };
|
||||
04FC97062EB30A00007BD342 /* KBGuideUserCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97052EB30A00007BD342 /* KBGuideUserCell.m */; };
|
||||
7A36414DFDA5BEC9B7D2E318 /* Pods_CustomKeyboard.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C1092FB2B452F95B15D4263 /* Pods_CustomKeyboard.framework */; };
|
||||
A1B2C3D42EB0A0A100000001 /* KBFunctionTagCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D32EB0A0A100000001 /* KBFunctionTagCell.m */; };
|
||||
A1B2C3E22EB0C0A100000001 /* KBNetworkManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3E12EB0C0A100000001 /* KBNetworkManager.m */; };
|
||||
@@ -109,6 +113,14 @@
|
||||
04FC95D42EB1EA16007BD342 /* BaseCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BaseCell.m; sourceTree = "<group>"; };
|
||||
04FC95D52EB1EA16007BD342 /* BaseTableView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseTableView.h; sourceTree = "<group>"; };
|
||||
04FC95D62EB1EA16007BD342 /* BaseTableView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BaseTableView.m; sourceTree = "<group>"; };
|
||||
04FC95DB2EB202A3007BD342 /* KBGuideVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBGuideVC.h; sourceTree = "<group>"; };
|
||||
04FC95DC2EB202A3007BD342 /* KBGuideVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBGuideVC.m; sourceTree = "<group>"; };
|
||||
04FC96FE2EB30A00007BD342 /* KBGuideTopCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBGuideTopCell.h; sourceTree = "<group>"; };
|
||||
04FC96FF2EB30A00007BD342 /* KBGuideTopCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBGuideTopCell.m; sourceTree = "<group>"; };
|
||||
04FC97012EB30A00007BD342 /* KBGuideKFCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBGuideKFCell.h; sourceTree = "<group>"; };
|
||||
04FC97022EB30A00007BD342 /* KBGuideKFCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBGuideKFCell.m; sourceTree = "<group>"; };
|
||||
04FC97042EB30A00007BD342 /* KBGuideUserCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBGuideUserCell.h; sourceTree = "<group>"; };
|
||||
04FC97052EB30A00007BD342 /* KBGuideUserCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBGuideUserCell.m; sourceTree = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
727EC7532EAF848B00B36487 /* keyBoard.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = keyBoard.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@@ -149,6 +161,14 @@
|
||||
04C6EAE32EAF942E0089C901 /* VC */,
|
||||
04C6EAAC2EAF86530089C901 /* AppDelegate.h */,
|
||||
04C6EAAD2EAF86530089C901 /* AppDelegate.m */,
|
||||
04FC95DB2EB202A3007BD342 /* KBGuideVC.h */,
|
||||
04FC95DC2EB202A3007BD342 /* KBGuideVC.m */,
|
||||
04FC96FE2EB30A00007BD342 /* KBGuideTopCell.h */,
|
||||
04FC96FF2EB30A00007BD342 /* KBGuideTopCell.m */,
|
||||
04FC97012EB30A00007BD342 /* KBGuideKFCell.h */,
|
||||
04FC97022EB30A00007BD342 /* KBGuideKFCell.m */,
|
||||
04FC97042EB30A00007BD342 /* KBGuideUserCell.h */,
|
||||
04FC97052EB30A00007BD342 /* KBGuideUserCell.m */,
|
||||
04C6EAAE2EAF86530089C901 /* Assets.xcassets */,
|
||||
04C6EAAF2EAF86530089C901 /* Info.plist */,
|
||||
04C6EAB12EAF86530089C901 /* LaunchScreen.storyboard */,
|
||||
@@ -612,6 +632,10 @@
|
||||
04FC95D72EB1EA16007BD342 /* BaseTableView.m in Sources */,
|
||||
04FC95D82EB1EA16007BD342 /* BaseCell.m in Sources */,
|
||||
04FC95C92EB1E4C9007BD342 /* BaseNavigationController.m in Sources */,
|
||||
04FC95DD2EB202A3007BD342 /* KBGuideVC.m in Sources */,
|
||||
04FC97002EB30A00007BD342 /* KBGuideTopCell.m in Sources */,
|
||||
04FC97032EB30A00007BD342 /* KBGuideKFCell.m in Sources */,
|
||||
04FC97062EB30A00007BD342 /* KBGuideUserCell.m in Sources */,
|
||||
04FC95CF2EB1E7A1007BD342 /* HomeVC.m in Sources */,
|
||||
04C6EABF2EAF86530089C901 /* main.m in Sources */,
|
||||
04FC95CC2EB1E780007BD342 /* BaseTabBarController.m in Sources */,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
//
|
||||
|
||||
#import "HomeVC.h"
|
||||
#import "KBGuideVC.h"
|
||||
|
||||
@interface HomeVC ()
|
||||
|
||||
@@ -27,6 +28,11 @@
|
||||
[self.view addSubview:label];
|
||||
}
|
||||
|
||||
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
|
||||
KBGuideVC *vc = [[KBGuideVC alloc] init];
|
||||
[self.navigationController pushViewController:vc animated:true];
|
||||
}
|
||||
|
||||
/*
|
||||
#pragma mark - Navigation
|
||||
|
||||
|
||||
20
keyBoard/KBGuideKFCell.h
Normal file
20
keyBoard/KBGuideKFCell.h
Normal file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// KBGuideKFCell.h
|
||||
// keyBoard
|
||||
//
|
||||
// 客服回复气泡 cell(左侧头像 + 白色圆角气泡)
|
||||
//
|
||||
|
||||
#import "BaseCell.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface KBGuideKFCell : BaseCell
|
||||
|
||||
/// 设置文案
|
||||
- (void)configText:(NSString *)text;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
77
keyBoard/KBGuideKFCell.m
Normal file
77
keyBoard/KBGuideKFCell.m
Normal file
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// KBGuideKFCell.m
|
||||
// keyBoard
|
||||
//
|
||||
|
||||
#import "KBGuideKFCell.h"
|
||||
|
||||
@interface KBGuideKFCell ()
|
||||
@property (nonatomic, strong) UIView *avatarView; // 左侧头像
|
||||
@property (nonatomic, strong) UIView *bubbleView; // 气泡
|
||||
@property (nonatomic, strong) UILabel *contentLabel; // 文案
|
||||
@end
|
||||
|
||||
@implementation KBGuideKFCell
|
||||
|
||||
- (void)setupUI {
|
||||
self.contentView.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0];
|
||||
|
||||
[self.contentView addSubview:self.avatarView];
|
||||
[self.avatarView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.contentView).offset(16);
|
||||
make.top.equalTo(self.contentView).offset(10);
|
||||
make.width.height.mas_equalTo(36);
|
||||
}];
|
||||
|
||||
[self.contentView addSubview:self.bubbleView];
|
||||
[self.bubbleView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.avatarView.mas_right).offset(8);
|
||||
make.top.equalTo(self.contentView).offset(8);
|
||||
make.right.lessThanOrEqualTo(self.contentView).offset(-80);
|
||||
make.bottom.equalTo(self.contentView).offset(-8);
|
||||
}];
|
||||
|
||||
[self.bubbleView addSubview:self.contentLabel];
|
||||
[self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.equalTo(self.bubbleView).insets(UIEdgeInsetsMake(10, 12, 10, 12));
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)configText:(NSString *)text {
|
||||
self.contentLabel.text = text;
|
||||
}
|
||||
|
||||
#pragma mark - Lazy
|
||||
|
||||
- (UIView *)avatarView {
|
||||
if (!_avatarView) {
|
||||
_avatarView = [UIView new];
|
||||
_avatarView.backgroundColor = [UIColor colorWithRed:0.23 green:0.47 blue:0.96 alpha:1.0];
|
||||
_avatarView.layer.cornerRadius = 18;
|
||||
_avatarView.layer.masksToBounds = YES;
|
||||
}
|
||||
return _avatarView;
|
||||
}
|
||||
|
||||
- (UIView *)bubbleView {
|
||||
if (!_bubbleView) {
|
||||
_bubbleView = [UIView new];
|
||||
_bubbleView.backgroundColor = [UIColor whiteColor];
|
||||
_bubbleView.layer.cornerRadius = 18;
|
||||
_bubbleView.layer.masksToBounds = YES;
|
||||
}
|
||||
return _bubbleView;
|
||||
}
|
||||
|
||||
- (UILabel *)contentLabel {
|
||||
if (!_contentLabel) {
|
||||
_contentLabel = [UILabel new];
|
||||
_contentLabel.numberOfLines = 0;
|
||||
_contentLabel.font = [UIFont systemFontOfSize:15];
|
||||
_contentLabel.textColor = [UIColor colorWithWhite:0.15 alpha:1.0];
|
||||
}
|
||||
return _contentLabel;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
17
keyBoard/KBGuideTopCell.h
Normal file
17
keyBoard/KBGuideTopCell.h
Normal file
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// KBGuideTopCell.h
|
||||
// keyBoard
|
||||
//
|
||||
// 顶部固定引导 cell(左侧头像 + 卡片文案)
|
||||
//
|
||||
|
||||
#import "BaseCell.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface KBGuideTopCell : BaseCell
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
156
keyBoard/KBGuideTopCell.m
Normal file
156
keyBoard/KBGuideTopCell.m
Normal file
@@ -0,0 +1,156 @@
|
||||
//
|
||||
// KBGuideTopCell.m
|
||||
// keyBoard
|
||||
//
|
||||
|
||||
#import "KBGuideTopCell.h"
|
||||
|
||||
@interface KBGuideTopCell ()
|
||||
|
||||
// 左侧头像(占位色块代替图片)
|
||||
@property (nonatomic, strong) UIView *avatarView;
|
||||
// 白色卡片容器
|
||||
@property (nonatomic, strong) UIView *cardView;
|
||||
// 卡片标题/正文
|
||||
@property (nonatomic, strong) UILabel *titleLabel;
|
||||
@property (nonatomic, strong) UILabel *descLabel;
|
||||
@property (nonatomic, strong) UIView *line1;
|
||||
@property (nonatomic, strong) UILabel *q1Label;
|
||||
@property (nonatomic, strong) UIView *line2;
|
||||
@property (nonatomic, strong) UILabel *q2Label;
|
||||
|
||||
@end
|
||||
|
||||
@implementation KBGuideTopCell
|
||||
|
||||
- (void)setupUI {
|
||||
self.contentView.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0];
|
||||
|
||||
// 头像
|
||||
[self.contentView addSubview:self.avatarView];
|
||||
[self.avatarView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.contentView).offset(16);
|
||||
make.top.equalTo(self.contentView).offset(12);
|
||||
make.width.height.mas_equalTo(36);
|
||||
}];
|
||||
|
||||
// 卡片
|
||||
[self.contentView addSubview:self.cardView];
|
||||
[self.cardView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.avatarView.mas_right).offset(8);
|
||||
make.right.lessThanOrEqualTo(self.contentView).offset(-32);
|
||||
make.top.equalTo(self.contentView).offset(8);
|
||||
make.bottom.equalTo(self.contentView).offset(-8);
|
||||
}];
|
||||
|
||||
[self.cardView addSubview:self.titleLabel];
|
||||
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.left.equalTo(self.cardView).offset(12);
|
||||
make.right.equalTo(self.cardView).offset(-12);
|
||||
}];
|
||||
|
||||
[self.cardView addSubview:self.descLabel];
|
||||
[self.descLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.equalTo(self.titleLabel.mas_bottom).offset(6);
|
||||
make.left.right.equalTo(self.titleLabel);
|
||||
}];
|
||||
|
||||
// 分隔、两条示例问题
|
||||
[self.cardView addSubview:self.line1];
|
||||
[self.cardView addSubview:self.q1Label];
|
||||
[self.cardView addSubview:self.line2];
|
||||
[self.cardView addSubview:self.q2Label];
|
||||
|
||||
[self.line1 mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.equalTo(self.descLabel.mas_bottom).offset(10);
|
||||
make.left.right.equalTo(self.cardView);
|
||||
make.height.mas_equalTo(KB_ONE_PIXEL);
|
||||
}];
|
||||
|
||||
[self.q1Label mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.equalTo(self.line1.mas_bottom).offset(10);
|
||||
make.left.right.equalTo(self.titleLabel);
|
||||
}];
|
||||
|
||||
[self.line2 mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.equalTo(self.q1Label.mas_bottom).offset(10);
|
||||
make.left.right.equalTo(self.cardView);
|
||||
make.height.mas_equalTo(KB_ONE_PIXEL);
|
||||
}];
|
||||
|
||||
[self.q2Label mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.equalTo(self.line2.mas_bottom).offset(10);
|
||||
make.left.right.equalTo(self.titleLabel);
|
||||
make.bottom.equalTo(self.cardView).offset(-14);
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Lazy
|
||||
|
||||
- (UIView *)avatarView {
|
||||
if (!_avatarView) {
|
||||
_avatarView = [UIView new];
|
||||
_avatarView.backgroundColor = [UIColor colorWithRed:0.23 green:0.47 blue:0.96 alpha:1.0];
|
||||
_avatarView.layer.cornerRadius = 18;
|
||||
_avatarView.layer.masksToBounds = YES;
|
||||
}
|
||||
return _avatarView;
|
||||
}
|
||||
|
||||
- (UIView *)cardView {
|
||||
if (!_cardView) {
|
||||
_cardView = [UIView new];
|
||||
_cardView.backgroundColor = [UIColor whiteColor];
|
||||
_cardView.layer.cornerRadius = 18;
|
||||
_cardView.layer.masksToBounds = YES;
|
||||
}
|
||||
return _cardView;
|
||||
}
|
||||
|
||||
- (UILabel *)titleLabel {
|
||||
if (!_titleLabel) {
|
||||
_titleLabel = [UILabel new];
|
||||
_titleLabel.numberOfLines = 0;
|
||||
_titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold];
|
||||
_titleLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1.0];
|
||||
_titleLabel.text = @"👋 欢迎使用『Lovekey 键盘』";
|
||||
}
|
||||
return _titleLabel;
|
||||
}
|
||||
|
||||
- (UILabel *)descLabel {
|
||||
if (!_descLabel) {
|
||||
_descLabel = [UILabel new];
|
||||
_descLabel.numberOfLines = 0;
|
||||
_descLabel.font = [UIFont systemFontOfSize:14];
|
||||
_descLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1.0];
|
||||
_descLabel.text = @"点击任一对话去粘贴,选择任意回复方式去试用吧~";
|
||||
}
|
||||
return _descLabel;
|
||||
}
|
||||
|
||||
- (UIView *)line1 { if (!_line1) { _line1 = [UIView new]; _line1.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1.0]; } return _line1; }
|
||||
- (UIView *)line2 { if (!_line2) { _line2 = [UIView new]; _line2.backgroundColor = [UIColor colorWithWhite:0.92 alpha:1.0]; } return _line2; }
|
||||
|
||||
- (UILabel *)q1Label {
|
||||
if (!_q1Label) {
|
||||
_q1Label = [UILabel new];
|
||||
_q1Label.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold];
|
||||
_q1Label.textColor = [UIColor blackColor];
|
||||
_q1Label.text = @"在干嘛?";
|
||||
}
|
||||
return _q1Label;
|
||||
}
|
||||
|
||||
- (UILabel *)q2Label {
|
||||
if (!_q2Label) {
|
||||
_q2Label = [UILabel new];
|
||||
_q2Label.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold];
|
||||
_q2Label.textColor = [UIColor blackColor];
|
||||
_q2Label.text = @"我去洗澡了";
|
||||
}
|
||||
return _q2Label;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
19
keyBoard/KBGuideUserCell.h
Normal file
19
keyBoard/KBGuideUserCell.h
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// KBGuideUserCell.h
|
||||
// keyBoard
|
||||
//
|
||||
// 我方发送气泡 cell(右侧紫色气泡)
|
||||
//
|
||||
|
||||
#import "BaseCell.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface KBGuideUserCell : BaseCell
|
||||
|
||||
- (void)configText:(NSString *)text;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
60
keyBoard/KBGuideUserCell.m
Normal file
60
keyBoard/KBGuideUserCell.m
Normal file
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// KBGuideUserCell.m
|
||||
// keyBoard
|
||||
//
|
||||
|
||||
#import "KBGuideUserCell.h"
|
||||
|
||||
@interface KBGuideUserCell ()
|
||||
@property (nonatomic, strong) UIView *bubbleView; // 右侧紫色气泡
|
||||
@property (nonatomic, strong) UILabel *contentLabel;
|
||||
@end
|
||||
|
||||
@implementation KBGuideUserCell
|
||||
|
||||
- (void)setupUI {
|
||||
self.contentView.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0];
|
||||
|
||||
[self.contentView addSubview:self.bubbleView];
|
||||
[self.bubbleView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.right.equalTo(self.contentView).offset(-16);
|
||||
make.top.equalTo(self.contentView).offset(8);
|
||||
make.left.greaterThanOrEqualTo(self.contentView).offset(80);
|
||||
make.bottom.equalTo(self.contentView).offset(-8);
|
||||
}];
|
||||
|
||||
[self.bubbleView addSubview:self.contentLabel];
|
||||
[self.contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.equalTo(self.bubbleView).insets(UIEdgeInsetsMake(8, 10, 8, 10));
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)configText:(NSString *)text {
|
||||
self.contentLabel.text = text;
|
||||
}
|
||||
|
||||
#pragma mark - Lazy
|
||||
|
||||
- (UIView *)bubbleView {
|
||||
if (!_bubbleView) {
|
||||
_bubbleView = [UIView new];
|
||||
_bubbleView.backgroundColor = [UIColor colorWithRed:0.42 green:0.45 blue:0.98 alpha:1.0];
|
||||
_bubbleView.layer.cornerRadius = 12;
|
||||
_bubbleView.layer.masksToBounds = YES;
|
||||
}
|
||||
return _bubbleView;
|
||||
}
|
||||
|
||||
- (UILabel *)contentLabel {
|
||||
if (!_contentLabel) {
|
||||
_contentLabel = [UILabel new];
|
||||
_contentLabel.numberOfLines = 0;
|
||||
_contentLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightSemibold];
|
||||
_contentLabel.textColor = [UIColor whiteColor];
|
||||
_contentLabel.textAlignment = NSTextAlignmentCenter;
|
||||
}
|
||||
return _contentLabel;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
16
keyBoard/KBGuideVC.h
Normal file
16
keyBoard/KBGuideVC.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// KBGuideVC.h
|
||||
// keyBoard
|
||||
//
|
||||
// Created by Mac on 2025/10/29.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface KBGuideVC : UIViewController
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
227
keyBoard/KBGuideVC.m
Normal file
227
keyBoard/KBGuideVC.m
Normal file
@@ -0,0 +1,227 @@
|
||||
//
|
||||
// KBGuideVC.m
|
||||
// keyBoard
|
||||
//
|
||||
// Created by Mac on 2025/10/29.
|
||||
//
|
||||
|
||||
#import "KBGuideVC.h"
|
||||
#import "KBGuideTopCell.h"
|
||||
#import "KBGuideKFCell.h"
|
||||
#import "KBGuideUserCell.h"
|
||||
|
||||
typedef NS_ENUM(NSInteger, KBGuideItemType) {
|
||||
KBGuideItemTypeTop = 0, // 顶部固定卡片
|
||||
KBGuideItemTypeUser, // 我方消息
|
||||
KBGuideItemTypeKF // 客服回复
|
||||
};
|
||||
|
||||
@interface KBGuideVC () <UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate>
|
||||
|
||||
@property (nonatomic, strong) BaseTableView *tableView; // 列表(继承 BaseTableView)
|
||||
@property (nonatomic, strong) UIView *inputBar; // 底部输入容器
|
||||
@property (nonatomic, strong) UITextField *textField; // 输入框
|
||||
@property (nonatomic, strong) MASConstraint *inputBarBottom;// 输入栏底部约束
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray<NSDictionary *> *items; // 数据源 [{type, text}]
|
||||
|
||||
@end
|
||||
|
||||
@implementation KBGuideVC
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
self.view.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0];
|
||||
self.title = @"使用引导";
|
||||
|
||||
[self.view addSubview:self.tableView];
|
||||
[self.view addSubview:self.inputBar];
|
||||
|
||||
[self.inputBar addSubview:self.textField];
|
||||
|
||||
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.left.right.equalTo(self.view);
|
||||
make.bottom.equalTo(self.view);
|
||||
}];
|
||||
|
||||
[self.inputBar mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.right.equalTo(self.view);
|
||||
make.height.mas_equalTo(52);
|
||||
// 底部跟随键盘变化
|
||||
if (@available(iOS 11.0, *)) {
|
||||
self.inputBarBottom = make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
|
||||
} else {
|
||||
self.inputBarBottom = make.bottom.equalTo(self.view);
|
||||
}
|
||||
}];
|
||||
|
||||
[self.textField mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(self.inputBar).offset(12);
|
||||
make.right.equalTo(self.inputBar).offset(-12);
|
||||
make.centerY.equalTo(self.inputBar);
|
||||
make.height.mas_equalTo(36);
|
||||
}];
|
||||
|
||||
// 初始只有固定 Top
|
||||
[self.items addObject:@{ @"type": @(KBGuideItemTypeTop), @"text": @"" }];
|
||||
[self.tableView reloadData];
|
||||
|
||||
// 键盘监听
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kb_keyboardWillChange:) name:UIKeyboardWillChangeFrameNotification object:nil];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
// 发送:回车发送一条消息,随后插入固定的客服回复
|
||||
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
|
||||
NSString *text = [textField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
if (text.length == 0) { return NO; }
|
||||
|
||||
// 1. 插入我方消息
|
||||
[self.items addObject:@{ @"type": @(KBGuideItemTypeUser), @"text": text ?: @"" }];
|
||||
// 2. 紧跟一条固定客服消息
|
||||
NSString *reply = @"🎉 如您遇到其他问题,可点击在线客服帮您解决~";
|
||||
[self.items addObject:@{ @"type": @(KBGuideItemTypeKF), @"text": reply }];
|
||||
|
||||
// 刷新并滚动到底部
|
||||
[self.tableView reloadData];
|
||||
[self scrollToBottomAnimated:YES];
|
||||
|
||||
textField.text = @"";
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)kb_keyboardWillChange:(NSNotification *)note {
|
||||
NSDictionary *info = note.userInfo;
|
||||
NSTimeInterval duration = [info[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
|
||||
UIViewAnimationOptions curve = ([info[UIKeyboardAnimationCurveUserInfoKey] integerValue] << 16);
|
||||
|
||||
CGRect endFrame = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue];
|
||||
CGFloat screenH = UIScreen.mainScreen.bounds.size.height;
|
||||
CGFloat kbHeight = MAX(0, screenH - endFrame.origin.y);
|
||||
|
||||
CGFloat safeBtm = 0;
|
||||
if (@available(iOS 11.0, *)) { safeBtm = self.view.safeAreaInsets.bottom; }
|
||||
|
||||
// 输入栏距离底部 = -max(kbHeight - 安全区, 0)
|
||||
CGFloat offset = -MAX(kbHeight - safeBtm, 0);
|
||||
self.inputBarBottom.offset = offset;
|
||||
|
||||
[UIView animateWithDuration:duration delay:0 options:curve animations:^{
|
||||
[self.view layoutIfNeeded];
|
||||
// 留出输入栏高度的 contentInset,避免最后一行被遮挡
|
||||
UIEdgeInsets inset = self.tableView.contentInset;
|
||||
inset.bottom = 52 + MAX(kbHeight - safeBtm, 0);
|
||||
self.tableView.contentInset = inset;
|
||||
self.tableView.scrollIndicatorInsets = inset;
|
||||
} completion:^(BOOL finished) {
|
||||
[self scrollToBottomAnimated:YES];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)scrollToBottomAnimated:(BOOL)animated {
|
||||
if (self.items.count == 0) return;
|
||||
NSInteger last = self.items.count - 1;
|
||||
NSIndexPath *ip = [NSIndexPath indexPathForRow:last inSection:0];
|
||||
if (last >= 0) {
|
||||
[self.tableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionBottom animated:animated];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UITableView
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
return self.items.count;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
NSDictionary *it = self.items[indexPath.row];
|
||||
KBGuideItemType type = [it[@"type"] integerValue];
|
||||
NSString *text = it[@"text"] ?: @"";
|
||||
|
||||
if (type == KBGuideItemTypeTop) {
|
||||
KBGuideTopCell *cell = [tableView dequeueReusableCellWithIdentifier:[KBGuideTopCell reuseId]];
|
||||
if (!cell) cell = [[KBGuideTopCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[KBGuideTopCell reuseId]];
|
||||
return cell;
|
||||
} else if (type == KBGuideItemTypeUser) {
|
||||
KBGuideUserCell *cell = [tableView dequeueReusableCellWithIdentifier:[KBGuideUserCell reuseId]];
|
||||
if (!cell) cell = [[KBGuideUserCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[KBGuideUserCell reuseId]];
|
||||
[cell configText:text];
|
||||
return cell;
|
||||
} else {
|
||||
KBGuideKFCell *cell = [tableView dequeueReusableCellWithIdentifier:[KBGuideKFCell reuseId]];
|
||||
if (!cell) cell = [[KBGuideKFCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[KBGuideKFCell reuseId]];
|
||||
[cell configText:text];
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
return UITableViewAutomaticDimension;
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
return 100;
|
||||
}
|
||||
|
||||
#pragma mark - Lazy
|
||||
|
||||
- (BaseTableView *)tableView {
|
||||
if (!_tableView) {
|
||||
_tableView = [[BaseTableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
|
||||
_tableView.delegate = self;
|
||||
_tableView.dataSource = self;
|
||||
_tableView.separatorStyle = UITableViewCellSeparatorStyleNone; // 无分割线
|
||||
_tableView.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0];
|
||||
_tableView.rowHeight = UITableViewAutomaticDimension;
|
||||
_tableView.estimatedRowHeight = 120; // 开启自适应高度
|
||||
_tableView.contentInset = UIEdgeInsetsMake(0, 0, 52 + KB_SafeAreaBottom(), 0);
|
||||
_tableView.scrollIndicatorInsets = _tableView.contentInset;
|
||||
}
|
||||
return _tableView;
|
||||
}
|
||||
|
||||
- (UIView *)inputBar {
|
||||
if (!_inputBar) {
|
||||
_inputBar = [UIView new];
|
||||
_inputBar.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0];
|
||||
UIView *bg = [UIView new];
|
||||
bg.backgroundColor = [UIColor whiteColor];
|
||||
bg.layer.cornerRadius = 10; bg.layer.masksToBounds = YES;
|
||||
[_inputBar addSubview:bg];
|
||||
[bg mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.left.equalTo(_inputBar).offset(12);
|
||||
make.right.equalTo(_inputBar).offset(-12);
|
||||
make.top.equalTo(_inputBar).offset(8);
|
||||
make.bottom.equalTo(_inputBar).offset(-8);
|
||||
}];
|
||||
}
|
||||
return _inputBar;
|
||||
}
|
||||
|
||||
- (UITextField *)textField {
|
||||
if (!_textField) {
|
||||
_textField = [UITextField new];
|
||||
_textField.delegate = self;
|
||||
_textField.returnKeyType = UIReturnKeySend; // 回车发送
|
||||
_textField.font = [UIFont systemFontOfSize:15];
|
||||
_textField.placeholder = @"在键盘粘贴对话后,选择回复方式";
|
||||
_textField.backgroundColor = [UIColor whiteColor];
|
||||
_textField.layer.cornerRadius = 10; _textField.layer.masksToBounds = YES;
|
||||
UIView *pad = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 36)];
|
||||
_textField.leftView = pad; _textField.leftViewMode = UITextFieldViewModeAlways;
|
||||
}
|
||||
return _textField;
|
||||
}
|
||||
|
||||
- (NSMutableArray<NSDictionary *> *)items {
|
||||
if (!_items) { _items = @[].mutableCopy; }
|
||||
return _items;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -16,11 +16,74 @@
|
||||
/// 三方
|
||||
#import <Masonry/Masonry.h>
|
||||
|
||||
/// 系统
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
/// 项目
|
||||
#import "BaseNavigationController.h"
|
||||
#import "BaseTableView.h"
|
||||
#import "BaseCell.h"
|
||||
|
||||
|
||||
//-----------------------------------------------宏定义全局----------------------------------------------------------/
|
||||
/// UI 尺寸/设备宏
|
||||
// 屏幕尺寸
|
||||
#define KB_SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width)
|
||||
#define KB_SCREEN_HEIGHT ([UIScreen mainScreen].bounds.size.height)
|
||||
#define KB_ONE_PIXEL (1.0 / [UIScreen mainScreen].scale)
|
||||
|
||||
// 基础高度
|
||||
#define KB_NAVBAR_BASE_HEIGHT 44.0
|
||||
#define KB_TABBAR_BASE_HEIGHT 49.0
|
||||
|
||||
// 当前 KeyWindow(iOS 13 场景化兼容)
|
||||
static inline UIWindow *KB_KeyWindow(void) {
|
||||
UIWindow *window = nil;
|
||||
if (@available(iOS 13.0, *)) {
|
||||
for (UIScene *scene in UIApplication.sharedApplication.connectedScenes) {
|
||||
if (scene.activationState == UISceneActivationStateForegroundActive && [scene isKindOfClass:[UIWindowScene class]]) {
|
||||
UIWindowScene *ws = (UIWindowScene *)scene;
|
||||
for (UIWindow *w in ws.windows) {
|
||||
if (w.isKeyWindow) { window = w; break; }
|
||||
}
|
||||
if (window) { break; }
|
||||
}
|
||||
}
|
||||
if (!window) { window = UIApplication.sharedApplication.windows.firstObject; }
|
||||
} else {
|
||||
window = UIApplication.sharedApplication.keyWindow;
|
||||
}
|
||||
return window;
|
||||
}
|
||||
|
||||
// Safe Area
|
||||
static inline UIEdgeInsets KB_SafeAreaInsets(void) {
|
||||
if (@available(iOS 11.0, *)) {
|
||||
UIWindow *w = KB_KeyWindow();
|
||||
return w ? w.safeAreaInsets : UIEdgeInsetsZero;
|
||||
}
|
||||
return UIEdgeInsetsZero;
|
||||
}
|
||||
|
||||
static inline CGFloat KB_SafeAreaTop(void) { return KB_SafeAreaInsets().top; }
|
||||
static inline CGFloat KB_SafeAreaBottom(void) { return KB_SafeAreaInsets().bottom; }
|
||||
|
||||
// 状态栏高度(iOS13+ 兼容)
|
||||
static inline CGFloat KB_StatusBarHeight(void) {
|
||||
if (@available(iOS 13.0, *)) {
|
||||
UIWindow *w = KB_KeyWindow();
|
||||
UIStatusBarManager *m = w.windowScene.statusBarManager;
|
||||
return m ? m.statusBarFrame.size.height : 0.0;
|
||||
} else {
|
||||
return UIApplication.sharedApplication.statusBarFrame.size.height;
|
||||
}
|
||||
}
|
||||
|
||||
// 导航栏+状态栏总高度、TabBar 高度、是否异形屏
|
||||
#define KB_STATUSBAR_HEIGHT (KB_StatusBarHeight())
|
||||
#define KB_NAV_TOTAL_HEIGHT (KB_NAVBAR_BASE_HEIGHT + KB_StatusBarHeight())
|
||||
#define KB_TABBAR_HEIGHT (KB_TABBAR_BASE_HEIGHT + KB_SafeAreaBottom())
|
||||
#define KB_IS_IPHONEX_SERIES (KB_SafeAreaBottom() > 0.0)
|
||||
|
||||
|
||||
#endif /* KeyBoardPrefixHeader_pch */
|
||||
|
||||
Reference in New Issue
Block a user