1
This commit is contained in:
@@ -58,6 +58,15 @@
|
|||||||
047920072ED86ABC004E8522 /* kb_guide_keyboard.gif in Resources */ = {isa = PBXBuildFile; fileRef = 047920062ED86ABC004E8522 /* kb_guide_keyboard.gif */; };
|
047920072ED86ABC004E8522 /* kb_guide_keyboard.gif in Resources */ = {isa = PBXBuildFile; fileRef = 047920062ED86ABC004E8522 /* kb_guide_keyboard.gif */; };
|
||||||
0479200B2ED87CEE004E8522 /* permiss_video.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 0479200A2ED87CEE004E8522 /* permiss_video.mp4 */; };
|
0479200B2ED87CEE004E8522 /* permiss_video.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 0479200A2ED87CEE004E8522 /* permiss_video.mp4 */; };
|
||||||
047920112ED98E7D004E8522 /* permiss_video_2.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 047920102ED98E7D004E8522 /* permiss_video_2.mp4 */; };
|
047920112ED98E7D004E8522 /* permiss_video_2.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 047920102ED98E7D004E8522 /* permiss_video_2.mp4 */; };
|
||||||
|
0479204A2EDDCE25004E8522 /* KBUserSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 047920492EDDCE25004E8522 /* KBUserSessionManager.m */; };
|
||||||
|
0479205A2EDEE1FC004E8522 /* CRBoxTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = 047920542EDEE1FC004E8522 /* CRBoxTextView.m */; };
|
||||||
|
0479205B2EDEE1FC004E8522 /* CRSecrectImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 047920582EDEE1FC004E8522 /* CRSecrectImageView.m */; };
|
||||||
|
0479205C2EDEE1FC004E8522 /* CRBoxFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 0479204C2EDEE1FC004E8522 /* CRBoxFlowLayout.m */; };
|
||||||
|
0479205D2EDEE1FC004E8522 /* CRBoxInputView.m in Sources */ = {isa = PBXBuildFile; fileRef = 047920522EDEE1FC004E8522 /* CRBoxInputView.m */; };
|
||||||
|
0479205E2EDEE1FC004E8522 /* CRBoxInputCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 0479204E2EDEE1FC004E8522 /* CRBoxInputCell.m */; };
|
||||||
|
0479205F2EDEE1FC004E8522 /* CRBoxInputCellProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = 047920502EDEE1FC004E8522 /* CRBoxInputCellProperty.m */; };
|
||||||
|
047920602EDEE1FC004E8522 /* CRLineView.m in Sources */ = {isa = PBXBuildFile; fileRef = 047920562EDEE1FC004E8522 /* CRLineView.m */; };
|
||||||
|
047920632EDEEFC7004E8522 /* KBLoginVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 047920622EDEEFC7004E8522 /* KBLoginVC.m */; };
|
||||||
047C650D2EBC8A840035E841 /* KBPanModalView.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C650C2EBC8A840035E841 /* KBPanModalView.m */; };
|
047C650D2EBC8A840035E841 /* KBPanModalView.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C650C2EBC8A840035E841 /* KBPanModalView.m */; };
|
||||||
047C65102EBCA8DD0035E841 /* HomeRankContentVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C650F2EBCA8DD0035E841 /* HomeRankContentVC.m */; };
|
047C65102EBCA8DD0035E841 /* HomeRankContentVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C650F2EBCA8DD0035E841 /* HomeRankContentVC.m */; };
|
||||||
047C65502EBCBA9E0035E841 /* KBShopVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C654F2EBCBA9E0035E841 /* KBShopVC.m */; };
|
047C65502EBCBA9E0035E841 /* KBShopVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 047C654F2EBCBA9E0035E841 /* KBShopVC.m */; };
|
||||||
@@ -274,6 +283,24 @@
|
|||||||
047920062ED86ABC004E8522 /* kb_guide_keyboard.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = kb_guide_keyboard.gif; sourceTree = "<group>"; };
|
047920062ED86ABC004E8522 /* kb_guide_keyboard.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = kb_guide_keyboard.gif; sourceTree = "<group>"; };
|
||||||
0479200A2ED87CEE004E8522 /* permiss_video.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = permiss_video.mp4; sourceTree = "<group>"; };
|
0479200A2ED87CEE004E8522 /* permiss_video.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = permiss_video.mp4; sourceTree = "<group>"; };
|
||||||
047920102ED98E7D004E8522 /* permiss_video_2.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = permiss_video_2.mp4; sourceTree = "<group>"; };
|
047920102ED98E7D004E8522 /* permiss_video_2.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = permiss_video_2.mp4; sourceTree = "<group>"; };
|
||||||
|
047920482EDDCE25004E8522 /* KBUserSessionManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBUserSessionManager.h; sourceTree = "<group>"; };
|
||||||
|
047920492EDDCE25004E8522 /* KBUserSessionManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBUserSessionManager.m; sourceTree = "<group>"; };
|
||||||
|
0479204B2EDEE1FC004E8522 /* CRBoxFlowLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CRBoxFlowLayout.h; sourceTree = "<group>"; };
|
||||||
|
0479204C2EDEE1FC004E8522 /* CRBoxFlowLayout.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CRBoxFlowLayout.m; sourceTree = "<group>"; };
|
||||||
|
0479204D2EDEE1FC004E8522 /* CRBoxInputCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CRBoxInputCell.h; sourceTree = "<group>"; };
|
||||||
|
0479204E2EDEE1FC004E8522 /* CRBoxInputCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CRBoxInputCell.m; sourceTree = "<group>"; };
|
||||||
|
0479204F2EDEE1FC004E8522 /* CRBoxInputCellProperty.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CRBoxInputCellProperty.h; sourceTree = "<group>"; };
|
||||||
|
047920502EDEE1FC004E8522 /* CRBoxInputCellProperty.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CRBoxInputCellProperty.m; sourceTree = "<group>"; };
|
||||||
|
047920512EDEE1FC004E8522 /* CRBoxInputView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CRBoxInputView.h; sourceTree = "<group>"; };
|
||||||
|
047920522EDEE1FC004E8522 /* CRBoxInputView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CRBoxInputView.m; sourceTree = "<group>"; };
|
||||||
|
047920532EDEE1FC004E8522 /* CRBoxTextView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CRBoxTextView.h; sourceTree = "<group>"; };
|
||||||
|
047920542EDEE1FC004E8522 /* CRBoxTextView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CRBoxTextView.m; sourceTree = "<group>"; };
|
||||||
|
047920552EDEE1FC004E8522 /* CRLineView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CRLineView.h; sourceTree = "<group>"; };
|
||||||
|
047920562EDEE1FC004E8522 /* CRLineView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CRLineView.m; sourceTree = "<group>"; };
|
||||||
|
047920572EDEE1FC004E8522 /* CRSecrectImageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CRSecrectImageView.h; sourceTree = "<group>"; };
|
||||||
|
047920582EDEE1FC004E8522 /* CRSecrectImageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CRSecrectImageView.m; sourceTree = "<group>"; };
|
||||||
|
047920612EDEEFC7004E8522 /* KBLoginVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBLoginVC.h; sourceTree = "<group>"; };
|
||||||
|
047920622EDEEFC7004E8522 /* KBLoginVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBLoginVC.m; sourceTree = "<group>"; };
|
||||||
047C650B2EBC8A840035E841 /* KBPanModalView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBPanModalView.h; sourceTree = "<group>"; };
|
047C650B2EBC8A840035E841 /* KBPanModalView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBPanModalView.h; sourceTree = "<group>"; };
|
||||||
047C650C2EBC8A840035E841 /* KBPanModalView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBPanModalView.m; sourceTree = "<group>"; };
|
047C650C2EBC8A840035E841 /* KBPanModalView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBPanModalView.m; sourceTree = "<group>"; };
|
||||||
047C650E2EBCA8DD0035E841 /* HomeRankContentVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeRankContentVC.h; sourceTree = "<group>"; };
|
047C650E2EBCA8DD0035E841 /* HomeRankContentVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeRankContentVC.h; sourceTree = "<group>"; };
|
||||||
@@ -628,6 +655,27 @@
|
|||||||
path = FunctionTest;
|
path = FunctionTest;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
047920592EDEE1FC004E8522 /* CRBoxInputView */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
0479204B2EDEE1FC004E8522 /* CRBoxFlowLayout.h */,
|
||||||
|
0479204C2EDEE1FC004E8522 /* CRBoxFlowLayout.m */,
|
||||||
|
0479204D2EDEE1FC004E8522 /* CRBoxInputCell.h */,
|
||||||
|
0479204E2EDEE1FC004E8522 /* CRBoxInputCell.m */,
|
||||||
|
0479204F2EDEE1FC004E8522 /* CRBoxInputCellProperty.h */,
|
||||||
|
047920502EDEE1FC004E8522 /* CRBoxInputCellProperty.m */,
|
||||||
|
047920512EDEE1FC004E8522 /* CRBoxInputView.h */,
|
||||||
|
047920522EDEE1FC004E8522 /* CRBoxInputView.m */,
|
||||||
|
047920532EDEE1FC004E8522 /* CRBoxTextView.h */,
|
||||||
|
047920542EDEE1FC004E8522 /* CRBoxTextView.m */,
|
||||||
|
047920552EDEE1FC004E8522 /* CRLineView.h */,
|
||||||
|
047920562EDEE1FC004E8522 /* CRLineView.m */,
|
||||||
|
047920572EDEE1FC004E8522 /* CRSecrectImageView.h */,
|
||||||
|
047920582EDEE1FC004E8522 /* CRSecrectImageView.m */,
|
||||||
|
);
|
||||||
|
path = CRBoxInputView;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
047C652C2EBCAAAC0035E841 /* Resource */ = {
|
047C652C2EBCAAAC0035E841 /* Resource */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -791,6 +839,7 @@
|
|||||||
04122F6C2EC5F40800EF7AB3 /* FGIAPService */,
|
04122F6C2EC5F40800EF7AB3 /* FGIAPService */,
|
||||||
049FB2162EC20A6600FAB05D /* BMLongPressDragCellCollectionView */,
|
049FB2162EC20A6600FAB05D /* BMLongPressDragCellCollectionView */,
|
||||||
048908D92EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout */,
|
048908D92EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout */,
|
||||||
|
047920592EDEE1FC004E8522 /* CRBoxInputView */,
|
||||||
);
|
);
|
||||||
path = Vender;
|
path = Vender;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -1255,6 +1304,8 @@
|
|||||||
04FC95F02EB339A7007BD342 /* LoginViewController.m */,
|
04FC95F02EB339A7007BD342 /* LoginViewController.m */,
|
||||||
04FC96112EB34E00007BD342 /* KBLoginSheetViewController.h */,
|
04FC96112EB34E00007BD342 /* KBLoginSheetViewController.h */,
|
||||||
04FC96122EB34E00007BD342 /* KBLoginSheetViewController.m */,
|
04FC96122EB34E00007BD342 /* KBLoginSheetViewController.m */,
|
||||||
|
047920612EDEEFC7004E8522 /* KBLoginVC.h */,
|
||||||
|
047920622EDEEFC7004E8522 /* KBLoginVC.m */,
|
||||||
);
|
);
|
||||||
path = VC;
|
path = VC;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -1277,6 +1328,8 @@
|
|||||||
04FC95F32EB339C1007BD342 /* AppleSignInManager.m */,
|
04FC95F32EB339C1007BD342 /* AppleSignInManager.m */,
|
||||||
04286A042ECC81B200CE730C /* KBSkinService.h */,
|
04286A042ECC81B200CE730C /* KBSkinService.h */,
|
||||||
04286A052ECC81B200CE730C /* KBSkinService.m */,
|
04286A052ECC81B200CE730C /* KBSkinService.m */,
|
||||||
|
047920482EDDCE25004E8522 /* KBUserSessionManager.h */,
|
||||||
|
047920492EDDCE25004E8522 /* KBUserSessionManager.m */,
|
||||||
);
|
);
|
||||||
path = Manager;
|
path = Manager;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -1597,6 +1650,7 @@
|
|||||||
04122F622EC5F41D00EF7AB3 /* KBUser.m in Sources */,
|
04122F622EC5F41D00EF7AB3 /* KBUser.m in Sources */,
|
||||||
04122F8B2EC6F7C800EF7AB3 /* IAPVerifyTransactionObj.m in Sources */,
|
04122F8B2EC6F7C800EF7AB3 /* IAPVerifyTransactionObj.m in Sources */,
|
||||||
04286A062ECC81B200CE730C /* KBSkinService.m in Sources */,
|
04286A062ECC81B200CE730C /* KBSkinService.m in Sources */,
|
||||||
|
0479204A2EDDCE25004E8522 /* KBUserSessionManager.m in Sources */,
|
||||||
04122FAD2EC73C0100EF7AB3 /* KBVipSubscribeCell.m in Sources */,
|
04122FAD2EC73C0100EF7AB3 /* KBVipSubscribeCell.m in Sources */,
|
||||||
049FB31D2EC21BCD00FAB05D /* KBMyKeyboardCell.m in Sources */,
|
049FB31D2EC21BCD00FAB05D /* KBMyKeyboardCell.m in Sources */,
|
||||||
048909F62EC0AAAA00FABA60 /* KBCategoryTitleCell.m in Sources */,
|
048909F62EC0AAAA00FABA60 /* KBCategoryTitleCell.m in Sources */,
|
||||||
@@ -1657,6 +1711,7 @@
|
|||||||
0477BDFA2EBC66340055D639 /* HomeHeadView.m in Sources */,
|
0477BDFA2EBC66340055D639 /* HomeHeadView.m in Sources */,
|
||||||
04FC97032EB30A00007BD342 /* KBGuideKFCell.m in Sources */,
|
04FC97032EB30A00007BD342 /* KBGuideKFCell.m in Sources */,
|
||||||
04FC97062EB30A00007BD342 /* KBGuideUserCell.m in Sources */,
|
04FC97062EB30A00007BD342 /* KBGuideUserCell.m in Sources */,
|
||||||
|
047920632EDEEFC7004E8522 /* KBLoginVC.m in Sources */,
|
||||||
04FC97092EB31B14007BD342 /* KBHUD.m in Sources */,
|
04FC97092EB31B14007BD342 /* KBHUD.m in Sources */,
|
||||||
04FC970E2EB334F8007BD342 /* UIImageView+KBWebImage.m in Sources */,
|
04FC970E2EB334F8007BD342 /* UIImageView+KBWebImage.m in Sources */,
|
||||||
049FB2232EC311F900FAB05D /* KBPersonInfoVC.m in Sources */,
|
049FB2232EC311F900FAB05D /* KBPersonInfoVC.m in Sources */,
|
||||||
@@ -1674,6 +1729,13 @@
|
|||||||
048908DA2EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout.m in Sources */,
|
048908DA2EBF61AF00FABA60 /* UICollectionViewLeftAlignedLayout.m in Sources */,
|
||||||
04C6EABF2EAF86530089C901 /* main.m in Sources */,
|
04C6EABF2EAF86530089C901 /* main.m in Sources */,
|
||||||
04FC95CC2EB1E780007BD342 /* BaseTabBarController.m in Sources */,
|
04FC95CC2EB1E780007BD342 /* BaseTabBarController.m in Sources */,
|
||||||
|
0479205A2EDEE1FC004E8522 /* CRBoxTextView.m in Sources */,
|
||||||
|
0479205B2EDEE1FC004E8522 /* CRSecrectImageView.m in Sources */,
|
||||||
|
0479205C2EDEE1FC004E8522 /* CRBoxFlowLayout.m in Sources */,
|
||||||
|
0479205D2EDEE1FC004E8522 /* CRBoxInputView.m in Sources */,
|
||||||
|
0479205E2EDEE1FC004E8522 /* CRBoxInputCell.m in Sources */,
|
||||||
|
0479205F2EDEE1FC004E8522 /* CRBoxInputCellProperty.m in Sources */,
|
||||||
|
047920602EDEE1FC004E8522 /* CRLineView.m in Sources */,
|
||||||
047C65502EBCBA9E0035E841 /* KBShopVC.m in Sources */,
|
047C65502EBCBA9E0035E841 /* KBShopVC.m in Sources */,
|
||||||
0477BE042EBC83130055D639 /* HomeMainVC.m in Sources */,
|
0477BE042EBC83130055D639 /* HomeMainVC.m in Sources */,
|
||||||
0477BDFD2EBC6A170055D639 /* HomeHotVC.m in Sources */,
|
0477BDFD2EBC6A170055D639 /* HomeHotVC.m in Sources */,
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
#import "KBSexSelVC.h"
|
#import "KBSexSelVC.h"
|
||||||
#import "KBKeyboardPermissionManager.h"
|
#import "KBKeyboardPermissionManager.h"
|
||||||
#import "KBVipPay.h"
|
#import "KBVipPay.h"
|
||||||
|
#import "KBUserSessionManager.h"
|
||||||
|
#import "KBLoginVC.h"
|
||||||
|
|
||||||
// 注意:用于判断系统已启用本输入法扩展的 bundle id 需与扩展 target 的
|
// 注意:用于判断系统已启用本输入法扩展的 bundle id 需与扩展 target 的
|
||||||
// PRODUCT_BUNDLE_IDENTIFIER 完全一致。
|
// PRODUCT_BUNDLE_IDENTIFIER 完全一致。
|
||||||
@@ -38,6 +40,9 @@
|
|||||||
[[FGIAPManager shared] setConfigureWith:[IAPVerifyTransactionObj new]];
|
[[FGIAPManager shared] setConfigureWith:[IAPVerifyTransactionObj new]];
|
||||||
/// 2:配置国际化
|
/// 2:配置国际化
|
||||||
[KBLocalizationManager shared].supportedLanguageCodes = @[ @"en", @"zh-Hans"];
|
[KBLocalizationManager shared].supportedLanguageCodes = @[ @"en", @"zh-Hans"];
|
||||||
|
/// 3 : 处理token问题
|
||||||
|
// [[KBUserSessionManager shared] bootstrapIfNeeded];
|
||||||
|
|
||||||
|
|
||||||
// 首次安装/升级:重置“完全访问”记录,避免继承旧安装遗留在 Keychain 中的状态
|
// 首次安装/升级:重置“完全访问”记录,避免继承旧安装遗留在 Keychain 中的状态
|
||||||
static NSString *const kKBFullAccessRecordInitializedKey = @"KBFullAccessRecordInitialized";
|
static NSString *const kKBFullAccessRecordInitializedKey = @"KBFullAccessRecordInitialized";
|
||||||
@@ -49,12 +54,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 首次安装先进入性别选择页;点击 Skip 或确认后再进入主 TabBar
|
// 首次安装先进入性别选择页;点击 Skip 或确认后再进入主 TabBar
|
||||||
BOOL hasShownSexVC = [[NSUserDefaults standardUserDefaults] boolForKey:KBSexSelectShownKey];
|
// BOOL hasShownSexVC = [[NSUserDefaults standardUserDefaults] boolForKey:KBSexSelectShownKey];
|
||||||
if (hasShownSexVC) {
|
// if (hasShownSexVC) {
|
||||||
[self setupRootVC];
|
// [self setupRootVC];
|
||||||
} else {
|
// } else {
|
||||||
[self setupSexSelectRootVC];
|
[self setupSexSelectRootVC];
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 主工程默认开启网络总开关(键盘扩展仍需用户允许完全访问后再行开启)
|
// 主工程默认开启网络总开关(键盘扩展仍需用户允许完全访问后再行开启)
|
||||||
[KBNetworkManager shared].enabled = YES;
|
[KBNetworkManager shared].enabled = YES;
|
||||||
@@ -93,9 +98,13 @@
|
|||||||
|
|
||||||
/// 首次安装时,展示性别选择页作为根控制器
|
/// 首次安装时,展示性别选择页作为根控制器
|
||||||
- (void)setupSexSelectRootVC {
|
- (void)setupSexSelectRootVC {
|
||||||
|
KBLoginVC *vc = [[KBLoginVC alloc] init];
|
||||||
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||||
self.window.backgroundColor = [UIColor whiteColor];
|
self.window.backgroundColor = [UIColor whiteColor];
|
||||||
[self.window makeKeyAndVisible];
|
[self.window makeKeyAndVisible];
|
||||||
|
self.window.rootViewController = vc;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
KBSexSelVC *sexVC = [KBSexSelVC new];
|
KBSexSelVC *sexVC = [KBSexSelVC new];
|
||||||
__weak typeof(self) weakSelf = self;
|
__weak typeof(self) weakSelf = self;
|
||||||
|
|||||||
6
keyBoard/Assets.xcassets/Login/Contents.json
Normal file
6
keyBoard/Assets.xcassets/Login/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
22
keyBoard/Assets.xcassets/Login/login_bg_icon.imageset/Contents.json
vendored
Normal file
22
keyBoard/Assets.xcassets/Login/login_bg_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "login_bg_icon@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "login_bg_icon@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Login/login_bg_icon.imageset/login_bg_icon@2x.png
vendored
Normal file
BIN
keyBoard/Assets.xcassets/Login/login_bg_icon.imageset/login_bg_icon@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
BIN
keyBoard/Assets.xcassets/Login/login_bg_icon.imageset/login_bg_icon@3x.png
vendored
Normal file
BIN
keyBoard/Assets.xcassets/Login/login_bg_icon.imageset/login_bg_icon@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.7 MiB |
22
keyBoard/Assets.xcassets/Login/login_email_icon.imageset/Contents.json
vendored
Normal file
22
keyBoard/Assets.xcassets/Login/login_email_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "login_email_icon@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "login_email_icon@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Login/login_email_icon.imageset/login_email_icon@2x.png
vendored
Normal file
BIN
keyBoard/Assets.xcassets/Login/login_email_icon.imageset/login_email_icon@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 753 B |
BIN
keyBoard/Assets.xcassets/Login/login_email_icon.imageset/login_email_icon@3x.png
vendored
Normal file
BIN
keyBoard/Assets.xcassets/Login/login_email_icon.imageset/login_email_icon@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
22
keyBoard/Assets.xcassets/Login/login_jianp_icon.imageset/Contents.json
vendored
Normal file
22
keyBoard/Assets.xcassets/Login/login_jianp_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "login_jianp_icon@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "login_jianp_icon@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/Login/login_jianp_icon.imageset/login_jianp_icon@2x.png
vendored
Normal file
BIN
keyBoard/Assets.xcassets/Login/login_jianp_icon.imageset/login_jianp_icon@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 252 KiB |
BIN
keyBoard/Assets.xcassets/Login/login_jianp_icon.imageset/login_jianp_icon@3x.png
vendored
Normal file
BIN
keyBoard/Assets.xcassets/Login/login_jianp_icon.imageset/login_jianp_icon@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 515 KiB |
16
keyBoard/Class/Login/VC/KBLoginVC.h
Normal file
16
keyBoard/Class/Login/VC/KBLoginVC.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// KBLoginVC.h
|
||||||
|
// keyBoard
|
||||||
|
//
|
||||||
|
// Created by Mac on 2025/12/2.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "BaseViewController.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface KBLoginVC : BaseViewController
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
308
keyBoard/Class/Login/VC/KBLoginVC.m
Normal file
308
keyBoard/Class/Login/VC/KBLoginVC.m
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
//
|
||||||
|
// KBLoginVC.m
|
||||||
|
// keyBoard
|
||||||
|
//
|
||||||
|
// Created by Mac on 2025/12/2.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "KBLoginVC.h"
|
||||||
|
#import <AuthenticationServices/AuthenticationServices.h>
|
||||||
|
|
||||||
|
@interface KBLoginVC ()
|
||||||
|
|
||||||
|
// 背景
|
||||||
|
@property (nonatomic, strong) UIImageView *bgImageView; // 整体背景图:login_bg_icon
|
||||||
|
@property (nonatomic, strong) UIImageView *topRightImageView; // 顶部右侧装饰图:login_jianp_icon
|
||||||
|
|
||||||
|
// 底部白色容器(仅上圆角 26)
|
||||||
|
@property (nonatomic, strong) UIView *contentContainerView;
|
||||||
|
|
||||||
|
// 标题
|
||||||
|
@property (nonatomic, strong) UILabel *titleLabel;
|
||||||
|
|
||||||
|
// 按钮
|
||||||
|
@property (nonatomic, strong) UIControl *appleLoginButton; // Apple 原生登录按钮(iOS13 以下降级为普通按钮)
|
||||||
|
@property (nonatomic, strong) UIButton *emailLoginButton; // 邮箱登录按钮
|
||||||
|
|
||||||
|
// 协议 & 底部文案
|
||||||
|
@property (nonatomic, strong) UILabel *agreementLabel; // “By Continuing, You Agree To Our”
|
||||||
|
@property (nonatomic, strong) UIButton *policyButton; // “Terms Of Service & Privacy Policy”
|
||||||
|
|
||||||
|
@property (nonatomic, strong) UILabel *noAccountLabel; // “Don't Have An Account?”
|
||||||
|
@property (nonatomic, strong) UIButton *signUpButton; // “Sign Up”
|
||||||
|
@property (nonatomic, strong) UIButton *forgotPasswordButton; // “Forgot Password?”
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation KBLoginVC
|
||||||
|
|
||||||
|
- (void)viewDidLoad {
|
||||||
|
[super viewDidLoad];
|
||||||
|
// 使用全屏内容,隐藏自定义导航栏
|
||||||
|
self.kb_enableCustomNavBar = NO;
|
||||||
|
self.view.backgroundColor = [UIColor whiteColor];
|
||||||
|
|
||||||
|
[self setupUI];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewDidLayoutSubviews {
|
||||||
|
[super viewDidLayoutSubviews];
|
||||||
|
// 仅白色容器的左上、右上圆角为 26
|
||||||
|
if (!CGRectIsEmpty(self.contentContainerView.bounds)) {
|
||||||
|
UIRectCorner corners = UIRectCornerTopLeft | UIRectCornerTopRight;
|
||||||
|
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.contentContainerView.bounds
|
||||||
|
byRoundingCorners:corners
|
||||||
|
cornerRadii:CGSizeMake(26, 26)];
|
||||||
|
CAShapeLayer *mask = [CAShapeLayer layer];
|
||||||
|
mask.frame = self.contentContainerView.bounds;
|
||||||
|
mask.path = path.CGPath;
|
||||||
|
self.contentContainerView.layer.mask = mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - UI
|
||||||
|
|
||||||
|
- (void)setupUI {
|
||||||
|
// 背景图
|
||||||
|
[self.view addSubview:self.bgImageView];
|
||||||
|
[self.bgImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.edges.equalTo(self.view);
|
||||||
|
}];
|
||||||
|
|
||||||
|
// 顶部右侧装饰图
|
||||||
|
[self.view addSubview:self.topRightImageView];
|
||||||
|
[self.topRightImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.top.equalTo(self.view).offset(KB_StatusBarHeight() + KBFit(24));
|
||||||
|
make.right.equalTo(self.view).offset(-KBFit(20));
|
||||||
|
make.width.mas_equalTo(KBFit(244));
|
||||||
|
make.height.mas_equalTo(KBFit(224));
|
||||||
|
}];
|
||||||
|
|
||||||
|
// 底部白色容器
|
||||||
|
[self.view addSubview:self.contentContainerView];
|
||||||
|
[self.contentContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.left.right.bottom.equalTo(self.view);
|
||||||
|
// 顶部位置大致贴合设计稿,可根据实际效果微调
|
||||||
|
make.top.equalTo(self.view).offset(272);
|
||||||
|
}];
|
||||||
|
|
||||||
|
// 标题
|
||||||
|
[self.contentContainerView addSubview:self.titleLabel];
|
||||||
|
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.top.equalTo(self.contentContainerView).offset(32);
|
||||||
|
make.centerX.equalTo(self.contentContainerView);
|
||||||
|
}];
|
||||||
|
|
||||||
|
// Apple 登录按钮
|
||||||
|
[self.contentContainerView addSubview:self.appleLoginButton];
|
||||||
|
[self.appleLoginButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.top.equalTo(self.titleLabel.mas_bottom).offset(24);
|
||||||
|
make.left.equalTo(self.contentContainerView).offset(30);
|
||||||
|
make.right.equalTo(self.contentContainerView).offset(-30);
|
||||||
|
make.height.mas_equalTo(52);
|
||||||
|
}];
|
||||||
|
|
||||||
|
// 邮箱登录按钮
|
||||||
|
[self.contentContainerView addSubview:self.emailLoginButton];
|
||||||
|
[self.emailLoginButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.top.equalTo(self.appleLoginButton.mas_bottom).offset(16);
|
||||||
|
make.left.right.height.equalTo(self.appleLoginButton);
|
||||||
|
}];
|
||||||
|
|
||||||
|
// 底部协议文案
|
||||||
|
[self.contentContainerView addSubview:self.policyButton];
|
||||||
|
[self.contentContainerView addSubview:self.agreementLabel];
|
||||||
|
|
||||||
|
[self.policyButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.centerX.equalTo(self.contentContainerView);
|
||||||
|
make.bottom.equalTo(self.contentContainerView).offset(-KB_SAFE_BOTTOM - 84);
|
||||||
|
}];
|
||||||
|
|
||||||
|
[self.agreementLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.centerX.equalTo(self.contentContainerView);
|
||||||
|
make.bottom.equalTo(self.policyButton.mas_top).offset(-4);
|
||||||
|
}];
|
||||||
|
|
||||||
|
// 底部账号相关文案
|
||||||
|
UIButton *forgot = self.forgotPasswordButton;
|
||||||
|
[self.contentContainerView addSubview:forgot];
|
||||||
|
[forgot mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.centerX.equalTo(self.contentContainerView);
|
||||||
|
make.bottom.equalTo(self.contentContainerView).offset(-KB_SAFE_BOTTOM - 24);
|
||||||
|
}];
|
||||||
|
|
||||||
|
UIView *accountLine = [UIView new];
|
||||||
|
[self.contentContainerView addSubview:accountLine];
|
||||||
|
[accountLine mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.centerX.equalTo(self.contentContainerView);
|
||||||
|
make.bottom.equalTo(forgot.mas_top).offset(-8);
|
||||||
|
}];
|
||||||
|
|
||||||
|
[accountLine addSubview:self.noAccountLabel];
|
||||||
|
[accountLine addSubview:self.signUpButton];
|
||||||
|
|
||||||
|
[self.noAccountLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.top.left.bottom.equalTo(accountLine);
|
||||||
|
}];
|
||||||
|
|
||||||
|
[self.signUpButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.left.equalTo(self.noAccountLabel.mas_right).offset(4);
|
||||||
|
make.right.equalTo(accountLine);
|
||||||
|
make.centerY.equalTo(self.noAccountLabel);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Actions
|
||||||
|
|
||||||
|
- (void)onTapAppleLogin {
|
||||||
|
// 后续可接入 Apple Sign-In 逻辑,这里先占位
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onTapEmailLogin {
|
||||||
|
// 后续接入邮箱登录逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onTapPolicy {
|
||||||
|
// 打开服务条款/隐私政策
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onTapSignUp {
|
||||||
|
// 打开注册页
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onTapForgotPassword {
|
||||||
|
// 打开忘记密码页
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Lazy UI
|
||||||
|
|
||||||
|
- (UIImageView *)bgImageView {
|
||||||
|
if (!_bgImageView) {
|
||||||
|
_bgImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"login_bg_icon"]];
|
||||||
|
_bgImageView.contentMode = UIViewContentModeScaleAspectFill;
|
||||||
|
_bgImageView.clipsToBounds = YES;
|
||||||
|
}
|
||||||
|
return _bgImageView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIImageView *)topRightImageView {
|
||||||
|
if (!_topRightImageView) {
|
||||||
|
_topRightImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"login_jianp_icon"]];
|
||||||
|
_topRightImageView.contentMode = UIViewContentModeScaleAspectFit;
|
||||||
|
_topRightImageView.clipsToBounds = YES;
|
||||||
|
}
|
||||||
|
return _topRightImageView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIView *)contentContainerView {
|
||||||
|
if (!_contentContainerView) {
|
||||||
|
_contentContainerView = [UIView new];
|
||||||
|
_contentContainerView.backgroundColor = [UIColor whiteColor];
|
||||||
|
}
|
||||||
|
return _contentContainerView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UILabel *)titleLabel {
|
||||||
|
if (!_titleLabel) {
|
||||||
|
_titleLabel = [UILabel new];
|
||||||
|
_titleLabel.text = KBLocalized(@"Log In To Key Of Love");
|
||||||
|
_titleLabel.textColor = [UIColor colorWithHex:KBBlackValue];
|
||||||
|
_titleLabel.font = [KBFont bold:18];
|
||||||
|
_titleLabel.textAlignment = NSTextAlignmentCenter;
|
||||||
|
}
|
||||||
|
return _titleLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIControl *)appleLoginButton {
|
||||||
|
if (!_appleLoginButton) {
|
||||||
|
ASAuthorizationAppleIDButton *btn = [ASAuthorizationAppleIDButton buttonWithType:ASAuthorizationAppleIDButtonTypeSignIn
|
||||||
|
style:ASAuthorizationAppleIDButtonStyleWhite];
|
||||||
|
[btn addTarget:self action:@selector(onTapAppleLogin) forControlEvents:UIControlEventTouchUpInside];
|
||||||
|
btn.cornerRadius = 10.0;
|
||||||
|
btn.layer.borderColor = [UIColor colorWithHex:0xE5E5E5].CGColor;
|
||||||
|
btn.layer.borderWidth = 1;
|
||||||
|
_appleLoginButton = btn;
|
||||||
|
}
|
||||||
|
return _appleLoginButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIButton *)emailLoginButton {
|
||||||
|
if (!_emailLoginButton) {
|
||||||
|
_emailLoginButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||||
|
[_emailLoginButton setTitle:KBLocalized(@"Continue Via Email") forState:UIControlStateNormal];
|
||||||
|
[_emailLoginButton setTitleColor:[UIColor colorWithHex:KBBlackValue] forState:UIControlStateNormal];
|
||||||
|
_emailLoginButton.titleLabel.font = [KBFont medium:16];
|
||||||
|
_emailLoginButton.backgroundColor = [UIColor colorWithHex:0xF7F7F7];
|
||||||
|
_emailLoginButton.layer.cornerRadius = 10.0;
|
||||||
|
_emailLoginButton.layer.masksToBounds = YES;
|
||||||
|
|
||||||
|
UIImage *icon = [UIImage imageNamed:@"login_email_icon"];
|
||||||
|
if (icon) {
|
||||||
|
[_emailLoginButton setImage:icon forState:UIControlStateNormal];
|
||||||
|
// 图片在左,文字在右,保持与截图类似
|
||||||
|
_emailLoginButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
|
||||||
|
_emailLoginButton.imageEdgeInsets = UIEdgeInsetsMake(0, 16, 0, 0);
|
||||||
|
_emailLoginButton.titleEdgeInsets = UIEdgeInsetsMake(0, 32, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[_emailLoginButton addTarget:self action:@selector(onTapEmailLogin) forControlEvents:UIControlEventTouchUpInside];
|
||||||
|
}
|
||||||
|
return _emailLoginButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UILabel *)agreementLabel {
|
||||||
|
if (!_agreementLabel) {
|
||||||
|
_agreementLabel = [UILabel new];
|
||||||
|
_agreementLabel.text = KBLocalized(@"By Continuing, You Agree To Our");
|
||||||
|
_agreementLabel.font = [KBFont regular:12];
|
||||||
|
_agreementLabel.textColor = [UIColor colorWithWhite:0.45 alpha:1.0];
|
||||||
|
_agreementLabel.textAlignment = NSTextAlignmentCenter;
|
||||||
|
_agreementLabel.numberOfLines = 1;
|
||||||
|
}
|
||||||
|
return _agreementLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIButton *)policyButton {
|
||||||
|
if (!_policyButton) {
|
||||||
|
_policyButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||||
|
[_policyButton setTitle:KBLocalized(@"Terms Of Service & Privacy Policy") forState:UIControlStateNormal];
|
||||||
|
[_policyButton setTitleColor:[UIColor colorWithHex:KBColorValue] forState:UIControlStateNormal];
|
||||||
|
_policyButton.titleLabel.font = [KBFont regular:12];
|
||||||
|
[_policyButton addTarget:self action:@selector(onTapPolicy) forControlEvents:UIControlEventTouchUpInside];
|
||||||
|
}
|
||||||
|
return _policyButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UILabel *)noAccountLabel {
|
||||||
|
if (!_noAccountLabel) {
|
||||||
|
_noAccountLabel = [UILabel new];
|
||||||
|
_noAccountLabel.text = KBLocalized(@"Don't Have An Account?");
|
||||||
|
_noAccountLabel.font = [KBFont regular:13];
|
||||||
|
_noAccountLabel.textColor = [UIColor colorWithWhite:0.45 alpha:1.0];
|
||||||
|
}
|
||||||
|
return _noAccountLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIButton *)signUpButton {
|
||||||
|
if (!_signUpButton) {
|
||||||
|
_signUpButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||||
|
[_signUpButton setTitle:KBLocalized(@"Sign Up") forState:UIControlStateNormal];
|
||||||
|
[_signUpButton setTitleColor:[UIColor colorWithHex:KBColorValue] forState:UIControlStateNormal];
|
||||||
|
_signUpButton.titleLabel.font = [KBFont medium:13];
|
||||||
|
[_signUpButton addTarget:self action:@selector(onTapSignUp) forControlEvents:UIControlEventTouchUpInside];
|
||||||
|
}
|
||||||
|
return _signUpButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIButton *)forgotPasswordButton {
|
||||||
|
if (!_forgotPasswordButton) {
|
||||||
|
_forgotPasswordButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||||
|
[_forgotPasswordButton setTitle:KBLocalized(@"Forgot Password?") forState:UIControlStateNormal];
|
||||||
|
[_forgotPasswordButton setTitleColor:[UIColor colorWithHex:KBColorValue] forState:UIControlStateNormal];
|
||||||
|
_forgotPasswordButton.titleLabel.font = [KBFont regular:13];
|
||||||
|
[_forgotPasswordButton addTarget:self action:@selector(onTapForgotPassword) forControlEvents:UIControlEventTouchUpInside];
|
||||||
|
}
|
||||||
|
return _forgotPasswordButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
42
keyBoard/Class/Manager/KBUserSessionManager.h
Normal file
42
keyBoard/Class/Manager/KBUserSessionManager.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
//
|
||||||
|
// KBUserSessionManager.h
|
||||||
|
// keyBoard
|
||||||
|
//
|
||||||
|
// Created by Mac on 2025/12/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
// KBUserSessionManager.h
|
||||||
|
// 主 App + 键盘扩展 共用的登录会话管理
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@class KBUser;
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface KBUserSessionManager : NSObject
|
||||||
|
|
||||||
|
+ (instancetype)shared;
|
||||||
|
|
||||||
|
/// 当前登录用户(可能为 nil)
|
||||||
|
@property (atomic, strong, readonly, nullable) KBUser *currentUser;
|
||||||
|
|
||||||
|
/// 是否已登录:由 KBAuthManager 基于 accessToken 判断
|
||||||
|
@property (nonatomic, assign, readonly) BOOL isLoggedIn;
|
||||||
|
|
||||||
|
/// 启动时调用:做“卸载重装”检测 & 恢复本地缓存
|
||||||
|
- (void)bootstrapIfNeeded;
|
||||||
|
|
||||||
|
/// 当前 accessToken,可能为 nil/空字符串
|
||||||
|
- (nullable NSString *)accessToken;
|
||||||
|
|
||||||
|
/// 登录成功统一入口:写 Keychain + 缓存用户信息
|
||||||
|
- (void)handleLoginSuccessWithUser:(KBUser *)user;
|
||||||
|
|
||||||
|
/// 退出登录:清 Keychain + 本地缓存
|
||||||
|
- (void)logout;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
155
keyBoard/Class/Manager/KBUserSessionManager.m
Normal file
155
keyBoard/Class/Manager/KBUserSessionManager.m
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
//
|
||||||
|
// KBUserSessionManager.m
|
||||||
|
// keyBoard
|
||||||
|
//
|
||||||
|
// Created by Mac on 2025/12/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "KBUserSessionManager.h"
|
||||||
|
#import "KBAuthManager.h"
|
||||||
|
#import "KBUser.h"
|
||||||
|
#import "KBConfig.h"
|
||||||
|
#import <MJExtension/MJExtension.h>
|
||||||
|
|
||||||
|
/// App Group 里的用户缓存 key
|
||||||
|
static NSString * const kKBSessionUserStoreKey = @"KBSession.currentUser";
|
||||||
|
/// “本次安装是否已初始化”标记 key(用来识别卸载重装)
|
||||||
|
static NSString * const kKBSessionInstallFlagKey = @"KBSession.installInitialized";
|
||||||
|
|
||||||
|
@interface KBUserSessionManager ()
|
||||||
|
@property (nonatomic, strong) NSUserDefaults *defaults;
|
||||||
|
@property (atomic, strong, readwrite, nullable) KBUser *currentUser;
|
||||||
|
@property (nonatomic, assign) BOOL didBootstrap;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation KBUserSessionManager
|
||||||
|
|
||||||
|
+ (instancetype)shared {
|
||||||
|
static KBUserSessionManager *m;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
m = [KBUserSessionManager new];
|
||||||
|
});
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)init {
|
||||||
|
if (self = [super init]) {
|
||||||
|
// 优先用 App Group 的 UserDefaults,App 和扩展共用一份
|
||||||
|
NSUserDefaults *ud = [[NSUserDefaults alloc] initWithSuiteName:AppGroup];
|
||||||
|
_defaults = ud ?: [NSUserDefaults standardUserDefaults];
|
||||||
|
|
||||||
|
// 监听 token 变化(例如别处调用了 signOut)
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
|
selector:@selector(_onAuthChanged:)
|
||||||
|
name:KBAuthChangedNotification
|
||||||
|
object:nil];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Public
|
||||||
|
|
||||||
|
- (void)bootstrapIfNeeded {
|
||||||
|
if (self.didBootstrap) return;
|
||||||
|
self.didBootstrap = YES;
|
||||||
|
|
||||||
|
BOOL hasInitializedThisInstall = [self.defaults boolForKey:kKBSessionInstallFlagKey];
|
||||||
|
|
||||||
|
KBAuthManager *auth = [KBAuthManager shared]; // 内部会 reloadFromKeychain
|
||||||
|
|
||||||
|
if (!hasInitializedThisInstall) {
|
||||||
|
// 说明是“卸载重装后的第一次运行”(或者真正第一次安装)
|
||||||
|
[self.defaults setBool:YES forKey:kKBSessionInstallFlagKey];
|
||||||
|
[self.defaults synchronize];
|
||||||
|
|
||||||
|
// 若此时 Keychain 里已有 token,多半是上一次安装遗留的;按你的需求清掉
|
||||||
|
if (auth.current.accessToken.length > 0) {
|
||||||
|
[auth signOut];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清除旧的用户缓存
|
||||||
|
[self.defaults removeObjectForKey:kKBSessionUserStoreKey];
|
||||||
|
[self.defaults synchronize];
|
||||||
|
self.currentUser = nil;
|
||||||
|
} else {
|
||||||
|
// 正常启动:从本地恢复用户信息
|
||||||
|
[self p_loadUserFromStore];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isLoggedIn {
|
||||||
|
return [[KBAuthManager shared] isLoggedIn];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)accessToken {
|
||||||
|
return [KBAuthManager shared].current.accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)handleLoginSuccessWithUser:(KBUser *)user {
|
||||||
|
if (!user) return;
|
||||||
|
|
||||||
|
// 先写 Keychain(统一走 KBAuthManager)
|
||||||
|
NSString *token = user.token;
|
||||||
|
if (token.length > 0) {
|
||||||
|
[[KBAuthManager shared] saveAccessToken:token
|
||||||
|
refreshToken:user.refreshToken
|
||||||
|
expiryDate:user.expiryDate
|
||||||
|
userIdentifier:user.appleUserId ?: user.userId];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 再缓存用户信息,供 App/键盘使用
|
||||||
|
self.currentUser = user;
|
||||||
|
[self p_saveUserToStore:user];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)logout {
|
||||||
|
// 清 Keychain
|
||||||
|
[[KBAuthManager shared] signOut];
|
||||||
|
|
||||||
|
// 清本地用户缓存
|
||||||
|
self.currentUser = nil;
|
||||||
|
[self.defaults removeObjectForKey:kKBSessionUserStoreKey];
|
||||||
|
[self.defaults synchronize];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Private
|
||||||
|
|
||||||
|
- (void)p_loadUserFromStore {
|
||||||
|
id obj = [self.defaults objectForKey:kKBSessionUserStoreKey];
|
||||||
|
if (![obj isKindOfClass:[NSDictionary class]]) {
|
||||||
|
self.currentUser = nil;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
KBUser *user = [KBUser mj_objectWithKeyValues:(NSDictionary *)obj];
|
||||||
|
self.currentUser = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)p_saveUserToStore:(KBUser *)user {
|
||||||
|
if (!user) {
|
||||||
|
[self.defaults removeObjectForKey:kKBSessionUserStoreKey];
|
||||||
|
[self.defaults synchronize];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSDictionary *dict = [user mj_keyValues];
|
||||||
|
if (dict) {
|
||||||
|
[self.defaults setObject:dict forKey:kKBSessionUserStoreKey];
|
||||||
|
[self.defaults synchronize];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_onAuthChanged:(NSNotification *)note {
|
||||||
|
// 如果 token 被别处清掉了,这里同步清一下 currentUser
|
||||||
|
if (![[KBAuthManager shared] isLoggedIn]) {
|
||||||
|
self.currentUser = nil;
|
||||||
|
[self.defaults removeObjectForKey:kKBSessionUserStoreKey];
|
||||||
|
[self.defaults synchronize];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@
|
|||||||
- (void)onTapAvatarEdit { [self presentImagePicker]; }
|
- (void)onTapAvatarEdit { [self presentImagePicker]; }
|
||||||
|
|
||||||
- (void)onTapLogout {
|
- (void)onTapLogout {
|
||||||
// 示例:退出登录
|
[[KBUserSessionManager shared] logout];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Lazy UI(懒加载)
|
#pragma mark - Lazy UI(懒加载)
|
||||||
|
|||||||
31
keyBoard/Class/Vender/CRBoxInputView/CRBoxFlowLayout.h
Normal file
31
keyBoard/Class/Vender/CRBoxInputView/CRBoxFlowLayout.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// CRBoxFlowLayout.h
|
||||||
|
// CaiShenYe
|
||||||
|
//
|
||||||
|
// Created by Chobits on 2019/1/3.
|
||||||
|
// Copyright © 2019 Chobits. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface CRBoxFlowLayout : UICollectionViewFlowLayout
|
||||||
|
|
||||||
|
/** ifNeedEqualGap
|
||||||
|
* default: YES
|
||||||
|
*/
|
||||||
|
@property (assign, nonatomic) BOOL ifNeedEqualGap;
|
||||||
|
|
||||||
|
@property (assign, nonatomic) NSInteger itemNum;
|
||||||
|
|
||||||
|
/** minLineSpacing
|
||||||
|
* default: 10
|
||||||
|
*/
|
||||||
|
@property (assign, nonatomic) NSInteger minLineSpacing;
|
||||||
|
|
||||||
|
- (void)autoCalucateLineSpacing;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
58
keyBoard/Class/Vender/CRBoxInputView/CRBoxFlowLayout.m
Normal file
58
keyBoard/Class/Vender/CRBoxInputView/CRBoxFlowLayout.m
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
//
|
||||||
|
// CRBoxFlowLayout.m
|
||||||
|
// CaiShenYe
|
||||||
|
//
|
||||||
|
// Created by Chobits on 2019/1/3.
|
||||||
|
// Copyright © 2019 Chobits. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "CRBoxFlowLayout.h"
|
||||||
|
|
||||||
|
@implementation CRBoxFlowLayout
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
|
||||||
|
if (self) {
|
||||||
|
[self initPara];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)initPara
|
||||||
|
{
|
||||||
|
self.ifNeedEqualGap = YES;
|
||||||
|
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
|
||||||
|
self.minLineSpacing = 10;
|
||||||
|
self.minimumLineSpacing = 0;
|
||||||
|
self.minimumInteritemSpacing = 0;
|
||||||
|
self.sectionInset = UIEdgeInsetsZero;
|
||||||
|
self.itemNum = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)prepareLayout
|
||||||
|
{
|
||||||
|
if (_ifNeedEqualGap) {
|
||||||
|
[self autoCalucateLineSpacing];
|
||||||
|
}
|
||||||
|
|
||||||
|
[super prepareLayout];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)autoCalucateLineSpacing
|
||||||
|
{
|
||||||
|
if (self.itemNum > 1) {
|
||||||
|
CGFloat width = CGRectGetWidth(self.collectionView.frame);
|
||||||
|
self.minimumLineSpacing = floor(1.0 * (width - self.itemNum * self.itemSize.width - self.collectionView.contentInset.left - self.collectionView.contentInset.right) / (self.itemNum - 1));
|
||||||
|
|
||||||
|
if (self.minimumLineSpacing < self.minLineSpacing) {
|
||||||
|
self.minimumLineSpacing = self.minLineSpacing;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
self.minimumLineSpacing = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
38
keyBoard/Class/Vender/CRBoxInputView/CRBoxInputCell.h
Normal file
38
keyBoard/Class/Vender/CRBoxInputView/CRBoxInputCell.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
//
|
||||||
|
// CRBoxInputCell.h
|
||||||
|
// CaiShenYe
|
||||||
|
//
|
||||||
|
// Created by Chobits on 2019/1/3.
|
||||||
|
// Copyright © 2019 Chobits. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
#import "CRBoxInputCellProperty.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
#define CRBoxCursoryAnimationKey @"CRBoxCursoryAnimationKey"
|
||||||
|
#define CRBoxInputCellID @"CRBoxInputCellID"
|
||||||
|
|
||||||
|
@interface CRBoxInputCell : UICollectionViewCell
|
||||||
|
|
||||||
|
/**
|
||||||
|
cursor
|
||||||
|
You should not use these properties, unless you know what you are doing.
|
||||||
|
*/
|
||||||
|
@property (strong, nonatomic) UIView *cursorView;
|
||||||
|
@property (assign, nonatomic) BOOL ifNeedCursor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
boxInputCellProperty
|
||||||
|
You should not use these properties, unless you know what you are doing.
|
||||||
|
*/
|
||||||
|
@property (strong, nonatomic) CRBoxInputCellProperty *boxInputCellProperty;
|
||||||
|
|
||||||
|
// 你可以在继承的子类中重写父类方法
|
||||||
|
// You can inherit and rewrite
|
||||||
|
- (UIView *)createCustomSecurityView __deprecated_msg("Please use `customSecurityViewBlock` in CRBoxInputCellProperty.");
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
281
keyBoard/Class/Vender/CRBoxInputView/CRBoxInputCell.m
Normal file
281
keyBoard/Class/Vender/CRBoxInputView/CRBoxInputCell.m
Normal file
@@ -0,0 +1,281 @@
|
|||||||
|
//
|
||||||
|
// CRBoxInputCell.m
|
||||||
|
// CaiShenYe
|
||||||
|
//
|
||||||
|
// Created by Chobits on 2019/1/3.
|
||||||
|
// Copyright © 2019 Chobits. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "CRBoxInputCell.h"
|
||||||
|
#import <Masonry/Masonry.h>
|
||||||
|
#import "CRLineView.h"
|
||||||
|
|
||||||
|
@interface CRBoxInputCell ()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@property (strong, nonatomic) UILabel *valueLabel;
|
||||||
|
@property (strong, nonatomic) CABasicAnimation *opacityAnimation;
|
||||||
|
@property (strong, nonatomic) UIView *customSecurityView;
|
||||||
|
|
||||||
|
@property (strong, nonatomic) CRLineView *lineView;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation CRBoxInputCell
|
||||||
|
|
||||||
|
- (instancetype)initWithFrame:(CGRect)frame
|
||||||
|
{
|
||||||
|
self = [super initWithFrame:frame];
|
||||||
|
|
||||||
|
if (self) {
|
||||||
|
[self createUIBase];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)initPara
|
||||||
|
{
|
||||||
|
self.ifNeedCursor = YES;
|
||||||
|
self.userInteractionEnabled = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)createUIBase
|
||||||
|
{
|
||||||
|
[self initPara];
|
||||||
|
|
||||||
|
_valueLabel = [UILabel new];
|
||||||
|
_valueLabel.font = [UIFont systemFontOfSize:38];
|
||||||
|
[self.contentView addSubview:_valueLabel];
|
||||||
|
[_valueLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.centerX.offset(0);
|
||||||
|
make.centerY.offset(0);
|
||||||
|
}];
|
||||||
|
|
||||||
|
_cursorView = [UIView new];
|
||||||
|
[self.contentView addSubview:_cursorView];
|
||||||
|
[_cursorView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.centerX.offset(0);
|
||||||
|
make.centerY.offset(0);
|
||||||
|
}];
|
||||||
|
|
||||||
|
[self initCellProperty];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)initCellProperty
|
||||||
|
{
|
||||||
|
CRBoxInputCellProperty *cellProperty = [CRBoxInputCellProperty new];
|
||||||
|
self.boxInputCellProperty = cellProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)valueLabelLoadData
|
||||||
|
{
|
||||||
|
_valueLabel.hidden = NO;
|
||||||
|
[self hideCustomSecurityView];
|
||||||
|
|
||||||
|
// 默认字体配置
|
||||||
|
__weak typeof(self) weakSelf = self;
|
||||||
|
void (^defaultTextConfig)(void) = ^{
|
||||||
|
if (weakSelf.boxInputCellProperty.cellFont) {
|
||||||
|
weakSelf.valueLabel.font = weakSelf.boxInputCellProperty.cellFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weakSelf.boxInputCellProperty.cellTextColor) {
|
||||||
|
weakSelf.valueLabel.textColor = weakSelf.boxInputCellProperty.cellTextColor;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 占位字符字体配置
|
||||||
|
void (^placeholderTextConfig)(void) = ^{
|
||||||
|
if (weakSelf.boxInputCellProperty.cellFont) {
|
||||||
|
weakSelf.valueLabel.font = weakSelf.boxInputCellProperty.cellPlaceholderFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weakSelf.boxInputCellProperty.cellTextColor) {
|
||||||
|
weakSelf.valueLabel.textColor = weakSelf.boxInputCellProperty.cellPlaceholderTextColor;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BOOL hasOriginValue = self.boxInputCellProperty.originValue && self.boxInputCellProperty.originValue.length > 0;
|
||||||
|
if (hasOriginValue) {
|
||||||
|
if (self.boxInputCellProperty.ifShowSecurity) {
|
||||||
|
if (self.boxInputCellProperty.securityType == CRBoxSecuritySymbolType) {
|
||||||
|
_valueLabel.text = self.boxInputCellProperty.securitySymbol;
|
||||||
|
}else if (self.boxInputCellProperty.securityType == CRBoxSecurityCustomViewType) {
|
||||||
|
_valueLabel.hidden = YES;
|
||||||
|
[self showCustomSecurityView];
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
_valueLabel.text = self.boxInputCellProperty.originValue;
|
||||||
|
}
|
||||||
|
defaultTextConfig();
|
||||||
|
}else{
|
||||||
|
BOOL hasPlaceholderText = self.boxInputCellProperty.cellPlaceholderText && self.boxInputCellProperty.cellPlaceholderText.length > 0;
|
||||||
|
// 有占位字符
|
||||||
|
if (hasPlaceholderText) {
|
||||||
|
_valueLabel.text = self.boxInputCellProperty.cellPlaceholderText;
|
||||||
|
placeholderTextConfig();
|
||||||
|
}
|
||||||
|
// 空
|
||||||
|
else{
|
||||||
|
_valueLabel.text = @"";
|
||||||
|
defaultTextConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Custom security view
|
||||||
|
- (void)showCustomSecurityView
|
||||||
|
{
|
||||||
|
if (!self.customSecurityView.superview) {
|
||||||
|
[self.contentView addSubview:self.customSecurityView];
|
||||||
|
[self.customSecurityView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.edges.mas_equalTo(UIEdgeInsetsZero);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
self.customSecurityView.alpha = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)hideCustomSecurityView
|
||||||
|
{
|
||||||
|
// Must add this judge. Otherwise _customSecurityView maybe null, and cause error.
|
||||||
|
if (_customSecurityView) {
|
||||||
|
self.customSecurityView.alpha = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Setter & Getter
|
||||||
|
- (CABasicAnimation *)opacityAnimation
|
||||||
|
{
|
||||||
|
if (!_opacityAnimation) {
|
||||||
|
_opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
|
||||||
|
_opacityAnimation.fromValue = @(1.0);
|
||||||
|
_opacityAnimation.toValue = @(0.0);
|
||||||
|
_opacityAnimation.duration = 0.9;
|
||||||
|
_opacityAnimation.repeatCount = HUGE_VALF;
|
||||||
|
_opacityAnimation.removedOnCompletion = YES;
|
||||||
|
_opacityAnimation.fillMode = kCAFillModeForwards;
|
||||||
|
_opacityAnimation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _opacityAnimation;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setSelected:(BOOL)selected
|
||||||
|
{
|
||||||
|
if (selected) {
|
||||||
|
self.layer.borderColor = self.boxInputCellProperty.cellBorderColorSelected.CGColor;
|
||||||
|
self.backgroundColor = self.boxInputCellProperty.cellBgColorSelected;
|
||||||
|
}else{
|
||||||
|
BOOL hasFill = _valueLabel.text.length > 0 ? YES : NO;
|
||||||
|
UIColor *cellBorderColor = self.boxInputCellProperty.cellBorderColorNormal;
|
||||||
|
UIColor *cellBackgroundColor = self.boxInputCellProperty.cellBgColorNormal;
|
||||||
|
if (hasFill) {
|
||||||
|
if (self.boxInputCellProperty.cellBorderColorFilled) {
|
||||||
|
cellBorderColor = self.boxInputCellProperty.cellBorderColorFilled;
|
||||||
|
}
|
||||||
|
if (self.boxInputCellProperty.cellBgColorFilled) {
|
||||||
|
cellBackgroundColor = self.boxInputCellProperty.cellBgColorFilled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.layer.borderColor = cellBorderColor.CGColor;
|
||||||
|
self.backgroundColor = cellBackgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_lineView) {
|
||||||
|
// 未选中
|
||||||
|
if (!selected) {
|
||||||
|
if (self.boxInputCellProperty.originValue.length > 0 && _lineView.underlineColorFilled) {
|
||||||
|
// 有内容
|
||||||
|
_lineView.lineView.backgroundColor = _lineView.underlineColorFilled;
|
||||||
|
}else if (_lineView.underlineColorNormal) {
|
||||||
|
// 无内容
|
||||||
|
_lineView.lineView.backgroundColor = _lineView.underlineColorNormal;
|
||||||
|
}else{
|
||||||
|
// 默认
|
||||||
|
_lineView.lineView.backgroundColor = CRColorMaster;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 已选中
|
||||||
|
else if (selected && _lineView.underlineColorSelected){
|
||||||
|
_lineView.lineView.backgroundColor = _lineView.underlineColorSelected;
|
||||||
|
}
|
||||||
|
// 默认
|
||||||
|
else{
|
||||||
|
_lineView.lineView.backgroundColor = CRColorMaster;
|
||||||
|
}
|
||||||
|
|
||||||
|
_lineView.selected = selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_ifNeedCursor) {
|
||||||
|
if (selected) {
|
||||||
|
_cursorView.hidden= NO;
|
||||||
|
[_cursorView.layer addAnimation:self.opacityAnimation forKey:CRBoxCursoryAnimationKey];
|
||||||
|
}else{
|
||||||
|
_cursorView.hidden= YES;
|
||||||
|
[_cursorView.layer removeAnimationForKey:CRBoxCursoryAnimationKey];
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
_cursorView.hidden= YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setBoxInputCellProperty:(CRBoxInputCellProperty *)boxInputCellProperty
|
||||||
|
{
|
||||||
|
_boxInputCellProperty = boxInputCellProperty;
|
||||||
|
|
||||||
|
_cursorView.backgroundColor = boxInputCellProperty.cellCursorColor;
|
||||||
|
[_cursorView mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.width.mas_equalTo(boxInputCellProperty.cellCursorWidth);
|
||||||
|
make.height.mas_equalTo(boxInputCellProperty.cellCursorHeight);
|
||||||
|
}];
|
||||||
|
self.layer.cornerRadius = boxInputCellProperty.cornerRadius;
|
||||||
|
self.layer.borderWidth = boxInputCellProperty.borderWidth;
|
||||||
|
|
||||||
|
[self valueLabelLoadData];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIView *)customSecurityView
|
||||||
|
{
|
||||||
|
if (!_customSecurityView) {
|
||||||
|
// Compatiable for 0.19 verion and earlier.
|
||||||
|
if ([self respondsToSelector:@selector(createCustomSecurityView)]) {
|
||||||
|
_customSecurityView = [self createCustomSecurityView];
|
||||||
|
}
|
||||||
|
else if(_boxInputCellProperty.customSecurityViewBlock){
|
||||||
|
NSAssert(_boxInputCellProperty.customSecurityViewBlock, @"customSecurityViewBlock can not be null!");
|
||||||
|
_customSecurityView = _boxInputCellProperty.customSecurityViewBlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _customSecurityView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)layoutSubviews
|
||||||
|
{
|
||||||
|
__weak typeof(self) weakSelf = self;
|
||||||
|
|
||||||
|
if (_boxInputCellProperty.showLine && !_lineView) {
|
||||||
|
NSAssert(_boxInputCellProperty.customLineViewBlock, @"customLineViewBlock can not be null!");
|
||||||
|
_lineView = _boxInputCellProperty.customLineViewBlock();
|
||||||
|
[self.contentView addSubview:_lineView];
|
||||||
|
[_lineView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.left.right.bottom.top.offset(0);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_boxInputCellProperty.configCellShadowBlock) {
|
||||||
|
_boxInputCellProperty.configCellShadowBlock(weakSelf.layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
[super layoutSubviews];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
200
keyBoard/Class/Vender/CRBoxInputView/CRBoxInputCellProperty.h
Normal file
200
keyBoard/Class/Vender/CRBoxInputView/CRBoxInputCellProperty.h
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
//
|
||||||
|
// CRBoxInputCellProperty.h
|
||||||
|
// CaiShenYe
|
||||||
|
//
|
||||||
|
// Created by Chobits on 2019/1/3.
|
||||||
|
// Copyright © 2019 Chobits. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "CRLineView.h"
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, CRBoxSecurityType) {
|
||||||
|
CRBoxSecuritySymbolType,
|
||||||
|
CRBoxSecurityCustomViewType,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef UIView *_Nonnull(^CustomSecurityViewBlock)(void);
|
||||||
|
typedef CRLineView *_Nonnull(^CustomLineViewBlock)(void);
|
||||||
|
typedef void(^ConfigCellShadowBlock)(CALayer *layer);
|
||||||
|
|
||||||
|
@interface CRBoxInputCellProperty : NSObject <NSCopying>
|
||||||
|
|
||||||
|
#pragma mark - UI
|
||||||
|
/**
|
||||||
|
cell边框宽度
|
||||||
|
默认:0.5
|
||||||
|
*/
|
||||||
|
@property (assign, nonatomic) CGFloat borderWidth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
cell边框颜色
|
||||||
|
状态:未选中状态时
|
||||||
|
默认:[UIColor colorWithRed:228/255.0 green:228/255.0 blue:228/255.0 alpha:1]
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) UIColor *cellBorderColorNormal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
cell边框颜色
|
||||||
|
状态:选中状态时
|
||||||
|
默认:[UIColor colorWithRed:255/255.0 green:70/255.0 blue:62/255.0 alpha:1]
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) UIColor *cellBorderColorSelected;
|
||||||
|
|
||||||
|
/**
|
||||||
|
cell边框颜色
|
||||||
|
状态:填充文字后,未选中状态时
|
||||||
|
默认:nil
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) UIColor *__nullable cellBorderColorFilled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
cell背景颜色
|
||||||
|
状态:无填充文字,未选中状态时
|
||||||
|
默认:[UIColor whiteColor]
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) UIColor *cellBgColorNormal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
cell背景颜色
|
||||||
|
状态:选中状态时
|
||||||
|
默认:[UIColor whiteColor]
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) UIColor *cellBgColorSelected;
|
||||||
|
|
||||||
|
/**
|
||||||
|
cell背景颜色
|
||||||
|
状态:填充文字后,未选中状态时
|
||||||
|
默认:与cellBgColorFilled相同
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) UIColor *__nullable cellBgColorFilled;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
光标颜色
|
||||||
|
默认: [UIColor colorWithRed:255/255.0 green:70/255.0 blue:62/255.0 alpha:1]
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) UIColor *cellCursorColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
光标宽度
|
||||||
|
默认: 2
|
||||||
|
*/
|
||||||
|
@property (assign, nonatomic) CGFloat cellCursorWidth;
|
||||||
|
|
||||||
|
/**
|
||||||
|
光标高度
|
||||||
|
默认: 32
|
||||||
|
*/
|
||||||
|
@property (assign, nonatomic) CGFloat cellCursorHeight;
|
||||||
|
|
||||||
|
/**
|
||||||
|
圆角
|
||||||
|
默认: 4
|
||||||
|
*/
|
||||||
|
@property (assign, nonatomic) CGFloat cornerRadius;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - line
|
||||||
|
/**
|
||||||
|
显示下划线
|
||||||
|
默认: NO
|
||||||
|
*/
|
||||||
|
@property (assign, nonatomic) BOOL showLine;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - label
|
||||||
|
/**
|
||||||
|
字体/字号
|
||||||
|
默认:[UIFont systemFontOfSize:20];
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) UIFont *cellFont;
|
||||||
|
|
||||||
|
/**
|
||||||
|
字体颜色
|
||||||
|
默认:[UIColor blackColor];
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) UIColor *cellTextColor;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - Security
|
||||||
|
/**
|
||||||
|
是否密文显示
|
||||||
|
默认:NO
|
||||||
|
*/
|
||||||
|
@property (assign, nonatomic) BOOL ifShowSecurity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
密文符号
|
||||||
|
默认:✱
|
||||||
|
说明:只有ifShowSecurity=YES时,有效
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) NSString *securitySymbol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
保存当前显示的字符
|
||||||
|
若想一次性修改所有输入值,请使用 CRBoxInputView中的'reloadInputString'方法
|
||||||
|
禁止修改该值!!!(除非你知道该怎么使用它。)
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic, readonly) NSString *originValue;
|
||||||
|
- (void)setMyOriginValue:(NSString *)originValue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
密文类型
|
||||||
|
默认:CRBoxSecuritySymbolType
|
||||||
|
类型说明:
|
||||||
|
CRBoxSecuritySymbolType 符号类型,根据securitySymbol,originValue的内容来显示
|
||||||
|
CRBoxSecurityCustomViewType 自定义View类型,可以自定义密文状态下的图片,View
|
||||||
|
*/
|
||||||
|
@property (assign, nonatomic) CRBoxSecurityType securityType;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - Placeholder
|
||||||
|
/**
|
||||||
|
占位符默认填充值
|
||||||
|
禁止修改该值!!!(除非你知道该怎么使用它。)
|
||||||
|
*/
|
||||||
|
@property (strong, nonatomic) NSString *__nullable cellPlaceholderText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
占位符字体颜色
|
||||||
|
默认:[UIColor colorWithRed:114/255.0 green:126/255.0 blue:124/255.0 alpha:0.3];
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) UIColor *cellPlaceholderTextColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
占位符字体/字号
|
||||||
|
默认:[UIFont systemFontOfSize:20];
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) UIFont *cellPlaceholderFont;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - Block
|
||||||
|
/**
|
||||||
|
自定义密文View回调
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) CustomSecurityViewBlock customSecurityViewBlock;
|
||||||
|
/**
|
||||||
|
自定义下划线回调
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) CustomLineViewBlock customLineViewBlock;
|
||||||
|
/**
|
||||||
|
自定义阴影回调
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) ConfigCellShadowBlock __nullable configCellShadowBlock;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - Test
|
||||||
|
@property (assign, nonatomic) NSInteger index;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
157
keyBoard/Class/Vender/CRBoxInputView/CRBoxInputCellProperty.m
Normal file
157
keyBoard/Class/Vender/CRBoxInputView/CRBoxInputCellProperty.m
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
//
|
||||||
|
// CRBoxInputself.m
|
||||||
|
// CaiShenYe
|
||||||
|
//
|
||||||
|
// Created by Chobits on 2019/1/3.
|
||||||
|
// Copyright © 2019 Chobits. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "CRBoxInputCellProperty.h"
|
||||||
|
#import <Masonry/Masonry.h>
|
||||||
|
|
||||||
|
@interface CRBoxInputCellProperty ()
|
||||||
|
|
||||||
|
@property (copy, nonatomic, readwrite) NSString *originValue;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@implementation CRBoxInputCellProperty
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
|
||||||
|
if (self) {
|
||||||
|
|
||||||
|
__weak typeof(self) weakSelf = self;
|
||||||
|
|
||||||
|
// UI
|
||||||
|
self.borderWidth = (0.5);
|
||||||
|
self.cellBorderColorNormal = [UIColor colorWithRed:228/255.0 green:228/255.0 blue:228/255.0 alpha:1];
|
||||||
|
self.cellBorderColorSelected = [UIColor colorWithRed:255/255.0 green:70/255.0 blue:62/255.0 alpha:1];
|
||||||
|
self.cellBorderColorFilled = nil;
|
||||||
|
self.cellBgColorNormal = [UIColor whiteColor];
|
||||||
|
self.cellBgColorSelected = [UIColor whiteColor];
|
||||||
|
self.cellBgColorFilled = nil;
|
||||||
|
self.cellCursorColor = [UIColor colorWithRed:255/255.0 green:70/255.0 blue:62/255.0 alpha:1];
|
||||||
|
self.cellCursorWidth = 2;
|
||||||
|
self.cellCursorHeight = 32;
|
||||||
|
self.cornerRadius = 4;
|
||||||
|
|
||||||
|
// line
|
||||||
|
self.showLine = NO;
|
||||||
|
|
||||||
|
// label
|
||||||
|
self.cellFont = [UIFont systemFontOfSize:20];
|
||||||
|
self.cellTextColor = [UIColor blackColor];
|
||||||
|
|
||||||
|
// Security
|
||||||
|
self.ifShowSecurity = NO;
|
||||||
|
self.securitySymbol = @"✱";
|
||||||
|
self.originValue = @"";
|
||||||
|
self.securityType = CRBoxSecuritySymbolType;
|
||||||
|
|
||||||
|
// Placeholder
|
||||||
|
self.cellPlaceholderText = nil;
|
||||||
|
self.cellPlaceholderTextColor = [UIColor colorWithRed:114/255.0 green:116/255.0 blue:124/255.0 alpha:0.3];
|
||||||
|
self.cellPlaceholderFont = [UIFont systemFontOfSize:20];
|
||||||
|
|
||||||
|
// Block
|
||||||
|
self.customSecurityViewBlock = ^UIView * _Nonnull{
|
||||||
|
return [weakSelf defaultCustomSecurityView];
|
||||||
|
};
|
||||||
|
self.customLineViewBlock = ^CRLineView * _Nonnull{
|
||||||
|
return [CRLineView new];
|
||||||
|
};
|
||||||
|
self.configCellShadowBlock = nil;
|
||||||
|
|
||||||
|
// Test
|
||||||
|
self.index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Copy
|
||||||
|
- (id)copyWithZone:(NSZone *)zone
|
||||||
|
{
|
||||||
|
CRBoxInputCellProperty *copy = [[self class] allocWithZone:zone];
|
||||||
|
|
||||||
|
// UI
|
||||||
|
copy.borderWidth = _borderWidth;
|
||||||
|
copy.cellBorderColorNormal = [_cellBorderColorNormal copy];
|
||||||
|
copy.cellBorderColorSelected = [_cellBorderColorSelected copy];
|
||||||
|
if (_cellBorderColorFilled) {
|
||||||
|
copy.cellBorderColorFilled = [_cellBorderColorFilled copy];
|
||||||
|
}
|
||||||
|
copy.cellBgColorNormal = [_cellBgColorNormal copy];
|
||||||
|
copy.cellBgColorSelected = [_cellBgColorSelected copy];
|
||||||
|
if (_cellBgColorFilled) {
|
||||||
|
copy.cellBgColorFilled = [_cellBgColorFilled copy];
|
||||||
|
}
|
||||||
|
copy.cellCursorColor = [_cellCursorColor copy];
|
||||||
|
copy.cellCursorWidth = _cellCursorWidth;
|
||||||
|
copy.cellCursorHeight = _cellCursorHeight;
|
||||||
|
copy.cornerRadius = _cornerRadius;
|
||||||
|
|
||||||
|
// line
|
||||||
|
copy.showLine = _showLine;
|
||||||
|
|
||||||
|
// label
|
||||||
|
copy.cellFont = [_cellFont copy];
|
||||||
|
copy.cellTextColor = [_cellTextColor copy];
|
||||||
|
|
||||||
|
// Security
|
||||||
|
copy.ifShowSecurity = _ifShowSecurity;
|
||||||
|
copy.securitySymbol = [_securitySymbol copy];
|
||||||
|
copy.originValue = [_originValue copy];
|
||||||
|
copy.securityType = _securityType;
|
||||||
|
|
||||||
|
// Placeholder
|
||||||
|
if (_cellPlaceholderText) {
|
||||||
|
copy.cellPlaceholderText = [_cellPlaceholderText copy];
|
||||||
|
}
|
||||||
|
copy.cellPlaceholderTextColor = [_cellPlaceholderTextColor copy];
|
||||||
|
copy.cellPlaceholderFont = [_cellPlaceholderFont copy];
|
||||||
|
|
||||||
|
// Block
|
||||||
|
copy.customSecurityViewBlock = [_customSecurityViewBlock copy];
|
||||||
|
copy.customLineViewBlock = [_customLineViewBlock copy];
|
||||||
|
if (_configCellShadowBlock) {
|
||||||
|
copy.configCellShadowBlock = [_configCellShadowBlock copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test
|
||||||
|
copy.index = _index;
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Getter
|
||||||
|
- (UIView *)defaultCustomSecurityView
|
||||||
|
{
|
||||||
|
UIView *customSecurityView = [UIView new];
|
||||||
|
customSecurityView.backgroundColor = [UIColor clearColor];
|
||||||
|
|
||||||
|
// circleView
|
||||||
|
static CGFloat circleViewWidth = 20;
|
||||||
|
UIView *circleView = [UIView new];
|
||||||
|
circleView.backgroundColor = [UIColor blackColor];
|
||||||
|
circleView.layer.cornerRadius = 4;
|
||||||
|
[customSecurityView addSubview:circleView];
|
||||||
|
[circleView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.width.height.mas_equalTo(circleViewWidth);
|
||||||
|
make.centerX.offset(0);
|
||||||
|
make.centerY.offset(0);
|
||||||
|
}];
|
||||||
|
|
||||||
|
return customSecurityView;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Setter
|
||||||
|
- (void)setMyOriginValue:(NSString *)originValue {
|
||||||
|
_originValue = originValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
165
keyBoard/Class/Vender/CRBoxInputView/CRBoxInputView.h
Executable file
165
keyBoard/Class/Vender/CRBoxInputView/CRBoxInputView.h
Executable file
@@ -0,0 +1,165 @@
|
|||||||
|
//
|
||||||
|
// CRBoxInputView.h
|
||||||
|
// CRBoxInputView
|
||||||
|
//
|
||||||
|
// Created by Chobits on 2019/1/3.
|
||||||
|
// Copyright © 2019 Chobits. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
#import "CRBoxFlowLayout.h"
|
||||||
|
#import "CRBoxInputCellProperty.h"
|
||||||
|
#import "CRBoxInputCell.h"
|
||||||
|
@class CRBoxInputView;
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, CRTextEditStatus) {
|
||||||
|
CRTextEditStatus_Idle,
|
||||||
|
CRTextEditStatus_BeginEdit,
|
||||||
|
CRTextEditStatus_EndEdit,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, CRInputType) {
|
||||||
|
/// 数字
|
||||||
|
CRInputType_Number,
|
||||||
|
/// 普通(不作任何处理)
|
||||||
|
CRInputType_Normal,
|
||||||
|
/// 自定义正则(此时需要设置customInputRegex)
|
||||||
|
CRInputType_Regex,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void(^TextDidChangeblock)(NSString * _Nullable text, BOOL isFinished);
|
||||||
|
typedef void(^TextEditStatusChangeblock)(CRTextEditStatus editStatus);
|
||||||
|
typedef NSString *(^TextCustomProcessblock)(NSString * _Nullable text);
|
||||||
|
|
||||||
|
@interface CRBoxInputView : UIView
|
||||||
|
|
||||||
|
/**
|
||||||
|
是否需要光标
|
||||||
|
ifNeedCursor
|
||||||
|
default: YES
|
||||||
|
*/
|
||||||
|
@property (assign, nonatomic) BOOL ifNeedCursor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
验证码长度
|
||||||
|
codeLength
|
||||||
|
default: 4
|
||||||
|
*/
|
||||||
|
@property (nonatomic, assign, readonly) NSInteger codeLength; //If you want to set codeLength, please use `- (instancetype)initWithCodeLength:(NSInteger)codeLength, or - (void)resetCodeLength:(NSInteger)codeLength beginEdit:(BOOL)beginEdit` in CRBoxInputView.
|
||||||
|
|
||||||
|
/**
|
||||||
|
是否开启密文模式
|
||||||
|
描述:你可以在任何时候修改该属性,并且已经存在的文字会自动刷新。
|
||||||
|
ifNeedSecurity
|
||||||
|
desc: You can change this property anytime. And the existing texts can be refreshed automatically.
|
||||||
|
default: NO
|
||||||
|
*/
|
||||||
|
@property (assign, nonatomic) BOOL ifNeedSecurity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
显示密文的延时时间
|
||||||
|
securityDelay
|
||||||
|
desc: show security delay time
|
||||||
|
default: 0.3
|
||||||
|
*/
|
||||||
|
@property (assign, nonatomic) CGFloat securityDelay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
键盘类型
|
||||||
|
keyBoardType
|
||||||
|
default: UIKeyboardTypeNumberPad
|
||||||
|
*/
|
||||||
|
@property (assign, nonatomic) UIKeyboardType keyBoardType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
输入样式
|
||||||
|
inputType
|
||||||
|
default: CRInputType_Number
|
||||||
|
*/
|
||||||
|
@property (assign, nonatomic) CRInputType inputType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
自定义正则匹配输入内容
|
||||||
|
customInputRegex
|
||||||
|
default: @""
|
||||||
|
当inputType == CRInputType_Regex时才会生效
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) NSString * _Nullable customInputRegex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
textContentType
|
||||||
|
描述: 你可以设置为 'nil' 或者 'UITextContentTypeOneTimeCode' 来自动获取短信验证码
|
||||||
|
desc: You set this 'nil' or 'UITextContentTypeOneTimeCode' to auto fill verify code.
|
||||||
|
default: nil
|
||||||
|
*/
|
||||||
|
@property (null_unspecified,nonatomic,copy) UITextContentType textContentType NS_AVAILABLE_IOS(10_0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
占位字符填充值
|
||||||
|
说明:在对应的输入框没有内容时,会显示该值。
|
||||||
|
默认:nil
|
||||||
|
*/
|
||||||
|
@property (strong, nonatomic) NSString * _Nullable placeholderText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
弹出键盘时,是否清空所有输入
|
||||||
|
只有在输入的字数等于codeLength时,生效
|
||||||
|
default: NO
|
||||||
|
*/
|
||||||
|
@property (assign, nonatomic) BOOL ifClearAllInBeginEditing;
|
||||||
|
|
||||||
|
|
||||||
|
@property (copy, nonatomic) TextDidChangeblock _Nullable textDidChangeblock;
|
||||||
|
@property (copy, nonatomic) TextEditStatusChangeblock _Nullable textEditStatusChangeblock;
|
||||||
|
/// 文本自定义处理
|
||||||
|
@property (copy, nonatomic) TextCustomProcessblock _Nullable textCustomProcessblock;
|
||||||
|
@property (strong, nonatomic) CRBoxFlowLayout * _Nullable boxFlowLayout;
|
||||||
|
@property (strong, nonatomic) CRBoxInputCellProperty * _Nullable customCellProperty;
|
||||||
|
@property (strong, nonatomic, readonly) NSString * _Nullable textValue;
|
||||||
|
@property (strong, nonatomic) UIView * _Nullable inputAccessoryView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
装载数据和准备界面
|
||||||
|
desc: Load and prepareView
|
||||||
|
beginEdit: 自动开启编辑模式
|
||||||
|
default: YES
|
||||||
|
*/
|
||||||
|
- (void)loadAndPrepareView;
|
||||||
|
- (void)loadAndPrepareViewWithBeginEdit:(BOOL)beginEdit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
重载输入的数据(用来设置预设数据)
|
||||||
|
desc:Reload string. (You can use this function to set deault value)
|
||||||
|
*/
|
||||||
|
- (void)reloadInputString:(NSString *_Nullable)value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
清空输入
|
||||||
|
desc: Clear all
|
||||||
|
beginEdit: 自动开启编辑模式
|
||||||
|
default: YES
|
||||||
|
*/
|
||||||
|
- (void)clearAll;
|
||||||
|
- (void)clearAllWithBeginEdit:(BOOL)beginEdit;
|
||||||
|
|
||||||
|
- (UICollectionView *_Nullable)mainCollectionView;
|
||||||
|
|
||||||
|
// 快速设置
|
||||||
|
// Qiuck set
|
||||||
|
- (void)quickSetSecuritySymbol:(NSString *_Nullable)securitySymbol;
|
||||||
|
|
||||||
|
// 你可以在继承的子类中调用父类方法
|
||||||
|
// You can inherit and call super
|
||||||
|
- (void)initDefaultValue;
|
||||||
|
|
||||||
|
// 你可以在继承的子类中重写父类方法
|
||||||
|
// You can inherit and rewrite
|
||||||
|
- (UICollectionViewCell *_Nullable)customCollectionView:(UICollectionView *_Nullable)collectionView cellForItemAtIndexPath:(NSIndexPath *_Nullable)indexPath;
|
||||||
|
|
||||||
|
// code Length 调整
|
||||||
|
- (void)resetCodeLength:(NSInteger)codeLength beginEdit:(BOOL)beginEdit;
|
||||||
|
|
||||||
|
// Init
|
||||||
|
- (instancetype _Nullable )initWithCodeLength:(NSInteger)codeLength;
|
||||||
|
|
||||||
|
@end
|
||||||
649
keyBoard/Class/Vender/CRBoxInputView/CRBoxInputView.m
Executable file
649
keyBoard/Class/Vender/CRBoxInputView/CRBoxInputView.m
Executable file
@@ -0,0 +1,649 @@
|
|||||||
|
//
|
||||||
|
// CRBoxInputView.m
|
||||||
|
// CRBoxInputView
|
||||||
|
//
|
||||||
|
// Created by Chobits on 2019/1/3.
|
||||||
|
// Copyright © 2019 Chobits. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "CRBoxInputView.h"
|
||||||
|
#import <Masonry/Masonry.h>
|
||||||
|
#import "CRBoxTextView.h"
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSInteger, CRBoxTextChangeType) {
|
||||||
|
CRBoxTextChangeType_NoChange,
|
||||||
|
CRBoxTextChangeType_Insert,
|
||||||
|
CRBoxTextChangeType_Delete,
|
||||||
|
};
|
||||||
|
|
||||||
|
@interface CRBoxInputView () <UICollectionViewDataSource, UICollectionViewDelegate, UITextFieldDelegate>
|
||||||
|
{
|
||||||
|
NSInteger _oldLength;
|
||||||
|
BOOL _ifNeedBeginEdit;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSInteger codeLength;
|
||||||
|
@property (nonatomic, strong) UITapGestureRecognizer *tapGR;
|
||||||
|
@property (nonatomic, strong) CRBoxTextView *textView;
|
||||||
|
@property (nonatomic, strong) UICollectionView *mainCollectionView;
|
||||||
|
@property (nonatomic, strong) NSMutableArray <NSString *> *valueArr;
|
||||||
|
@property (nonatomic, strong) NSMutableArray <CRBoxInputCellProperty *> *cellPropertyArr;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation CRBoxInputView
|
||||||
|
|
||||||
|
- (instancetype)initWithFrame:(CGRect)frame
|
||||||
|
{
|
||||||
|
self = [super initWithFrame:frame];
|
||||||
|
if (self) {
|
||||||
|
[self initDefaultValue];
|
||||||
|
[self addNotificationObserver];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithCoder:(NSCoder *)coder
|
||||||
|
{
|
||||||
|
self = [super initWithCoder:coder];
|
||||||
|
if (self) {
|
||||||
|
[self initDefaultValue];
|
||||||
|
[self addNotificationObserver];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
[self initDefaultValue];
|
||||||
|
[self addNotificationObserver];
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype _Nullable )initWithCodeLength:(NSInteger)codeLength
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
[self initDefaultValue];
|
||||||
|
[self addNotificationObserver];
|
||||||
|
self.codeLength = codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[self removeNotificationObserver];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Notification Observer
|
||||||
|
- (void)addNotificationObserver
|
||||||
|
{
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeNotificationObserver {
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationWillResignActive:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
// 触发home按下,光标动画移除
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationDidBecomeActive:(NSNotification *)notification
|
||||||
|
{
|
||||||
|
// 重新进来后响应,光标动画重新开始
|
||||||
|
[self reloadAllCell];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - You can inherit
|
||||||
|
- (void)initDefaultValue
|
||||||
|
{
|
||||||
|
_oldLength = 0;
|
||||||
|
self.ifNeedSecurity = NO;
|
||||||
|
self.securityDelay = 0.3;
|
||||||
|
self.codeLength = 4;
|
||||||
|
self.ifNeedCursor = YES;
|
||||||
|
self.keyBoardType = UIKeyboardTypeNumberPad;
|
||||||
|
self.inputType = CRInputType_Number;
|
||||||
|
self.customInputRegex = @"";
|
||||||
|
self.backgroundColor = [UIColor clearColor];
|
||||||
|
_valueArr = [NSMutableArray new];
|
||||||
|
_ifNeedBeginEdit = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - LoadAndPrepareView
|
||||||
|
- (void)loadAndPrepareView
|
||||||
|
{
|
||||||
|
[self loadAndPrepareViewWithBeginEdit:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)loadAndPrepareViewWithBeginEdit:(BOOL)beginEdit
|
||||||
|
{
|
||||||
|
if (_codeLength<=0) {
|
||||||
|
NSAssert(NO, @"请输入大于0的验证码位数");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[self generateCellPropertyArr];
|
||||||
|
|
||||||
|
// mainCollectionView
|
||||||
|
if (!self.mainCollectionView || ![self.subviews containsObject:self.mainCollectionView]) {
|
||||||
|
[self addSubview:self.mainCollectionView];
|
||||||
|
[self.mainCollectionView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.edges.mas_equalTo(UIEdgeInsetsZero);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
// textView
|
||||||
|
if (!self.textView || ![self.subviews containsObject:self.textView]) {
|
||||||
|
[self addSubview:self.textView];
|
||||||
|
[self.textView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.width.height.mas_equalTo(0);
|
||||||
|
make.left.top.mas_equalTo(0);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
// tap
|
||||||
|
if (self.tapGR.view != self) {
|
||||||
|
[self addGestureRecognizer:self.tapGR];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (![self.textView.text isEqualToString:self.customCellProperty.originValue]) {
|
||||||
|
self.textView.text = self.customCellProperty.originValue;
|
||||||
|
[self textDidChange:self.textView];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (beginEdit) {
|
||||||
|
[self beginEdit];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)generateCellPropertyArr
|
||||||
|
{
|
||||||
|
[self.cellPropertyArr removeAllObjects];
|
||||||
|
for (int i = 0; i < self.codeLength; i++) {
|
||||||
|
[self.cellPropertyArr addObject:[self.customCellProperty copy]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - code Length 调整
|
||||||
|
- (void)resetCodeLength:(NSInteger)codeLength beginEdit:(BOOL)beginEdit
|
||||||
|
{
|
||||||
|
if (codeLength<=0) {
|
||||||
|
NSAssert(NO, @"请输入大于0的验证码位数");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.codeLength = codeLength;
|
||||||
|
[self generateCellPropertyArr];
|
||||||
|
[self clearAllWithBeginEdit:beginEdit];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Reload Input View
|
||||||
|
- (void)reloadInputString:(NSString *_Nullable)value
|
||||||
|
{
|
||||||
|
if (![self.textView.text isEqualToString:value]) {
|
||||||
|
self.textView.text = value;
|
||||||
|
[self baseTextDidChange:self.textView manualInvoke:YES];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - UITextFieldDelegate
|
||||||
|
- (void)textFieldDidBeginEditing:(UITextField *)textField
|
||||||
|
{
|
||||||
|
_ifNeedBeginEdit = YES;
|
||||||
|
|
||||||
|
if (self.ifClearAllInBeginEditing && self.textValue.length == self.codeLength) {
|
||||||
|
[self clearAll];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.textEditStatusChangeblock) {
|
||||||
|
self.textEditStatusChangeblock(CRTextEditStatus_BeginEdit);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self reloadAllCell];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)textFieldDidEndEditing:(UITextField *)textField
|
||||||
|
{
|
||||||
|
_ifNeedBeginEdit = NO;
|
||||||
|
|
||||||
|
if (self.textEditStatusChangeblock) {
|
||||||
|
self.textEditStatusChangeblock(CRTextEditStatus_EndEdit);
|
||||||
|
}
|
||||||
|
|
||||||
|
[self reloadAllCell];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - TextViewEdit
|
||||||
|
- (void)beginEdit{
|
||||||
|
if (![self.textView isFirstResponder]) {
|
||||||
|
[self.textView becomeFirstResponder];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)endEdit{
|
||||||
|
if ([self.textView isFirstResponder]) {
|
||||||
|
[self.textView resignFirstResponder];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)clearAll
|
||||||
|
{
|
||||||
|
[self clearAllWithBeginEdit:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)clearAllWithBeginEdit:(BOOL)beginEdit
|
||||||
|
{
|
||||||
|
_oldLength = 0;
|
||||||
|
[_valueArr removeAllObjects];
|
||||||
|
self.textView.text = @"";
|
||||||
|
[self allSecurityClose];
|
||||||
|
[self reloadAllCell];
|
||||||
|
[self triggerBlock];
|
||||||
|
|
||||||
|
if (beginEdit) {
|
||||||
|
[self beginEdit];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - UITextFieldDidChange
|
||||||
|
- (void)textDidChange:(UITextField *)textField {
|
||||||
|
[self baseTextDidChange:textField manualInvoke:NO];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤输入内容
|
||||||
|
*/
|
||||||
|
- (NSString *)filterInputContent:(NSString *)inputStr {
|
||||||
|
|
||||||
|
NSMutableString *mutableStr = [[NSMutableString alloc] initWithString:inputStr];
|
||||||
|
if (self.inputType == CRInputType_Number) {
|
||||||
|
|
||||||
|
/// 纯数字
|
||||||
|
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[^0-9]" options:0 error:nil];
|
||||||
|
[regex replaceMatchesInString:mutableStr options:0 range:NSMakeRange(0, [mutableStr length]) withTemplate:@""];
|
||||||
|
} else if (self.inputType == CRInputType_Normal) {
|
||||||
|
|
||||||
|
/// 不处理
|
||||||
|
nil;
|
||||||
|
} else if (self.inputType == CRInputType_Regex) {
|
||||||
|
|
||||||
|
/// 自定义正则
|
||||||
|
if (self.customInputRegex.length > 0) {
|
||||||
|
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:self.customInputRegex options:0 error:nil];
|
||||||
|
[regex replaceMatchesInString:mutableStr options:0 range:NSMakeRange(0, [mutableStr length]) withTemplate:@""];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [mutableStr copy];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* textDidChange基操作
|
||||||
|
* manualInvoke:是否为手动调用
|
||||||
|
*/
|
||||||
|
- (void)baseTextDidChange:(UITextField *)textField manualInvoke:(BOOL)manualInvoke {
|
||||||
|
|
||||||
|
__weak typeof(self) weakSelf = self;
|
||||||
|
NSString *verStr = textField.text;
|
||||||
|
|
||||||
|
//有空格去掉空格
|
||||||
|
verStr = [verStr stringByReplacingOccurrencesOfString:@" " withString:@""];
|
||||||
|
verStr = [self filterInputContent:verStr];
|
||||||
|
|
||||||
|
//自定义处理
|
||||||
|
if (self.textCustomProcessblock) {
|
||||||
|
verStr = self.textCustomProcessblock(verStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verStr.length >= _codeLength) {
|
||||||
|
verStr = [verStr substringToIndex:_codeLength];
|
||||||
|
[self endEdit];
|
||||||
|
}
|
||||||
|
textField.text = verStr;
|
||||||
|
|
||||||
|
// 判断删除/增加
|
||||||
|
CRBoxTextChangeType boxTextChangeType = CRBoxTextChangeType_NoChange;
|
||||||
|
if (verStr.length > _oldLength) {
|
||||||
|
boxTextChangeType = CRBoxTextChangeType_Insert;
|
||||||
|
}else if (verStr.length < _oldLength){
|
||||||
|
boxTextChangeType = CRBoxTextChangeType_Delete;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _valueArr
|
||||||
|
if (boxTextChangeType == CRBoxTextChangeType_Delete) {
|
||||||
|
[self setSecurityShow:NO index:_valueArr.count-1];
|
||||||
|
[_valueArr removeLastObject];
|
||||||
|
|
||||||
|
}else if (boxTextChangeType == CRBoxTextChangeType_Insert){
|
||||||
|
if (verStr.length > 0) {
|
||||||
|
if (_valueArr.count > 0) {
|
||||||
|
[self replaceValueArrToAsteriskWithIndex:_valueArr.count - 1 needEqualToCount:NO];
|
||||||
|
}
|
||||||
|
// NSString *subStr = [verStr substringWithRange:NSMakeRange(verStr.length - 1, 1)];
|
||||||
|
// [strongSelf.valueArr addObject:subStr];
|
||||||
|
[_valueArr removeAllObjects];
|
||||||
|
|
||||||
|
[verStr enumerateSubstringsInRange:NSMakeRange(0, verStr.length) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
|
||||||
|
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||||
|
[strongSelf.valueArr addObject:substring];
|
||||||
|
}];
|
||||||
|
|
||||||
|
if (self.ifNeedSecurity) {
|
||||||
|
if (manualInvoke) {
|
||||||
|
// 处理所有秘文
|
||||||
|
[self delaySecurityProcessAll];
|
||||||
|
}else {
|
||||||
|
// 只处理最后一个秘文
|
||||||
|
[self delaySecurityProcessLastOne];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[self reloadAllCell];
|
||||||
|
|
||||||
|
_oldLength = verStr.length;
|
||||||
|
|
||||||
|
if (boxTextChangeType != CRBoxTextChangeType_NoChange) {
|
||||||
|
[self triggerBlock];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Control security show
|
||||||
|
- (void)setSecurityShow:(BOOL)isShow index:(NSInteger)index
|
||||||
|
{
|
||||||
|
if (index < 0) {
|
||||||
|
NSAssert(NO, @"index必须大于等于0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CRBoxInputCellProperty *cellProperty = self.cellPropertyArr[index];
|
||||||
|
cellProperty.ifShowSecurity = isShow;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)allSecurityClose
|
||||||
|
{
|
||||||
|
[self.cellPropertyArr enumerateObjectsUsingBlock:^(CRBoxInputCellProperty * _Nonnull cellProperty, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||||
|
if (cellProperty.ifShowSecurity == YES) {
|
||||||
|
cellProperty.ifShowSecurity = NO;
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)allSecurityOpen
|
||||||
|
{
|
||||||
|
[self.cellPropertyArr enumerateObjectsUsingBlock:^(CRBoxInputCellProperty * _Nonnull cellProperty, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||||
|
if (cellProperty.ifShowSecurity == NO) {
|
||||||
|
cellProperty.ifShowSecurity = YES;
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark - Trigger block
|
||||||
|
- (void)triggerBlock
|
||||||
|
{
|
||||||
|
if (self.textDidChangeblock) {
|
||||||
|
BOOL isFinished = _valueArr.count == _codeLength ? YES : NO;
|
||||||
|
self.textDidChangeblock(_textView.text, isFinished);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Asterisk 替换密文
|
||||||
|
/**
|
||||||
|
* 替换密文
|
||||||
|
* needEqualToCount:是否只替换最后一个
|
||||||
|
*/
|
||||||
|
- (void)replaceValueArrToAsteriskWithIndex:(NSInteger)index needEqualToCount:(BOOL)needEqualToCount
|
||||||
|
{
|
||||||
|
if (!self.ifNeedSecurity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needEqualToCount && index != _valueArr.count - 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
[self setSecurityShow:YES index:index];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark 延时替换最后一个密文
|
||||||
|
- (void)delaySecurityProcessLastOne
|
||||||
|
{
|
||||||
|
__weak __typeof(self)weakSelf = self;
|
||||||
|
[self delayAfter:self.securityDelay dealBlock:^{
|
||||||
|
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||||
|
if (strongSelf.valueArr.count > 0) {
|
||||||
|
[strongSelf replaceValueArrToAsteriskWithIndex:strongSelf.valueArr.count-1 needEqualToCount:YES];
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[strongSelf reloadAllCell];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark 延时替换所有一个密文
|
||||||
|
- (void)delaySecurityProcessAll
|
||||||
|
{
|
||||||
|
__weak __typeof(self)weakSelf = self;
|
||||||
|
[self.valueArr enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||||
|
__strong __typeof(weakSelf)strongSelf = weakSelf;
|
||||||
|
[strongSelf replaceValueArrToAsteriskWithIndex:idx needEqualToCount:NO];
|
||||||
|
}];
|
||||||
|
|
||||||
|
[self reloadAllCell];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - DelayBlock
|
||||||
|
- (void)delayAfter:(CGFloat)delayTime dealBlock:(void (^)(void))dealBlock
|
||||||
|
{
|
||||||
|
dispatch_time_t timer = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayTime *NSEC_PER_SEC));
|
||||||
|
dispatch_after(timer, dispatch_get_main_queue(), ^{
|
||||||
|
if (dealBlock) {
|
||||||
|
dealBlock();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - UICollectionViewDataSource
|
||||||
|
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
|
||||||
|
{
|
||||||
|
return _codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
|
||||||
|
{
|
||||||
|
id tempCell = [self customCollectionView:collectionView cellForItemAtIndexPath:indexPath];
|
||||||
|
|
||||||
|
if ([tempCell isKindOfClass:[CRBoxInputCell class]]) {
|
||||||
|
|
||||||
|
CRBoxInputCell *cell = (CRBoxInputCell *)tempCell;
|
||||||
|
cell.ifNeedCursor = self.ifNeedCursor;
|
||||||
|
|
||||||
|
// CellProperty
|
||||||
|
CRBoxInputCellProperty *cellProperty = self.cellPropertyArr[indexPath.row];
|
||||||
|
cellProperty.index = indexPath.row;
|
||||||
|
|
||||||
|
NSString *currentPlaceholderStr = nil;
|
||||||
|
if (_placeholderText.length > indexPath.row) {
|
||||||
|
currentPlaceholderStr = [_placeholderText substringWithRange:NSMakeRange(indexPath.row, 1)];
|
||||||
|
cellProperty.cellPlaceholderText = currentPlaceholderStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// setOriginValue
|
||||||
|
NSUInteger focusIndex = _valueArr.count;
|
||||||
|
if (_valueArr.count > 0 && indexPath.row <= focusIndex - 1) {
|
||||||
|
[cellProperty setMyOriginValue:_valueArr[indexPath.row]];
|
||||||
|
}else{
|
||||||
|
[cellProperty setMyOriginValue:@""];
|
||||||
|
}
|
||||||
|
|
||||||
|
cell.boxInputCellProperty = cellProperty;
|
||||||
|
|
||||||
|
if (_ifNeedBeginEdit) {
|
||||||
|
cell.selected = indexPath.row == focusIndex ? YES : NO;
|
||||||
|
}else{
|
||||||
|
cell.selected = NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tempCell;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)reloadAllCell
|
||||||
|
{
|
||||||
|
[self.mainCollectionView reloadData];
|
||||||
|
|
||||||
|
NSUInteger focusIndex = _valueArr.count;
|
||||||
|
/// 最后一个
|
||||||
|
if (focusIndex == self.codeLength) {
|
||||||
|
[self.mainCollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:focusIndex - 1 inSection:0] atScrollPosition:UICollectionViewScrollPositionRight animated:YES];
|
||||||
|
} else {
|
||||||
|
[self.mainCollectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:focusIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Qiuck set
|
||||||
|
- (void)quickSetSecuritySymbol:(NSString *)securitySymbol
|
||||||
|
{
|
||||||
|
if (securitySymbol.length != 1) {
|
||||||
|
securitySymbol = @"✱";
|
||||||
|
}
|
||||||
|
|
||||||
|
self.customCellProperty.securitySymbol = securitySymbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - You can rewrite
|
||||||
|
- (UICollectionViewCell *)customCollectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
|
||||||
|
{
|
||||||
|
CRBoxInputCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CRBoxInputCellID forIndexPath:indexPath];
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Setter & Getter
|
||||||
|
- (UITapGestureRecognizer *)tapGR
|
||||||
|
{
|
||||||
|
if (!_tapGR) {
|
||||||
|
_tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(beginEdit)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _tapGR;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UICollectionView *)mainCollectionView
|
||||||
|
{
|
||||||
|
if (!_mainCollectionView) {
|
||||||
|
_mainCollectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:self.boxFlowLayout];
|
||||||
|
_mainCollectionView.showsHorizontalScrollIndicator = NO;
|
||||||
|
_mainCollectionView.backgroundColor = [UIColor clearColor];
|
||||||
|
_mainCollectionView.delegate = self;
|
||||||
|
_mainCollectionView.dataSource = self;
|
||||||
|
_mainCollectionView.layer.masksToBounds = YES;
|
||||||
|
_mainCollectionView.clipsToBounds = YES;
|
||||||
|
[_mainCollectionView registerClass:[CRBoxInputCell class] forCellWithReuseIdentifier:CRBoxInputCellID];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _mainCollectionView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CRBoxFlowLayout *)boxFlowLayout
|
||||||
|
{
|
||||||
|
if (!_boxFlowLayout) {
|
||||||
|
_boxFlowLayout = [CRBoxFlowLayout new];
|
||||||
|
_boxFlowLayout.itemSize = CGSizeMake(42, 47);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _boxFlowLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setCodeLength:(NSInteger)codeLength
|
||||||
|
{
|
||||||
|
_codeLength = codeLength;
|
||||||
|
self.boxFlowLayout.itemNum = codeLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setKeyBoardType:(UIKeyboardType)keyBoardType{
|
||||||
|
_keyBoardType = keyBoardType;
|
||||||
|
self.textView.keyboardType = keyBoardType;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CRBoxTextView *)textView{
|
||||||
|
if (!_textView) {
|
||||||
|
_textView = [CRBoxTextView new];
|
||||||
|
// _textView.alpha = 0.1;
|
||||||
|
// _textView.tintColor = [UIColor clearColor];
|
||||||
|
// _textView.backgroundColor = [UIColor clearColor];
|
||||||
|
// _textView.textColor = [UIColor clearColor];
|
||||||
|
_textView.delegate = self;
|
||||||
|
[_textView addTarget:self action:@selector(textDidChange:) forControlEvents:UIControlEventEditingChanged];
|
||||||
|
}
|
||||||
|
return _textView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setTextContentType:(UITextContentType)textContentType
|
||||||
|
{
|
||||||
|
_textContentType = textContentType;
|
||||||
|
|
||||||
|
_textView.textContentType = textContentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CRBoxInputCellProperty *)customCellProperty
|
||||||
|
{
|
||||||
|
if (!_customCellProperty) {
|
||||||
|
_customCellProperty = [CRBoxInputCellProperty new];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _customCellProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSMutableArray <CRBoxInputCellProperty *> *)cellPropertyArr
|
||||||
|
{
|
||||||
|
if (!_cellPropertyArr) {
|
||||||
|
_cellPropertyArr = [NSMutableArray new];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _cellPropertyArr;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)textValue
|
||||||
|
{
|
||||||
|
return _textView.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@synthesize inputAccessoryView = _inputAccessoryView;
|
||||||
|
- (void)setInputAccessoryView:(UIView *)inputAccessoryView
|
||||||
|
{
|
||||||
|
_inputAccessoryView = inputAccessoryView;
|
||||||
|
self.textView.inputAccessoryView = _inputAccessoryView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIView *)inputAccessoryView
|
||||||
|
{
|
||||||
|
return _inputAccessoryView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setIfNeedSecurity:(BOOL)ifNeedSecurity
|
||||||
|
{
|
||||||
|
_ifNeedSecurity = ifNeedSecurity;
|
||||||
|
|
||||||
|
if (ifNeedSecurity == YES) {
|
||||||
|
[self allSecurityOpen];
|
||||||
|
}else{
|
||||||
|
[self allSecurityClose];
|
||||||
|
}
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[self reloadAllCell];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
16
keyBoard/Class/Vender/CRBoxInputView/CRBoxTextView.h
Normal file
16
keyBoard/Class/Vender/CRBoxInputView/CRBoxTextView.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// CRBoxTextView.h
|
||||||
|
// CRBoxInputView
|
||||||
|
//
|
||||||
|
// Created by Chobits on 2019/1/3.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface CRBoxTextView : UITextField
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
20
keyBoard/Class/Vender/CRBoxInputView/CRBoxTextView.m
Normal file
20
keyBoard/Class/Vender/CRBoxInputView/CRBoxTextView.m
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// CRBoxTextView.m
|
||||||
|
// CRBoxInputView
|
||||||
|
//
|
||||||
|
// Created by Chobits on 2019/1/3.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "CRBoxTextView.h"
|
||||||
|
|
||||||
|
@implementation CRBoxTextView
|
||||||
|
|
||||||
|
/**
|
||||||
|
* /禁止可被粘贴复制
|
||||||
|
*/
|
||||||
|
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
52
keyBoard/Class/Vender/CRBoxInputView/CRLineView.h
Normal file
52
keyBoard/Class/Vender/CRBoxInputView/CRLineView.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// CRLineView.h
|
||||||
|
// CRBoxInputView_Example
|
||||||
|
//
|
||||||
|
// Created by Chobits on 2019/6/10.
|
||||||
|
// Copyright © 2019 BearRan. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
#define CRColorMaster [UIColor colorWithRed:49/255.0 green:51/255.0 blue:64/255.0 alpha:1]
|
||||||
|
|
||||||
|
@interface CRLineView : UIView
|
||||||
|
|
||||||
|
typedef void(^CRLineViewSelectChangeBlock)(CRLineView *lineView, BOOL selected);
|
||||||
|
|
||||||
|
@property (strong, nonatomic) UIView *lineView;
|
||||||
|
@property (assign, nonatomic) BOOL selected;
|
||||||
|
|
||||||
|
/**
|
||||||
|
下划线颜色
|
||||||
|
状态:未选中状态,且没有填充文字时
|
||||||
|
默认:[UIColor colorWithRed:49/255.0 green:51/255.0 blue:64/255.0 alpha:1]
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) UIColor *underlineColorNormal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
下划线颜色
|
||||||
|
状态:选中状态时
|
||||||
|
默认:[UIColor colorWithRed:49/255.0 green:51/255.0 blue:64/255.0 alpha:1]
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) UIColor *underlineColorSelected;
|
||||||
|
|
||||||
|
/**
|
||||||
|
下划线颜色
|
||||||
|
状态:未选中状态,且有填充文字时
|
||||||
|
默认:[UIColor colorWithRed:49/255.0 green:51/255.0 blue:64/255.0 alpha:1]
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) UIColor *underlineColorFilled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
选择状态改变时回调
|
||||||
|
*/
|
||||||
|
@property (copy, nonatomic) CRLineViewSelectChangeBlock __nullable selectChangeBlock;
|
||||||
|
|
||||||
|
- (instancetype)initWithFrame:(CGRect)frame UNAVAILABLE_ATTRIBUTE;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
60
keyBoard/Class/Vender/CRBoxInputView/CRLineView.m
Normal file
60
keyBoard/Class/Vender/CRBoxInputView/CRLineView.m
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// CRLineView.m
|
||||||
|
// CRBoxInputView_Example
|
||||||
|
//
|
||||||
|
// Created by Chobits on 2019/6/10.
|
||||||
|
// Copyright © 2019 BearRan. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "CRLineView.h"
|
||||||
|
#import <Masonry/Masonry.h>
|
||||||
|
|
||||||
|
@interface CRLineView()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation CRLineView
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
_underlineColorNormal = CRColorMaster;
|
||||||
|
_underlineColorSelected = CRColorMaster;
|
||||||
|
_underlineColorFilled = CRColorMaster;
|
||||||
|
[self createUI];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)createUI
|
||||||
|
{
|
||||||
|
static CGFloat sepLineViewHeight = 4;
|
||||||
|
|
||||||
|
_lineView = [UIView new];
|
||||||
|
[self addSubview:_lineView];
|
||||||
|
_lineView.backgroundColor = _underlineColorNormal;
|
||||||
|
_lineView.layer.cornerRadius = sepLineViewHeight / 2.0;
|
||||||
|
[_lineView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.height.mas_equalTo(sepLineViewHeight);
|
||||||
|
make.left.right.bottom.offset(0);
|
||||||
|
}];
|
||||||
|
|
||||||
|
_lineView.layer.shadowColor = [[UIColor blackColor] colorWithAlphaComponent:0.2].CGColor;
|
||||||
|
_lineView.layer.shadowOpacity = 1;
|
||||||
|
_lineView.layer.shadowOffset = CGSizeMake(0, 2);
|
||||||
|
_lineView.layer.shadowRadius = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setSelected:(BOOL)selected {
|
||||||
|
_selected = selected;
|
||||||
|
|
||||||
|
if (self.selectChangeBlock) {
|
||||||
|
__weak __typeof(self)weakSelf = self;
|
||||||
|
self.selectChangeBlock(weakSelf, selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
21
keyBoard/Class/Vender/CRBoxInputView/CRSecrectImageView.h
Normal file
21
keyBoard/Class/Vender/CRBoxInputView/CRSecrectImageView.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// CRSecrectImageView.h
|
||||||
|
// CRBoxInputView_Example
|
||||||
|
//
|
||||||
|
// Created by Chobits on 2019/6/10.
|
||||||
|
// Copyright © 2019 BearRan. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface CRSecrectImageView : UIView
|
||||||
|
|
||||||
|
@property (strong, nonatomic) UIImage *image;
|
||||||
|
@property (assign, nonatomic) CGFloat imageWidth;
|
||||||
|
@property (assign, nonatomic) CGFloat imageHeight;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
65
keyBoard/Class/Vender/CRBoxInputView/CRSecrectImageView.m
Normal file
65
keyBoard/Class/Vender/CRBoxInputView/CRSecrectImageView.m
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
//
|
||||||
|
// CRSecrectImageView.m
|
||||||
|
// CRBoxInputView_Example
|
||||||
|
//
|
||||||
|
// Created by Chobits on 2019/6/10.
|
||||||
|
// Copyright © 2019 BearRan. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "CRSecrectImageView.h"
|
||||||
|
#import <Masonry/Masonry.h>
|
||||||
|
|
||||||
|
@interface CRSecrectImageView()
|
||||||
|
{
|
||||||
|
UIImageView *_lockImgView;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation CRSecrectImageView
|
||||||
|
|
||||||
|
- (instancetype)init
|
||||||
|
{
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
[self createUI];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)createUI
|
||||||
|
{
|
||||||
|
_lockImgView = [UIImageView new];
|
||||||
|
_lockImgView.image = [UIImage imageNamed:@"smallLock"];
|
||||||
|
[self addSubview:_lockImgView];
|
||||||
|
[_lockImgView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.centerX.offset(0);
|
||||||
|
make.centerY.offset(0);
|
||||||
|
make.width.mas_equalTo(23);
|
||||||
|
make.height.mas_equalTo(27);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Setter & Getter
|
||||||
|
- (void)setImage:(UIImage *)image
|
||||||
|
{
|
||||||
|
_image = image;
|
||||||
|
_lockImgView.image = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setImageWidth:(CGFloat)imageWidth
|
||||||
|
{
|
||||||
|
_imageWidth = imageWidth;
|
||||||
|
[_lockImgView mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.width.mas_equalTo(imageWidth);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setImageHeight:(CGFloat)imageHeight
|
||||||
|
{
|
||||||
|
_imageHeight = imageHeight;
|
||||||
|
[_lockImgView mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.height.mas_equalTo(imageHeight);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -25,6 +25,8 @@
|
|||||||
#import "KBHUD.h"
|
#import "KBHUD.h"
|
||||||
#import "KBAlert.h"
|
#import "KBAlert.h"
|
||||||
#import "KBNetworkManager.h"
|
#import "KBNetworkManager.h"
|
||||||
|
#import "KBUserSessionManager.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// 项目
|
/// 项目
|
||||||
|
|||||||
Reference in New Issue
Block a user