BRBaseView.m 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. //
  2. // BaseView.m
  3. // BRPickerViewDemo
  4. //
  5. // Created by renbo on 2017/8/11.
  6. // Copyright © 2017 irenb. All rights reserved.
  7. //
  8. // 最新代码下载地址:https://github.com/91renb/BRPickerView
  9. #import "BRBaseView.h"
  10. @interface BRBaseView ()
  11. // 蒙层视图
  12. @property (nonatomic, strong) UIView *maskView;
  13. // 标题栏背景视图
  14. @property (nonatomic, strong) UIView *titleBarView;
  15. // 左边取消按钮
  16. @property (nonatomic, strong) UIButton *cancelBtn;
  17. // 右边确定按钮
  18. @property (nonatomic, strong) UIButton *doneBtn;
  19. // 中间标题
  20. @property (nonatomic, strong) UILabel *titleLabel;
  21. // 取消按钮离屏幕边缘的距离
  22. @property (nonatomic, assign) CGFloat cancelBtnMargin;
  23. // 确定按钮离屏幕边缘的距离
  24. @property (nonatomic, assign) CGFloat doneBtnMargin;
  25. @end
  26. @implementation BRBaseView
  27. - (void)initUI {
  28. self.frame = self.keyView.bounds;
  29. // 设置子视图的宽度随着父视图变化
  30. self.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  31. if (!self.pickerStyle.hiddenMaskView) {
  32. [self addSubview:self.maskView];
  33. }
  34. [self addSubview:self.alertView];
  35. // 是否隐藏标题栏
  36. if (!self.pickerStyle.hiddenTitleBarView) {
  37. [self.alertView addSubview:self.titleBarView];
  38. [self.alertView sendSubviewToBack:self.titleBarView];
  39. if (!self.pickerStyle.hiddenTitleLabel) {
  40. [self.titleBarView addSubview:self.titleLabel];
  41. }
  42. if (!self.pickerStyle.hiddenCancelBtn) {
  43. [self.titleBarView addSubview:self.cancelBtn];
  44. // 获取边距
  45. if (self.pickerStyle.cancelBtnFrame.origin.x < self.bounds.size.width / 2) {
  46. self.cancelBtnMargin = self.pickerStyle.cancelBtnFrame.origin.x;
  47. } else {
  48. self.cancelBtnMargin = self.bounds.size.width - self.pickerStyle.cancelBtnFrame.origin.x - self.pickerStyle.cancelBtnFrame.size.width;
  49. }
  50. }
  51. if (!self.pickerStyle.hiddenDoneBtn) {
  52. [self.titleBarView addSubview:self.doneBtn];
  53. // 获取边距
  54. if (self.pickerStyle.doneBtnFrame.origin.x < self.bounds.size.width / 2) {
  55. self.doneBtnMargin = self.pickerStyle.doneBtnFrame.origin.x;
  56. } else {
  57. self.doneBtnMargin = self.bounds.size.width - self.pickerStyle.doneBtnFrame.origin.x - self.pickerStyle.doneBtnFrame.size.width;
  58. }
  59. }
  60. }
  61. }
  62. #pragma mark - 适配横屏安全区域,更新子视图布局
  63. - (void)layoutSubviews {
  64. [super layoutSubviews];
  65. if (_cancelBtn || _doneBtn) {
  66. if (@available(iOS 11.0, *)) {
  67. UIEdgeInsets safeInsets = self.safeAreaInsets;
  68. if (_cancelBtn) {
  69. CGRect cancelBtnFrame = self.pickerStyle.cancelBtnFrame;
  70. if (cancelBtnFrame.origin.x < MIN(self.bounds.size.width / 2, self.bounds.size.height / 2)) {
  71. cancelBtnFrame.origin.x += safeInsets.left;
  72. } else {
  73. cancelBtnFrame.origin.x = self.bounds.size.width - cancelBtnFrame.size.width - safeInsets.right - self.cancelBtnMargin;
  74. }
  75. self.cancelBtn.frame = cancelBtnFrame;
  76. }
  77. if (_doneBtn) {
  78. CGRect doneBtnFrame = self.pickerStyle.doneBtnFrame;
  79. if (doneBtnFrame.origin.x < MIN(self.bounds.size.width / 2, self.bounds.size.height / 2)) {
  80. doneBtnFrame.origin.x += safeInsets.left;
  81. } else {
  82. doneBtnFrame.origin.x = self.bounds.size.width - doneBtnFrame.size.width - safeInsets.right - self.doneBtnMargin;
  83. }
  84. self.doneBtn.frame = doneBtnFrame;
  85. }
  86. }
  87. }
  88. if (_alertView && self.pickerStyle.topCornerRadius > 0) {
  89. // 设置顶部圆角
  90. [BRPickerStyle br_setView:_alertView roundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight withRadius:self.pickerStyle.topCornerRadius];
  91. }
  92. }
  93. #pragma mark - 蒙层视图
  94. - (UIView *)maskView {
  95. if (!_maskView) {
  96. _maskView = [[UIView alloc]initWithFrame:self.keyView.bounds];
  97. _maskView.backgroundColor = self.pickerStyle.maskColor;
  98. // 设置子视图的大小随着父视图变化
  99. _maskView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  100. _maskView.userInteractionEnabled = YES;
  101. UITapGestureRecognizer *myTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(didTapMaskView:)];
  102. [_maskView addGestureRecognizer:myTap];
  103. }
  104. return _maskView;
  105. }
  106. #pragma mark - 弹框视图
  107. - (UIView *)alertView {
  108. if (!_alertView) {
  109. CGFloat accessoryViewHeight = 0;
  110. if (self.pickerHeaderView) {
  111. accessoryViewHeight += self.pickerHeaderView.bounds.size.height;
  112. }
  113. if (self.pickerFooterView) {
  114. accessoryViewHeight += self.pickerFooterView.bounds.size.height;
  115. }
  116. CGFloat height = self.pickerStyle.titleBarHeight + self.pickerStyle.pickerHeight + self.pickerStyle.paddingBottom + accessoryViewHeight;
  117. _alertView = [[UIView alloc]initWithFrame:CGRectMake(0, self.keyView.bounds.size.height - height, self.keyView.bounds.size.width, height)];
  118. _alertView.backgroundColor = self.pickerStyle.alertViewColor ? self.pickerStyle.alertViewColor : self.pickerStyle.pickerColor;
  119. if (!self.pickerStyle.topCornerRadius && !self.pickerStyle.hiddenShadowLine) {
  120. // 设置弹框视图顶部边框线
  121. UIView *shadowLineView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, _alertView.frame.size.width, self.pickerStyle.shadowLineHeight)];
  122. shadowLineView.backgroundColor = self.pickerStyle.shadowLineColor;
  123. shadowLineView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  124. [_alertView addSubview:shadowLineView];
  125. }
  126. _alertView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
  127. }
  128. return _alertView;
  129. }
  130. #pragma mark - 标题栏视图
  131. - (UIView *)titleBarView {
  132. if (!_titleBarView) {
  133. _titleBarView =[[UIView alloc]initWithFrame:CGRectMake(0, 0, self.keyView.bounds.size.width, self.pickerStyle.titleBarHeight)];
  134. _titleBarView.backgroundColor = self.pickerStyle.titleBarColor;
  135. _titleBarView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  136. if (!self.pickerStyle.hiddenTitleLine) {
  137. // 设置标题栏底部分割线
  138. UIView *titleLineView = [[UIView alloc]initWithFrame:CGRectMake(0, _titleBarView.frame.size.height - 0.5f, _titleBarView.frame.size.width, 0.5f)];
  139. titleLineView.backgroundColor = self.pickerStyle.titleLineColor;
  140. titleLineView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  141. [_titleBarView addSubview:titleLineView];
  142. }
  143. }
  144. return _titleBarView;
  145. }
  146. #pragma mark - 取消按钮
  147. - (UIButton *)cancelBtn {
  148. if (!_cancelBtn) {
  149. _cancelBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  150. _cancelBtn.frame = self.pickerStyle.cancelBtnFrame;
  151. _cancelBtn.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin;
  152. _cancelBtn.backgroundColor = self.pickerStyle.cancelColor;;
  153. _cancelBtn.titleLabel.font = self.pickerStyle.cancelTextFont;
  154. [_cancelBtn setTitleColor:self.pickerStyle.cancelTextColor forState:UIControlStateNormal];
  155. if (self.pickerStyle.cancelBtnImage) {
  156. [_cancelBtn setImage:self.pickerStyle.cancelBtnImage forState:UIControlStateNormal];
  157. }
  158. if (self.pickerStyle.cancelBtnTitle) {
  159. [_cancelBtn setTitle:self.pickerStyle.cancelBtnTitle forState:UIControlStateNormal];
  160. }
  161. [_cancelBtn addTarget:self action:@selector(clickCancelBtn) forControlEvents:UIControlEventTouchUpInside];
  162. // 设置按钮圆角或边框
  163. if (self.pickerStyle.cancelBorderStyle == BRBorderStyleSolid) {
  164. _cancelBtn.layer.cornerRadius = self.pickerStyle.cancelCornerRadius > 0 ? self.pickerStyle.cancelCornerRadius : 6.0f;
  165. _cancelBtn.layer.borderColor = self.pickerStyle.cancelTextColor.CGColor;
  166. _cancelBtn.layer.borderWidth = self.pickerStyle.cancelBorderWidth > 0 ? self.pickerStyle.cancelBorderWidth : 1.0f;
  167. _cancelBtn.layer.masksToBounds = YES;
  168. } else if (self.pickerStyle.cancelBorderStyle == BRBorderStyleFill) {
  169. _cancelBtn.layer.cornerRadius = self.pickerStyle.cancelCornerRadius > 0 ? self.pickerStyle.cancelCornerRadius : 6.0f;
  170. _cancelBtn.layer.masksToBounds = YES;
  171. }
  172. }
  173. return _cancelBtn;
  174. }
  175. #pragma mark - 确定按钮
  176. - (UIButton *)doneBtn {
  177. if (!_doneBtn) {
  178. _doneBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  179. _doneBtn.frame = self.pickerStyle.doneBtnFrame;
  180. _doneBtn.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin;
  181. _doneBtn.backgroundColor = self.pickerStyle.doneColor;
  182. if (self.pickerStyle.doneBtnImage) {
  183. [_doneBtn setImage:self.pickerStyle.doneBtnImage forState:UIControlStateNormal];
  184. }
  185. if (self.pickerStyle.doneBtnTitle) {
  186. _doneBtn.titleLabel.font = self.pickerStyle.doneTextFont;
  187. [_doneBtn setTitleColor:self.pickerStyle.doneTextColor forState:UIControlStateNormal];
  188. [_doneBtn setTitle:self.pickerStyle.doneBtnTitle forState:UIControlStateNormal];
  189. }
  190. [_doneBtn addTarget:self action:@selector(clickDoneBtn) forControlEvents:UIControlEventTouchUpInside];
  191. // 设置按钮圆角或边框
  192. if (self.pickerStyle.doneBorderStyle == BRBorderStyleSolid) {
  193. _doneBtn.layer.cornerRadius = self.pickerStyle.doneCornerRadius > 0 ? self.pickerStyle.doneCornerRadius : 6.0f;
  194. _doneBtn.layer.borderColor = self.pickerStyle.doneTextColor.CGColor;
  195. _doneBtn.layer.borderWidth = self.pickerStyle.doneBorderWidth > 0 ? self.pickerStyle.doneBorderWidth : 1.0f;
  196. _doneBtn.layer.masksToBounds = YES;
  197. } else if (self.pickerStyle.doneBorderStyle == BRBorderStyleFill) {
  198. _doneBtn.layer.cornerRadius = self.pickerStyle.doneCornerRadius > 0 ? self.pickerStyle.doneCornerRadius : 6.0f;
  199. _doneBtn.layer.masksToBounds = YES;
  200. }
  201. }
  202. return _doneBtn;
  203. }
  204. #pragma mark - 中间标题label
  205. - (UILabel *)titleLabel {
  206. if (!_titleLabel) {
  207. _titleLabel = [[UILabel alloc]initWithFrame:self.pickerStyle.titleLabelFrame];
  208. _titleLabel.backgroundColor = self.pickerStyle.titleLabelColor;
  209. _titleLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin;
  210. _titleLabel.textAlignment = NSTextAlignmentCenter;
  211. _titleLabel.font = self.pickerStyle.titleTextFont;
  212. _titleLabel.textColor = self.pickerStyle.titleTextColor;
  213. _titleLabel.text = self.title;
  214. }
  215. return _titleLabel;
  216. }
  217. #pragma mark - 点击蒙层视图事件
  218. - (void)didTapMaskView:(UITapGestureRecognizer *)sender {
  219. [self removePickerFromView:nil];
  220. if (self.cancelBlock) {
  221. self.cancelBlock();
  222. }
  223. }
  224. #pragma mark - 取消按钮的点击事件
  225. - (void)clickCancelBtn {
  226. [self removePickerFromView:nil];
  227. if (self.cancelBlock) {
  228. self.cancelBlock();
  229. }
  230. }
  231. #pragma mark - 确定按钮的点击事件
  232. - (void)clickDoneBtn {
  233. [self removePickerFromView:nil];
  234. if (self.doneBlock) {
  235. self.doneBlock();
  236. }
  237. }
  238. #pragma mark - 添加视图方法
  239. - (void)addPickerToView:(UIView *)view {
  240. if (view) {
  241. self.frame = view.bounds;
  242. self.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  243. CGFloat accessoryViewHeight = 0;
  244. if (self.pickerHeaderView) {
  245. CGRect rect = self.pickerHeaderView.frame;
  246. self.pickerHeaderView.frame = CGRectMake(0, 0, view.bounds.size.width, rect.size.height);
  247. self.pickerHeaderView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  248. [self addSubview:self.pickerHeaderView];
  249. accessoryViewHeight += self.pickerHeaderView.bounds.size.height;
  250. }
  251. if (self.pickerFooterView) {
  252. CGRect rect = self.pickerFooterView.frame;
  253. self.pickerFooterView.frame = CGRectMake(0, view.bounds.size.height - rect.size.height, view.bounds.size.width, rect.size.height);
  254. self.pickerFooterView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  255. [self addSubview:self.pickerFooterView];
  256. accessoryViewHeight += self.pickerFooterView.bounds.size.height;
  257. }
  258. [view addSubview:self];
  259. } else {
  260. [self initUI];
  261. if (self.pickerHeaderView) {
  262. CGRect rect = self.pickerHeaderView.frame;
  263. CGFloat titleBarHeight = self.pickerStyle.hiddenTitleBarView ? 0 : self.pickerStyle.titleBarHeight;
  264. self.pickerHeaderView.frame = CGRectMake(0, titleBarHeight, self.alertView.bounds.size.width, rect.size.height);
  265. self.pickerHeaderView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  266. [self.alertView addSubview:self.pickerHeaderView];
  267. }
  268. if (self.pickerFooterView) {
  269. CGRect rect = self.pickerFooterView.frame;
  270. self.pickerFooterView.frame = CGRectMake(0, self.alertView.bounds.size.height - self.pickerStyle.paddingBottom - rect.size.height, self.alertView.bounds.size.width, rect.size.height);
  271. self.pickerFooterView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  272. [self.alertView addSubview:self.pickerFooterView];
  273. }
  274. [self.keyView addSubview:self];
  275. // iOS16:重新设置 alertView 高度(解决懒加载设置frame不生效问题)
  276. CGFloat accessoryViewHeight = 0;
  277. if (self.pickerHeaderView) {
  278. accessoryViewHeight += self.pickerHeaderView.bounds.size.height;
  279. }
  280. if (self.pickerFooterView) {
  281. accessoryViewHeight += self.pickerFooterView.bounds.size.height;
  282. }
  283. CGFloat height = self.pickerStyle.titleBarHeight + self.pickerStyle.pickerHeight + self.pickerStyle.paddingBottom + accessoryViewHeight;
  284. self.alertView.frame = CGRectMake(0, self.keyView.bounds.size.height - height, self.keyView.bounds.size.width, height);
  285. // 动画前初始位置
  286. CGRect rect = self.alertView.frame;
  287. rect.origin.y = self.bounds.size.height;
  288. self.alertView.frame = rect;
  289. // 弹出动画
  290. if (!self.pickerStyle.hiddenMaskView) {
  291. self.maskView.alpha = 0;
  292. }
  293. [UIView animateWithDuration:0.3f animations:^{
  294. if (!self.pickerStyle.hiddenMaskView) {
  295. self.maskView.alpha = 1;
  296. }
  297. CGFloat alertViewHeight = self.alertView.bounds.size.height;
  298. CGRect rect = self.alertView.frame;
  299. rect.origin.y -= alertViewHeight;
  300. self.alertView.frame = rect;
  301. }];
  302. }
  303. }
  304. #pragma mark - 移除视图方法
  305. - (void)removePickerFromView:(UIView *)view {
  306. if (view) {
  307. [self removeFromSuperview];
  308. } else {
  309. // 关闭动画
  310. [UIView animateWithDuration:0.2f animations:^{
  311. CGFloat alertViewHeight = self.alertView.bounds.size.height;
  312. CGRect rect = self.alertView.frame;
  313. rect.origin.y += alertViewHeight;
  314. self.alertView.frame = rect;
  315. if (!self.pickerStyle.hiddenMaskView) {
  316. self.maskView.alpha = 0;
  317. }
  318. } completion:^(BOOL finished) {
  319. [self removeFromSuperview];
  320. }];
  321. }
  322. }
  323. #pragma mark - 刷新选择器数据
  324. - (void)reloadData {
  325. }
  326. #pragma mark - 添加自定义视图到选择器(picker)上
  327. - (void)addSubViewToPicker:(UIView *)customView {
  328. }
  329. #pragma mark - 添加自定义视图到标题栏(titleBar)上
  330. - (void)addSubViewToTitleBar:(UIView *)customView {
  331. if (!self.pickerStyle.hiddenTitleBarView) {
  332. [self.titleBarView addSubview:customView];
  333. }
  334. }
  335. - (BRPickerStyle *)pickerStyle {
  336. if (!_pickerStyle) {
  337. _pickerStyle = [[BRPickerStyle alloc]init];
  338. }
  339. return _pickerStyle;
  340. }
  341. - (UIView *)keyView {
  342. if (!_keyView) {
  343. _keyView = BRGetKeyWindow();
  344. }
  345. return _keyView;
  346. }
  347. #pragma mark - setter 方法(支持动态设置标题)
  348. - (void)setTitle:(NSString *)title {
  349. _title = title;
  350. if (_titleLabel) {
  351. _titleLabel.text = title;
  352. }
  353. }
  354. - (void)dealloc {
  355. NSLog(@"%@ dealloc", NSStringFromClass([self class]));
  356. }
  357. @end