├── GIF └── 1.gif ├── README.md └── XLGesturePasswordDemo ├── XLGesturePassword ├── XLGestureInfoView.h ├── XLGestureInfoView.m ├── XLGestureInfoViewCell.h ├── XLGestureInfoViewCell.m ├── XLGesturePassword.h ├── XLGesturePassword.m ├── XLGesturePasswordCell.h └── XLGesturePasswordCell.m ├── XLGesturePasswordDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── MengXianLiang.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── MengXianLiang.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist └── XLGesturePasswordDemo ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets ├── AppIcon.appiconset │ └── Contents.json └── Contents.json ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── Info.plist ├── ViewController.h ├── ViewController.m └── main.m /GIF/1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengxianliang/XLGesturePassword/64fe12b176d62a9369f08e3962a8fde6b99731ff/GIF/1.gif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XLGesturePassword 2 | 3 | ### 显示效果 4 | 5 | 6 | 7 | ### 使用方法 8 | 9 | * 手势密码创建方法 10 | ```objc 11 | _passWord = [[XLGesturePassword alloc] init]; 12 | _passWord.bounds = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.width); 13 | _passWord.center = self.view.center; 14 | _passWord.itemBackGoundColor = ligntBlueColor; 15 | _passWord.itemCenterBallColor = blueColor; 16 | _passWord.lineNormalColor = blueColor; 17 | _passWord.lineErrorColor = redColor; 18 | [self.view addSubview:_passWord]; 19 | __weak typeof (self)weekSelf = self; 20 | [_passWord addPasswordBlock:^(NSString *password) { 21 | [weekSelf showPassword:password]; 22 | }]; 23 | ``` 24 | 25 | * 手势提示创建方法 26 | ```objc 27 | _infoView = [[XLGestureInfoView alloc] init]; 28 | _infoView.bounds = CGRectMake(0, 0, 80, 80); 29 | _infoView.center = CGPointMake(_passWord.center.x, CGRectGetMinY(_passWord.frame) - 50); 30 | _infoView.itemBackGoundColor = blueColor; 31 | [self.view addSubview:_infoView]; 32 | ``` 33 | 34 | 35 | ### 个人开发过的UI工具集合 [XLUIKit](https://github.com/mengxianliang/XLUIKit) 36 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePassword/XLGestureInfoView.h: -------------------------------------------------------------------------------- 1 | // 2 | // XLGestureInfoView.h 3 | // 手势密码Demo 4 | // 5 | // Created by MengXianLiang on 2018/5/23. 6 | // Copyright © 2018年 jwzt. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface XLGestureInfoView : UIView 12 | //选中颜色 13 | @property (nonatomic, strong) UIColor *itemBackGoundColor; 14 | //要显示的密码 15 | @property (nonatomic, copy) NSString *passWord; 16 | //重新输入 17 | - (void)refresh; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePassword/XLGestureInfoView.m: -------------------------------------------------------------------------------- 1 | // 2 | // XLGestureInfoView.m 3 | // 手势密码Demo 4 | // 5 | // Created by MengXianLiang on 2018/5/23. 6 | // Copyright © 2018年 jwzt. All rights reserved. 7 | // 8 | 9 | #import "XLGestureInfoView.h" 10 | #import "XLGestureInfoViewCell.h" 11 | 12 | @interface XLGestureInfoView () { 13 | UICollectionView *_collectionView; 14 | } 15 | @end 16 | 17 | @implementation XLGestureInfoView 18 | 19 | - (instancetype)init { 20 | if (self = [super init]) { 21 | [self buildUI]; 22 | [self setDefaultColor]; 23 | } 24 | return self; 25 | } 26 | 27 | - (void)buildUI { 28 | self.layer.masksToBounds = true; 29 | //初始化collectionView 30 | UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; 31 | _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; 32 | _collectionView.backgroundColor = [UIColor clearColor]; 33 | [_collectionView registerClass:[XLGestureInfoViewCell class] forCellWithReuseIdentifier:@"XLGestureInfoViewCell"]; 34 | _collectionView.dataSource = self; 35 | _collectionView.delegate = self; 36 | [self addSubview:_collectionView]; 37 | } 38 | 39 | //自动布局 40 | - (void)layoutSubviews { 41 | [super layoutSubviews]; 42 | _collectionView.frame = self.bounds; 43 | } 44 | 45 | //设置默认颜色 46 | - (void)setDefaultColor { 47 | self.itemBackGoundColor = [UIColor lightGrayColor]; 48 | } 49 | 50 | 51 | #pragma mark - 52 | #pragma mark CollectonViewDataSource 53 | 54 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 55 | return 9; 56 | } 57 | 58 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { 59 | return [self itemSpacing]; 60 | } 61 | 62 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { 63 | return [self itemSpacing]; 64 | } 65 | 66 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { 67 | return CGSizeMake([self itemWidth], [self itemWidth]); 68 | } 69 | 70 | - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { 71 | return UIEdgeInsetsMake([self itemSpacing], [self itemSpacing], [self itemSpacing], [self itemSpacing]); 72 | } 73 | 74 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 75 | static NSString* cellId = @"XLGestureInfoViewCell"; 76 | XLGestureInfoViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellId forIndexPath:indexPath]; 77 | cell.gestureSelected = [_passWord containsString:[NSString stringWithFormat:@"%zd",indexPath.row]]; 78 | cell.itemBackGoundColor = self.itemBackGoundColor; 79 | return cell; 80 | } 81 | 82 | #pragma mark - 83 | #pragma mark CollectionView辅助方法 84 | - (CGFloat)itemSpacing { 85 | return self.bounds.size.width/10.0f; 86 | } 87 | 88 | - (CGFloat)itemWidth { 89 | return (self.bounds.size.width - 4*[self itemSpacing])/3.0f; 90 | } 91 | 92 | #pragma mark - 93 | #pragma mark 功能方法 94 | - (void)refresh { 95 | _passWord = @""; 96 | [_collectionView reloadData]; 97 | } 98 | 99 | #pragma mark - 100 | #pragma mark Setter 101 | - (void)setPassWord:(NSString *)passWord { 102 | _passWord = passWord; 103 | [_collectionView reloadData]; 104 | } 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePassword/XLGestureInfoViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // XLGestureInfoViewCell.h 3 | // XLGesturePasswordDemo 4 | // 5 | // Created by MengXianLiang on 2018/5/24. 6 | // Copyright © 2018年 jwzt. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface XLGestureInfoViewCell : UICollectionViewCell 12 | 13 | //item背景色 14 | @property (nonatomic, strong) UIColor *itemBackGoundColor; 15 | //手势选中 16 | @property (nonatomic, assign) BOOL gestureSelected; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePassword/XLGestureInfoViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // XLGestureInfoViewCell.m 3 | // XLGesturePasswordDemo 4 | // 5 | // Created by MengXianLiang on 2018/5/24. 6 | // Copyright © 2018年 jwzt. All rights reserved. 7 | // 8 | 9 | #import "XLGestureInfoViewCell.h" 10 | 11 | @implementation XLGestureInfoViewCell 12 | - (instancetype)initWithFrame:(CGRect)frame { 13 | if (self = [super initWithFrame:frame]) { 14 | [self buildUI]; 15 | } 16 | return self; 17 | } 18 | 19 | - (void)buildUI { 20 | self.layer.cornerRadius = self.bounds.size.height/2.0f; 21 | self.layer.masksToBounds = true; 22 | self.layer.borderWidth = 1.0f; 23 | self.layer.borderColor = [UIColor colorWithRed:129/255.0f green:129/255.0f blue:129/255.0f alpha:1].CGColor; 24 | } 25 | 26 | - (void)setGestureSelected:(BOOL)gestureSelected { 27 | if (gestureSelected) {//选中 28 | self.layer.borderWidth = 0; 29 | self.backgroundColor = _itemBackGoundColor; 30 | }else{//未选中 31 | self.layer.borderWidth = 1; 32 | self.backgroundColor = [UIColor whiteColor]; 33 | } 34 | } 35 | 36 | - (void)setItemBackGoundColor:(UIColor *)itemBackGoundColor { 37 | _itemBackGoundColor = itemBackGoundColor; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePassword/XLGesturePassword.h: -------------------------------------------------------------------------------- 1 | // 2 | // XLGesturePassword.h 3 | // 手势密码Demo 4 | // 5 | // Created by MengXianLiang on 2018/5/23. 6 | // Copyright © 2018年 jwzt. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef void(^PasswordBlock)(NSString *password); 12 | 13 | @interface XLGesturePassword : UIView 14 | //item背景色 默认浅灰色 15 | @property (nonatomic, strong) UIColor *itemBackGoundColor; 16 | //item中间圆球的颜色 默认灰色 17 | @property (nonatomic, strong) UIColor *itemCenterBallColor; 18 | //线条正常状态的颜色 默认灰色 19 | @property (nonatomic, strong) UIColor *lineNormalColor; 20 | //线条错误状态的颜色 默认红色 21 | @property (nonatomic, strong) UIColor *lineErrorColor; 22 | //重新输入 23 | - (void)refresh; 24 | //错误 25 | - (void)showError; 26 | //密码回调 27 | - (void)addPasswordBlock:(PasswordBlock)passwordBlock; 28 | @end 29 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePassword/XLGesturePassword.m: -------------------------------------------------------------------------------- 1 | // 2 | // XLGesturePassword.m 3 | // 手势密码Demo 4 | // 5 | // Created by MengXianLiang on 2018/5/23. 6 | // Copyright © 2018年 jwzt. All rights reserved. 7 | // 8 | 9 | #import "XLGesturePassword.h" 10 | #import "XLGesturePasswordCell.h" 11 | 12 | @interface XLGesturePassword () { 13 | //集合视图 14 | UICollectionView *_collectionView; 15 | //手势路径 16 | UIBezierPath *_path; 17 | //连线 18 | CAShapeLayer *_layer; 19 | //存放每次手势路径上的indexPath 20 | NSMutableArray *_passwordIndexPathArr; 21 | //密码block 22 | PasswordBlock _passwordBlock; 23 | } 24 | @end 25 | 26 | @implementation XLGesturePassword 27 | 28 | - (instancetype)init { 29 | if (self = [super init]) { 30 | [self buildUI]; 31 | [self setDefaultColor]; 32 | } 33 | return self; 34 | } 35 | 36 | - (void)buildUI { 37 | 38 | self.layer.masksToBounds = true; 39 | 40 | //初始化collectionView 41 | UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; 42 | _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout]; 43 | _collectionView.backgroundColor = [UIColor clearColor]; 44 | [_collectionView registerClass:[XLGesturePasswordCell class] forCellWithReuseIdentifier:@"XLGesturePasswordCell"]; 45 | _collectionView.dataSource = self; 46 | _collectionView.delegate = self; 47 | [self addSubview:_collectionView]; 48 | 49 | //初始化手势 50 | UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panMethod:)]; 51 | [_collectionView addGestureRecognizer:pan]; 52 | 53 | //创建运动路径 54 | _path = [UIBezierPath bezierPath]; 55 | 56 | //创建中间连线 57 | _layer = [CAShapeLayer layer]; 58 | _layer.fillColor = [UIColor clearColor].CGColor; 59 | _layer.lineWidth = 3; 60 | _layer.lineCap = kCALineCapRound; 61 | _layer.lineJoin = kCALineJoinRound; 62 | [self.layer addSublayer:_layer]; 63 | 64 | //初始选中化数组 65 | _passwordIndexPathArr = [[NSMutableArray alloc] init]; 66 | } 67 | 68 | //设置默认颜色 69 | - (void)setDefaultColor { 70 | self.itemBackGoundColor = [UIColor lightGrayColor]; 71 | self.itemCenterBallColor = [UIColor grayColor]; 72 | self.lineNormalColor = [UIColor grayColor]; 73 | self.lineErrorColor = [UIColor redColor]; 74 | } 75 | 76 | //自动布局 77 | - (void)layoutSubviews { 78 | [super layoutSubviews]; 79 | _collectionView.frame = self.bounds; 80 | } 81 | 82 | 83 | #pragma mark - 84 | #pragma mark CollectonViewDataSource 85 | 86 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 87 | return 9; 88 | } 89 | 90 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { 91 | return [self itemSpacing]; 92 | } 93 | 94 | - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { 95 | return [self itemSpacing]; 96 | } 97 | 98 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { 99 | return CGSizeMake([self itemWidth], [self itemWidth]); 100 | } 101 | 102 | - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { 103 | return UIEdgeInsetsMake([self itemSpacing], [self itemSpacing], [self itemSpacing], [self itemSpacing]); 104 | } 105 | 106 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 107 | static NSString* cellId = @"XLGesturePasswordCell"; 108 | XLGesturePasswordCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellId forIndexPath:indexPath]; 109 | cell.gestureSelected = [_passwordIndexPathArr containsObject:indexPath]; 110 | cell.itemBackGoundColor = self.itemBackGoundColor; 111 | cell.itemCenterBallColor = self.itemCenterBallColor; 112 | return cell; 113 | } 114 | 115 | #pragma mark - 116 | #pragma mark CollectionView辅助方法 117 | - (CGFloat)itemSpacing { 118 | return self.bounds.size.width/10.0f; 119 | } 120 | 121 | - (CGFloat)itemWidth { 122 | return (self.bounds.size.width - 4*[self itemSpacing])/3.0f; 123 | } 124 | 125 | #pragma mark - 126 | #pragma mark 手势相关方法 127 | - (void)panMethod:(UIPanGestureRecognizer *)pan { 128 | CGPoint point = [pan locationInView:_collectionView]; 129 | switch (pan.state) { 130 | case UIGestureRecognizerStateBegan: 131 | [self gestureBegan]; 132 | break; 133 | case UIGestureRecognizerStateChanged: 134 | [self gestureChanged:point]; 135 | break; 136 | case UIGestureRecognizerStateEnded: 137 | [self gestureEnded]; 138 | break; 139 | default: 140 | break; 141 | } 142 | } 143 | 144 | //手势开始 145 | - (void)gestureBegan { 146 | [self refresh]; 147 | } 148 | 149 | //手势变化 150 | - (void)gestureChanged:(CGPoint)point { 151 | [self updatePasswordIndexPathArr:point]; 152 | [self updateGesturePath:point]; 153 | } 154 | 155 | //更新路径上的indexPath 156 | - (void)updatePasswordIndexPathArr:(CGPoint)point { 157 | for (NSIndexPath *indexPath in _collectionView.indexPathsForVisibleItems) { 158 | XLGesturePasswordCell *cell = (XLGesturePasswordCell *)[_collectionView cellForItemAtIndexPath:indexPath]; 159 | if (CGRectContainsPoint(cell.frame, point)) { 160 | if (![_passwordIndexPathArr containsObject:indexPath]) { 161 | [_passwordIndexPathArr addObject:indexPath]; 162 | cell.gestureSelected = true; 163 | } 164 | } 165 | } 166 | } 167 | 168 | //绘制手势路径 169 | - (void)configGesturePath { 170 | [_path removeAllPoints]; 171 | for (NSInteger i = 0; i < _passwordIndexPathArr.count; i++) { 172 | NSIndexPath *indexPath = _passwordIndexPathArr[i]; 173 | UICollectionViewCell *cell = [_collectionView cellForItemAtIndexPath:indexPath]; 174 | if (i == 0) { 175 | [_path moveToPoint:cell.center]; 176 | }else { 177 | [_path addLineToPoint:cell.center]; 178 | } 179 | } 180 | _layer.path = _path.CGPath; 181 | } 182 | 183 | //更新手势路径 184 | - (void)updateGesturePath:(CGPoint)point { 185 | [self configGesturePath]; 186 | [_path addLineToPoint:point]; 187 | _layer.path = _path.CGPath; 188 | } 189 | 190 | //手势结束 191 | - (void)gestureEnded { 192 | //显示手势路径 193 | [self configGesturePath]; 194 | NSString *password = @""; 195 | for (NSIndexPath *indexPath in _passwordIndexPathArr) { 196 | password = [NSString stringWithFormat:@"%@%zd",password,indexPath.row]; 197 | } 198 | if (_passwordBlock) { 199 | _passwordBlock(password); 200 | } 201 | } 202 | 203 | #pragma mark - 204 | #pragma mark Setter 205 | //设置线条正常颜色 206 | - (void)setLineNormalColor:(UIColor *)lineNormalColor { 207 | _lineNormalColor = lineNormalColor; 208 | _layer.strokeColor = lineNormalColor.CGColor; 209 | } 210 | 211 | //设置线条错误颜色 212 | - (void)setLineErrorColor:(UIColor *)lineErrorColor { 213 | _lineErrorColor = lineErrorColor; 214 | } 215 | 216 | #pragma mark - 217 | #pragma mark 功能方法 218 | //报错 219 | - (void)showError { 220 | _layer.strokeColor = _lineErrorColor.CGColor; 221 | dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)); 222 | dispatch_after(delayTime, dispatch_get_main_queue(), ^{ 223 | [self refresh]; 224 | }); 225 | } 226 | //重置 227 | - (void)refresh { 228 | //刷新列表 229 | [_passwordIndexPathArr removeAllObjects]; 230 | [_collectionView reloadData]; 231 | //更新路径 232 | [_path removeAllPoints]; 233 | _layer.path = _path.CGPath; 234 | _layer.strokeColor = _lineNormalColor.CGColor; 235 | 236 | } 237 | 238 | //添加密码输入回调 239 | - (void)addPasswordBlock:(PasswordBlock)passwordBlock { 240 | _passwordBlock = passwordBlock; 241 | } 242 | @end 243 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePassword/XLGesturePasswordCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // XLGestureCell.h 3 | // 手势密码Demo 4 | // 5 | // Created by MengXianLiang on 2018/5/23. 6 | // Copyright © 2018年 jwzt. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface XLGesturePasswordCell : UICollectionViewCell 12 | 13 | //item背景色 14 | @property (nonatomic, strong) UIColor *itemBackGoundColor; 15 | //item中间圆球的颜色 16 | @property (nonatomic, strong) UIColor *itemCenterBallColor; 17 | //手势选中 18 | @property (nonatomic, assign) BOOL gestureSelected; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePassword/XLGesturePasswordCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // XLGestureCell.m 3 | // 手势密码Demo 4 | // 5 | // Created by MengXianLiang on 2018/5/23. 6 | // Copyright © 2018年 jwzt. All rights reserved. 7 | // 8 | 9 | #import "XLGesturePasswordCell.h" 10 | 11 | @interface XLGesturePasswordCell () { 12 | UIView *_centerBall; 13 | } 14 | @end 15 | 16 | @implementation XLGesturePasswordCell 17 | 18 | - (instancetype)initWithFrame:(CGRect)frame { 19 | if (self = [super initWithFrame:frame]) { 20 | [self buildUI]; 21 | } 22 | return self; 23 | } 24 | 25 | - (void)buildUI { 26 | self.layer.cornerRadius = self.bounds.size.height/2.0f; 27 | self.layer.masksToBounds = true; 28 | self.layer.borderWidth = 1.0f; 29 | self.layer.borderColor = [UIColor colorWithRed:129/255.0f green:129/255.0f blue:129/255.0f alpha:1].CGColor; 30 | 31 | CGFloat dotW = self.bounds.size.width*0.45; 32 | _centerBall = [[UIView alloc] initWithFrame:CGRectMake(0, 0, dotW, dotW)]; 33 | _centerBall.center = CGPointMake(self.bounds.size.width/2.0f, self.bounds.size.height/2.0f); 34 | _centerBall.layer.cornerRadius = _centerBall.bounds.size.height/2.0f; 35 | _centerBall.layer.masksToBounds = true; 36 | [self addSubview:_centerBall]; 37 | } 38 | 39 | - (void)setGestureSelected:(BOOL)gestureSelected { 40 | if (gestureSelected) {//选中 41 | self.layer.borderWidth = 0; 42 | _centerBall.hidden = false; 43 | self.backgroundColor = _itemBackGoundColor; 44 | }else{//未选中 45 | self.layer.borderWidth = 1; 46 | _centerBall.hidden = true; 47 | self.backgroundColor = [UIColor whiteColor]; 48 | } 49 | } 50 | 51 | - (void)setItemBackGoundColor:(UIColor *)itemBackGoundColor { 52 | _itemBackGoundColor = itemBackGoundColor; 53 | } 54 | 55 | - (void)setItemCenterBallColor:(UIColor *)itemCenterBallColor { 56 | _centerBall.backgroundColor = itemCenterBallColor; 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePasswordDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5E5738A620B54E5D00A1BEBE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E5738A520B54E5D00A1BEBE /* AppDelegate.m */; }; 11 | 5E5738A920B54E5E00A1BEBE /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E5738A820B54E5E00A1BEBE /* ViewController.m */; }; 12 | 5E5738AC20B54E5E00A1BEBE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5E5738AA20B54E5E00A1BEBE /* Main.storyboard */; }; 13 | 5E5738AE20B54E5F00A1BEBE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5E5738AD20B54E5F00A1BEBE /* Assets.xcassets */; }; 14 | 5E5738B120B54E5F00A1BEBE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5E5738AF20B54E5F00A1BEBE /* LaunchScreen.storyboard */; }; 15 | 5E5738B420B54E5F00A1BEBE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E5738B320B54E5F00A1BEBE /* main.m */; }; 16 | 5E5738C120B54E7100A1BEBE /* XLGesturePasswordCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E5738BB20B54E7000A1BEBE /* XLGesturePasswordCell.m */; }; 17 | 5E5738C220B54E7100A1BEBE /* XLGestureInfoView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E5738BD20B54E7000A1BEBE /* XLGestureInfoView.m */; }; 18 | 5E5738C320B54E7100A1BEBE /* XLGesturePassword.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E5738C020B54E7000A1BEBE /* XLGesturePassword.m */; }; 19 | 5E5738C620B654D400A1BEBE /* XLGestureInfoViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E5738C520B654D400A1BEBE /* XLGestureInfoViewCell.m */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 5E5738A120B54E5D00A1BEBE /* XLGesturePasswordDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XLGesturePasswordDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | 5E5738A420B54E5D00A1BEBE /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 25 | 5E5738A520B54E5D00A1BEBE /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 26 | 5E5738A720B54E5E00A1BEBE /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 27 | 5E5738A820B54E5E00A1BEBE /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 28 | 5E5738AB20B54E5E00A1BEBE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 29 | 5E5738AD20B54E5F00A1BEBE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 30 | 5E5738B020B54E5F00A1BEBE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 31 | 5E5738B220B54E5F00A1BEBE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32 | 5E5738B320B54E5F00A1BEBE /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 33 | 5E5738BB20B54E7000A1BEBE /* XLGesturePasswordCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XLGesturePasswordCell.m; sourceTree = ""; }; 34 | 5E5738BC20B54E7000A1BEBE /* XLGesturePassword.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XLGesturePassword.h; sourceTree = ""; }; 35 | 5E5738BD20B54E7000A1BEBE /* XLGestureInfoView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XLGestureInfoView.m; sourceTree = ""; }; 36 | 5E5738BE20B54E7000A1BEBE /* XLGesturePasswordCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XLGesturePasswordCell.h; sourceTree = ""; }; 37 | 5E5738BF20B54E7000A1BEBE /* XLGestureInfoView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XLGestureInfoView.h; sourceTree = ""; }; 38 | 5E5738C020B54E7000A1BEBE /* XLGesturePassword.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XLGesturePassword.m; sourceTree = ""; }; 39 | 5E5738C420B654D400A1BEBE /* XLGestureInfoViewCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XLGestureInfoViewCell.h; sourceTree = ""; }; 40 | 5E5738C520B654D400A1BEBE /* XLGestureInfoViewCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XLGestureInfoViewCell.m; sourceTree = ""; }; 41 | /* End PBXFileReference section */ 42 | 43 | /* Begin PBXFrameworksBuildPhase section */ 44 | 5E57389E20B54E5D00A1BEBE /* Frameworks */ = { 45 | isa = PBXFrameworksBuildPhase; 46 | buildActionMask = 2147483647; 47 | files = ( 48 | ); 49 | runOnlyForDeploymentPostprocessing = 0; 50 | }; 51 | /* End PBXFrameworksBuildPhase section */ 52 | 53 | /* Begin PBXGroup section */ 54 | 5E57389820B54E5D00A1BEBE = { 55 | isa = PBXGroup; 56 | children = ( 57 | 5E5738BA20B54E7000A1BEBE /* XLGesturePassword */, 58 | 5E5738A320B54E5D00A1BEBE /* XLGesturePasswordDemo */, 59 | 5E5738A220B54E5D00A1BEBE /* Products */, 60 | ); 61 | sourceTree = ""; 62 | }; 63 | 5E5738A220B54E5D00A1BEBE /* Products */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 5E5738A120B54E5D00A1BEBE /* XLGesturePasswordDemo.app */, 67 | ); 68 | name = Products; 69 | sourceTree = ""; 70 | }; 71 | 5E5738A320B54E5D00A1BEBE /* XLGesturePasswordDemo */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 5E5738A420B54E5D00A1BEBE /* AppDelegate.h */, 75 | 5E5738A520B54E5D00A1BEBE /* AppDelegate.m */, 76 | 5E5738A720B54E5E00A1BEBE /* ViewController.h */, 77 | 5E5738A820B54E5E00A1BEBE /* ViewController.m */, 78 | 5E5738AA20B54E5E00A1BEBE /* Main.storyboard */, 79 | 5E5738AD20B54E5F00A1BEBE /* Assets.xcassets */, 80 | 5E5738AF20B54E5F00A1BEBE /* LaunchScreen.storyboard */, 81 | 5E5738B220B54E5F00A1BEBE /* Info.plist */, 82 | 5E5738B320B54E5F00A1BEBE /* main.m */, 83 | ); 84 | path = XLGesturePasswordDemo; 85 | sourceTree = ""; 86 | }; 87 | 5E5738BA20B54E7000A1BEBE /* XLGesturePassword */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 5E5738BC20B54E7000A1BEBE /* XLGesturePassword.h */, 91 | 5E5738C020B54E7000A1BEBE /* XLGesturePassword.m */, 92 | 5E5738BE20B54E7000A1BEBE /* XLGesturePasswordCell.h */, 93 | 5E5738BB20B54E7000A1BEBE /* XLGesturePasswordCell.m */, 94 | 5E5738BF20B54E7000A1BEBE /* XLGestureInfoView.h */, 95 | 5E5738BD20B54E7000A1BEBE /* XLGestureInfoView.m */, 96 | 5E5738C420B654D400A1BEBE /* XLGestureInfoViewCell.h */, 97 | 5E5738C520B654D400A1BEBE /* XLGestureInfoViewCell.m */, 98 | ); 99 | path = XLGesturePassword; 100 | sourceTree = ""; 101 | }; 102 | /* End PBXGroup section */ 103 | 104 | /* Begin PBXNativeTarget section */ 105 | 5E5738A020B54E5D00A1BEBE /* XLGesturePasswordDemo */ = { 106 | isa = PBXNativeTarget; 107 | buildConfigurationList = 5E5738B720B54E5F00A1BEBE /* Build configuration list for PBXNativeTarget "XLGesturePasswordDemo" */; 108 | buildPhases = ( 109 | 5E57389D20B54E5D00A1BEBE /* Sources */, 110 | 5E57389E20B54E5D00A1BEBE /* Frameworks */, 111 | 5E57389F20B54E5D00A1BEBE /* Resources */, 112 | ); 113 | buildRules = ( 114 | ); 115 | dependencies = ( 116 | ); 117 | name = XLGesturePasswordDemo; 118 | productName = XLGesturePasswordDemo; 119 | productReference = 5E5738A120B54E5D00A1BEBE /* XLGesturePasswordDemo.app */; 120 | productType = "com.apple.product-type.application"; 121 | }; 122 | /* End PBXNativeTarget section */ 123 | 124 | /* Begin PBXProject section */ 125 | 5E57389920B54E5D00A1BEBE /* Project object */ = { 126 | isa = PBXProject; 127 | attributes = { 128 | LastUpgradeCheck = 0930; 129 | ORGANIZATIONNAME = jwzt; 130 | TargetAttributes = { 131 | 5E5738A020B54E5D00A1BEBE = { 132 | CreatedOnToolsVersion = 9.3; 133 | }; 134 | }; 135 | }; 136 | buildConfigurationList = 5E57389C20B54E5D00A1BEBE /* Build configuration list for PBXProject "XLGesturePasswordDemo" */; 137 | compatibilityVersion = "Xcode 9.3"; 138 | developmentRegion = en; 139 | hasScannedForEncodings = 0; 140 | knownRegions = ( 141 | en, 142 | Base, 143 | ); 144 | mainGroup = 5E57389820B54E5D00A1BEBE; 145 | productRefGroup = 5E5738A220B54E5D00A1BEBE /* Products */; 146 | projectDirPath = ""; 147 | projectRoot = ""; 148 | targets = ( 149 | 5E5738A020B54E5D00A1BEBE /* XLGesturePasswordDemo */, 150 | ); 151 | }; 152 | /* End PBXProject section */ 153 | 154 | /* Begin PBXResourcesBuildPhase section */ 155 | 5E57389F20B54E5D00A1BEBE /* Resources */ = { 156 | isa = PBXResourcesBuildPhase; 157 | buildActionMask = 2147483647; 158 | files = ( 159 | 5E5738B120B54E5F00A1BEBE /* LaunchScreen.storyboard in Resources */, 160 | 5E5738AE20B54E5F00A1BEBE /* Assets.xcassets in Resources */, 161 | 5E5738AC20B54E5E00A1BEBE /* Main.storyboard in Resources */, 162 | ); 163 | runOnlyForDeploymentPostprocessing = 0; 164 | }; 165 | /* End PBXResourcesBuildPhase section */ 166 | 167 | /* Begin PBXSourcesBuildPhase section */ 168 | 5E57389D20B54E5D00A1BEBE /* Sources */ = { 169 | isa = PBXSourcesBuildPhase; 170 | buildActionMask = 2147483647; 171 | files = ( 172 | 5E5738C320B54E7100A1BEBE /* XLGesturePassword.m in Sources */, 173 | 5E5738A920B54E5E00A1BEBE /* ViewController.m in Sources */, 174 | 5E5738C120B54E7100A1BEBE /* XLGesturePasswordCell.m in Sources */, 175 | 5E5738C220B54E7100A1BEBE /* XLGestureInfoView.m in Sources */, 176 | 5E5738C620B654D400A1BEBE /* XLGestureInfoViewCell.m in Sources */, 177 | 5E5738B420B54E5F00A1BEBE /* main.m in Sources */, 178 | 5E5738A620B54E5D00A1BEBE /* AppDelegate.m in Sources */, 179 | ); 180 | runOnlyForDeploymentPostprocessing = 0; 181 | }; 182 | /* End PBXSourcesBuildPhase section */ 183 | 184 | /* Begin PBXVariantGroup section */ 185 | 5E5738AA20B54E5E00A1BEBE /* Main.storyboard */ = { 186 | isa = PBXVariantGroup; 187 | children = ( 188 | 5E5738AB20B54E5E00A1BEBE /* Base */, 189 | ); 190 | name = Main.storyboard; 191 | sourceTree = ""; 192 | }; 193 | 5E5738AF20B54E5F00A1BEBE /* LaunchScreen.storyboard */ = { 194 | isa = PBXVariantGroup; 195 | children = ( 196 | 5E5738B020B54E5F00A1BEBE /* Base */, 197 | ); 198 | name = LaunchScreen.storyboard; 199 | sourceTree = ""; 200 | }; 201 | /* End PBXVariantGroup section */ 202 | 203 | /* Begin XCBuildConfiguration section */ 204 | 5E5738B520B54E5F00A1BEBE /* Debug */ = { 205 | isa = XCBuildConfiguration; 206 | buildSettings = { 207 | ALWAYS_SEARCH_USER_PATHS = NO; 208 | CLANG_ANALYZER_NONNULL = YES; 209 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 210 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 211 | CLANG_CXX_LIBRARY = "libc++"; 212 | CLANG_ENABLE_MODULES = YES; 213 | CLANG_ENABLE_OBJC_ARC = YES; 214 | CLANG_ENABLE_OBJC_WEAK = YES; 215 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 216 | CLANG_WARN_BOOL_CONVERSION = YES; 217 | CLANG_WARN_COMMA = YES; 218 | CLANG_WARN_CONSTANT_CONVERSION = YES; 219 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 220 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 221 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 222 | CLANG_WARN_EMPTY_BODY = YES; 223 | CLANG_WARN_ENUM_CONVERSION = YES; 224 | CLANG_WARN_INFINITE_RECURSION = YES; 225 | CLANG_WARN_INT_CONVERSION = YES; 226 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 227 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 228 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 229 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 230 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 231 | CLANG_WARN_STRICT_PROTOTYPES = YES; 232 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 233 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 234 | CLANG_WARN_UNREACHABLE_CODE = YES; 235 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 236 | CODE_SIGN_IDENTITY = "iPhone Developer"; 237 | COPY_PHASE_STRIP = NO; 238 | DEBUG_INFORMATION_FORMAT = dwarf; 239 | ENABLE_STRICT_OBJC_MSGSEND = YES; 240 | ENABLE_TESTABILITY = YES; 241 | GCC_C_LANGUAGE_STANDARD = gnu11; 242 | GCC_DYNAMIC_NO_PIC = NO; 243 | GCC_NO_COMMON_BLOCKS = YES; 244 | GCC_OPTIMIZATION_LEVEL = 0; 245 | GCC_PREPROCESSOR_DEFINITIONS = ( 246 | "DEBUG=1", 247 | "$(inherited)", 248 | ); 249 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 250 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 251 | GCC_WARN_UNDECLARED_SELECTOR = YES; 252 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 253 | GCC_WARN_UNUSED_FUNCTION = YES; 254 | GCC_WARN_UNUSED_VARIABLE = YES; 255 | IPHONEOS_DEPLOYMENT_TARGET = 11.3; 256 | MTL_ENABLE_DEBUG_INFO = YES; 257 | ONLY_ACTIVE_ARCH = YES; 258 | SDKROOT = iphoneos; 259 | }; 260 | name = Debug; 261 | }; 262 | 5E5738B620B54E5F00A1BEBE /* Release */ = { 263 | isa = XCBuildConfiguration; 264 | buildSettings = { 265 | ALWAYS_SEARCH_USER_PATHS = NO; 266 | CLANG_ANALYZER_NONNULL = YES; 267 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 268 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 269 | CLANG_CXX_LIBRARY = "libc++"; 270 | CLANG_ENABLE_MODULES = YES; 271 | CLANG_ENABLE_OBJC_ARC = YES; 272 | CLANG_ENABLE_OBJC_WEAK = YES; 273 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 274 | CLANG_WARN_BOOL_CONVERSION = YES; 275 | CLANG_WARN_COMMA = YES; 276 | CLANG_WARN_CONSTANT_CONVERSION = YES; 277 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 278 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 279 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 280 | CLANG_WARN_EMPTY_BODY = YES; 281 | CLANG_WARN_ENUM_CONVERSION = YES; 282 | CLANG_WARN_INFINITE_RECURSION = YES; 283 | CLANG_WARN_INT_CONVERSION = YES; 284 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 285 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 286 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 287 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 288 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 289 | CLANG_WARN_STRICT_PROTOTYPES = YES; 290 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 291 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 292 | CLANG_WARN_UNREACHABLE_CODE = YES; 293 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 294 | CODE_SIGN_IDENTITY = "iPhone Developer"; 295 | COPY_PHASE_STRIP = NO; 296 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 297 | ENABLE_NS_ASSERTIONS = NO; 298 | ENABLE_STRICT_OBJC_MSGSEND = YES; 299 | GCC_C_LANGUAGE_STANDARD = gnu11; 300 | GCC_NO_COMMON_BLOCKS = YES; 301 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 302 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 303 | GCC_WARN_UNDECLARED_SELECTOR = YES; 304 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 305 | GCC_WARN_UNUSED_FUNCTION = YES; 306 | GCC_WARN_UNUSED_VARIABLE = YES; 307 | IPHONEOS_DEPLOYMENT_TARGET = 11.3; 308 | MTL_ENABLE_DEBUG_INFO = NO; 309 | SDKROOT = iphoneos; 310 | VALIDATE_PRODUCT = YES; 311 | }; 312 | name = Release; 313 | }; 314 | 5E5738B820B54E5F00A1BEBE /* Debug */ = { 315 | isa = XCBuildConfiguration; 316 | buildSettings = { 317 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 318 | CODE_SIGN_STYLE = Automatic; 319 | DEVELOPMENT_TEAM = C78VF44FUP; 320 | INFOPLIST_FILE = XLGesturePasswordDemo/Info.plist; 321 | LD_RUNPATH_SEARCH_PATHS = ( 322 | "$(inherited)", 323 | "@executable_path/Frameworks", 324 | ); 325 | PRODUCT_BUNDLE_IDENTIFIER = com.jwzt.XLGesturePasswordDemo; 326 | PRODUCT_NAME = "$(TARGET_NAME)"; 327 | TARGETED_DEVICE_FAMILY = "1,2"; 328 | }; 329 | name = Debug; 330 | }; 331 | 5E5738B920B54E5F00A1BEBE /* Release */ = { 332 | isa = XCBuildConfiguration; 333 | buildSettings = { 334 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 335 | CODE_SIGN_STYLE = Automatic; 336 | DEVELOPMENT_TEAM = C78VF44FUP; 337 | INFOPLIST_FILE = XLGesturePasswordDemo/Info.plist; 338 | LD_RUNPATH_SEARCH_PATHS = ( 339 | "$(inherited)", 340 | "@executable_path/Frameworks", 341 | ); 342 | PRODUCT_BUNDLE_IDENTIFIER = com.jwzt.XLGesturePasswordDemo; 343 | PRODUCT_NAME = "$(TARGET_NAME)"; 344 | TARGETED_DEVICE_FAMILY = "1,2"; 345 | }; 346 | name = Release; 347 | }; 348 | /* End XCBuildConfiguration section */ 349 | 350 | /* Begin XCConfigurationList section */ 351 | 5E57389C20B54E5D00A1BEBE /* Build configuration list for PBXProject "XLGesturePasswordDemo" */ = { 352 | isa = XCConfigurationList; 353 | buildConfigurations = ( 354 | 5E5738B520B54E5F00A1BEBE /* Debug */, 355 | 5E5738B620B54E5F00A1BEBE /* Release */, 356 | ); 357 | defaultConfigurationIsVisible = 0; 358 | defaultConfigurationName = Release; 359 | }; 360 | 5E5738B720B54E5F00A1BEBE /* Build configuration list for PBXNativeTarget "XLGesturePasswordDemo" */ = { 361 | isa = XCConfigurationList; 362 | buildConfigurations = ( 363 | 5E5738B820B54E5F00A1BEBE /* Debug */, 364 | 5E5738B920B54E5F00A1BEBE /* Release */, 365 | ); 366 | defaultConfigurationIsVisible = 0; 367 | defaultConfigurationName = Release; 368 | }; 369 | /* End XCConfigurationList section */ 370 | }; 371 | rootObject = 5E57389920B54E5D00A1BEBE /* Project object */; 372 | } 373 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePasswordDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePasswordDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePasswordDemo.xcodeproj/project.xcworkspace/xcuserdata/MengXianLiang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengxianliang/XLGesturePassword/64fe12b176d62a9369f08e3962a8fde6b99731ff/XLGesturePasswordDemo/XLGesturePasswordDemo.xcodeproj/project.xcworkspace/xcuserdata/MengXianLiang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePasswordDemo.xcodeproj/xcuserdata/MengXianLiang.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 18 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePasswordDemo.xcodeproj/xcuserdata/MengXianLiang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | XLGesturePasswordDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePasswordDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // XLGesturePasswordDemo 4 | // 5 | // Created by MengXianLiang on 2018/5/23. 6 | // Copyright © 2018年 jwzt. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePasswordDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // XLGesturePasswordDemo 4 | // 5 | // Created by MengXianLiang on 2018/5/23. 6 | // Copyright © 2018年 jwzt. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePasswordDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePasswordDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePasswordDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePasswordDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 29 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePasswordDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePasswordDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // XLGesturePasswordDemo 4 | // 5 | // Created by MengXianLiang on 2018/5/23. 6 | // Copyright © 2018年 jwzt. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | - (IBAction)Reenter:(id)sender; 14 | 15 | - (IBAction)ShowError:(id)sender; 16 | 17 | 18 | @end 19 | 20 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePasswordDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // XLGesturePasswordDemo 4 | // 5 | // Created by MengXianLiang on 2018/5/23. 6 | // Copyright © 2018年 jwzt. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "XLGesturePassword.h" 11 | #import "XLGestureInfoView.h" 12 | 13 | @interface ViewController () { 14 | XLGesturePassword *_passWord; 15 | XLGestureInfoView *_infoView; 16 | } 17 | 18 | @end 19 | 20 | @implementation ViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | 25 | UIColor *blueColor = [UIColor colorWithRed:0/255.0f green:160/255.0f blue:229/255.0f alpha:1]; 26 | UIColor *ligntBlueColor = [UIColor colorWithRed:181/255.0f green:224/255.0f blue:244/255.0f alpha:1]; 27 | UIColor *redColor = [UIColor colorWithRed:253/255.0f green:106/255.0f blue:95/255.0f alpha:1]; 28 | 29 | //密码输入 30 | _passWord = [[XLGesturePassword alloc] init]; 31 | _passWord.bounds = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.width); 32 | _passWord.center = self.view.center; 33 | _passWord.itemBackGoundColor = ligntBlueColor; 34 | _passWord.itemCenterBallColor = blueColor; 35 | _passWord.lineNormalColor = blueColor; 36 | _passWord.lineErrorColor = redColor; 37 | [self.view addSubview:_passWord]; 38 | __weak typeof (self)weekSelf = self; 39 | [_passWord addPasswordBlock:^(NSString *password) { 40 | [weekSelf showPassword:password]; 41 | }]; 42 | 43 | //密码提示 44 | _infoView = [[XLGestureInfoView alloc] init]; 45 | _infoView.bounds = CGRectMake(0, 0, 80, 80); 46 | _infoView.center = CGPointMake(_passWord.center.x, CGRectGetMinY(_passWord.frame) - 50); 47 | _infoView.itemBackGoundColor = blueColor; 48 | [self.view addSubview:_infoView]; 49 | } 50 | 51 | - (void)showPassword:(NSString *)password { 52 | _infoView.passWord = password; 53 | NSLog(@"密码是:%@",password); 54 | } 55 | 56 | - (IBAction)Reenter:(id)sender { 57 | [_passWord refresh]; 58 | [_infoView refresh]; 59 | } 60 | 61 | - (IBAction)ShowError:(id)sender { 62 | [_passWord showError]; 63 | } 64 | 65 | - (void)didReceiveMemoryWarning { 66 | [super didReceiveMemoryWarning]; 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /XLGesturePasswordDemo/XLGesturePasswordDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // XLGesturePasswordDemo 4 | // 5 | // Created by MengXianLiang on 2018/5/23. 6 | // Copyright © 2018年 jwzt. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | --------------------------------------------------------------------------------