This commit is contained in:
DDIsFriend
2023-09-04 16:39:06 +08:00
parent 115f27422e
commit 3b9b465d22
100 changed files with 29843 additions and 7812 deletions
+76
View File
@@ -0,0 +1,76 @@
//
// BaseView.h
// BRPickerViewDemo
//
// Created by renbo on 2017/8/11.
// Copyright © 2017 irenb. All rights reserved.
//
// 最新代码下载地址:https://github.com/91renb/BRPickerView
#import <UIKit/UIKit.h>
#import "BRPickerStyle.h"
NS_ASSUME_NONNULL_BEGIN
typedef void(^BRCancelBlock)(void);
typedef void(^BRDoneClickBlock)(void);
@interface BRBaseView : UIView
/** 选择器标题 */
@property (nullable, nonatomic, copy) NSString *title;
/** 是否自动选择,即滚动选择器后就执行结果回调,默认为 NO */
@property (nonatomic, assign) BOOL isAutoSelect;
/** 自定义UI样式(不传或为nil时,是默认样式) */
@property (nullable, nonatomic, strong) BRPickerStyle *pickerStyle;
/** 取消选择的回调 */
@property (nullable, nonatomic, copy) BRCancelBlock cancelBlock;
/** accessory view for above picker view. default is nil */
@property (nullable, nonatomic, strong) UIView *pickerHeaderView;
/** accessory view below picker view. default is nil */
@property (nullable, nonatomic, strong) UIView *pickerFooterView;
/// 确定按钮点击事件的回调
/// 应用场景:如果是自定义确定按钮,需要在该按钮点击事件方法里,执行一下 doneBlock 回调。目的是触发组件内部执行 resultBlock 回调,回调选择的值
@property (nullable, nonatomic, copy) BRDoneClickBlock doneBlock;
/** 弹框视图(使用场景:可以在 alertView 上添加选择器的自定义背景视图) */
@property (nullable, nonatomic, strong) UIView *alertView;
/** 组件的父视图:可以传 自己获取的 keyWindow,或页面的 view */
@property (nullable, nonatomic, strong) UIView *keyView;
/// 刷新选择器数据
/// 应用场景:动态更新数据源、动态更新选择的值、选择器类型切换等
- (void)reloadData;
/// 扩展一:添加选择器到指定容器视图上
/// 应用场景:可将中间的滚轮选择器 pickerView 视图(不包含蒙层及标题栏)添加到任何自定义视图上(会自动填满容器视图),也方便自定义更多的弹框样式
/// 补充说明:如果是自定义确定按钮,需要回调默认选择的值:只需在自定义确定按钮的点击事件方法里执行一下 doneBlock 回调(目的是去触发组件内部执行 resultBlock 回调,进而回调默认选择的值)
/// @param view 容器视图
- (void)addPickerToView:(nullable UIView *)view NS_REQUIRES_SUPER;
/// 从指定容器视图上移除选择器
/// @param view 容器视图
- (void)removePickerFromView:(nullable UIView *)view;
/// 扩展二:添加自定义视图到选择器(pickerView)上
/// 应用场景:可以添加一些固定的标题、单位等到选择器中间
/// @param customView 自定义视图
- (void)addSubViewToPicker:(UIView *)customView;
/// 扩展三:添加自定义视图到标题栏(titleBarView)上
/// 应用场景:可以添加一些子控件到标题栏
/// @param customView 自定义视图
- (void)addSubViewToTitleBar:(UIView *)customView;
@end
NS_ASSUME_NONNULL_END
+398
View File
@@ -0,0 +1,398 @@
//
// BaseView.m
// BRPickerViewDemo
//
// Created by renbo on 2017/8/11.
// Copyright © 2017 irenb. All rights reserved.
//
// 最新代码下载地址:https://github.com/91renb/BRPickerView
#import "BRBaseView.h"
@interface BRBaseView ()
// 蒙层视图
@property (nonatomic, strong) UIView *maskView;
// 标题栏背景视图
@property (nonatomic, strong) UIView *titleBarView;
// 左边取消按钮
@property (nonatomic, strong) UIButton *cancelBtn;
// 右边确定按钮
@property (nonatomic, strong) UIButton *doneBtn;
// 中间标题
@property (nonatomic, strong) UILabel *titleLabel;
// 取消按钮离屏幕边缘的距离
@property (nonatomic, assign) CGFloat cancelBtnMargin;
// 确定按钮离屏幕边缘的距离
@property (nonatomic, assign) CGFloat doneBtnMargin;
@end
@implementation BRBaseView
- (void)initUI {
self.frame = self.keyView.bounds;
// 设置子视图的宽度随着父视图变化
self.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
if (!self.pickerStyle.hiddenMaskView) {
[self addSubview:self.maskView];
}
[self addSubview:self.alertView];
// 是否隐藏标题栏
if (!self.pickerStyle.hiddenTitleBarView) {
[self.alertView addSubview:self.titleBarView];
[self.alertView sendSubviewToBack:self.titleBarView];
if (!self.pickerStyle.hiddenTitleLabel) {
[self.titleBarView addSubview:self.titleLabel];
}
if (!self.pickerStyle.hiddenCancelBtn) {
[self.titleBarView addSubview:self.cancelBtn];
// 获取边距
if (self.pickerStyle.cancelBtnFrame.origin.x < self.bounds.size.width / 2) {
self.cancelBtnMargin = self.pickerStyle.cancelBtnFrame.origin.x;
} else {
self.cancelBtnMargin = self.bounds.size.width - self.pickerStyle.cancelBtnFrame.origin.x - self.pickerStyle.cancelBtnFrame.size.width;
}
}
if (!self.pickerStyle.hiddenDoneBtn) {
[self.titleBarView addSubview:self.doneBtn];
// 获取边距
if (self.pickerStyle.doneBtnFrame.origin.x < self.bounds.size.width / 2) {
self.doneBtnMargin = self.pickerStyle.doneBtnFrame.origin.x;
} else {
self.doneBtnMargin = self.bounds.size.width - self.pickerStyle.doneBtnFrame.origin.x - self.pickerStyle.doneBtnFrame.size.width;
}
}
}
}
#pragma mark - 适配横屏安全区域,更新子视图布局
- (void)layoutSubviews {
[super layoutSubviews];
if (_cancelBtn || _doneBtn) {
if (@available(iOS 11.0, *)) {
UIEdgeInsets safeInsets = self.safeAreaInsets;
if (_cancelBtn) {
CGRect cancelBtnFrame = self.pickerStyle.cancelBtnFrame;
if (cancelBtnFrame.origin.x < MIN(self.bounds.size.width / 2, self.bounds.size.height / 2)) {
cancelBtnFrame.origin.x += safeInsets.left;
} else {
cancelBtnFrame.origin.x = self.bounds.size.width - cancelBtnFrame.size.width - safeInsets.right - self.cancelBtnMargin;
}
self.cancelBtn.frame = cancelBtnFrame;
}
if (_doneBtn) {
CGRect doneBtnFrame = self.pickerStyle.doneBtnFrame;
if (doneBtnFrame.origin.x < MIN(self.bounds.size.width / 2, self.bounds.size.height / 2)) {
doneBtnFrame.origin.x += safeInsets.left;
} else {
doneBtnFrame.origin.x = self.bounds.size.width - doneBtnFrame.size.width - safeInsets.right - self.doneBtnMargin;
}
self.doneBtn.frame = doneBtnFrame;
}
}
}
if (_alertView && self.pickerStyle.topCornerRadius > 0) {
// 设置顶部圆角
[BRPickerStyle br_setView:_alertView roundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight withRadius:self.pickerStyle.topCornerRadius];
}
}
#pragma mark - 蒙层视图
- (UIView *)maskView {
if (!_maskView) {
_maskView = [[UIView alloc]initWithFrame:self.keyView.bounds];
_maskView.backgroundColor = self.pickerStyle.maskColor;
// 设置子视图的大小随着父视图变化
_maskView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_maskView.userInteractionEnabled = YES;
UITapGestureRecognizer *myTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(didTapMaskView:)];
[_maskView addGestureRecognizer:myTap];
}
return _maskView;
}
#pragma mark - 弹框视图
- (UIView *)alertView {
if (!_alertView) {
CGFloat accessoryViewHeight = 0;
if (self.pickerHeaderView) {
accessoryViewHeight += self.pickerHeaderView.bounds.size.height;
}
if (self.pickerFooterView) {
accessoryViewHeight += self.pickerFooterView.bounds.size.height;
}
CGFloat height = self.pickerStyle.titleBarHeight + self.pickerStyle.pickerHeight + self.pickerStyle.paddingBottom + accessoryViewHeight;
_alertView = [[UIView alloc]initWithFrame:CGRectMake(0, self.keyView.bounds.size.height - height, self.keyView.bounds.size.width, height)];
_alertView.backgroundColor = self.pickerStyle.alertViewColor ? self.pickerStyle.alertViewColor : self.pickerStyle.pickerColor;
if (!self.pickerStyle.topCornerRadius && !self.pickerStyle.hiddenShadowLine) {
// 设置弹框视图顶部边框线
UIView *shadowLineView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, _alertView.frame.size.width, self.pickerStyle.shadowLineHeight)];
shadowLineView.backgroundColor = self.pickerStyle.shadowLineColor;
shadowLineView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[_alertView addSubview:shadowLineView];
}
_alertView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
}
return _alertView;
}
#pragma mark - 标题栏视图
- (UIView *)titleBarView {
if (!_titleBarView) {
_titleBarView =[[UIView alloc]initWithFrame:CGRectMake(0, 0, self.keyView.bounds.size.width, self.pickerStyle.titleBarHeight)];
_titleBarView.backgroundColor = self.pickerStyle.titleBarColor;
_titleBarView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
if (!self.pickerStyle.hiddenTitleLine) {
// 设置标题栏底部分割线
UIView *titleLineView = [[UIView alloc]initWithFrame:CGRectMake(0, _titleBarView.frame.size.height - 0.5f, _titleBarView.frame.size.width, 0.5f)];
titleLineView.backgroundColor = self.pickerStyle.titleLineColor;
titleLineView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[_titleBarView addSubview:titleLineView];
}
}
return _titleBarView;
}
#pragma mark - 取消按钮
- (UIButton *)cancelBtn {
if (!_cancelBtn) {
_cancelBtn = [UIButton buttonWithType:UIButtonTypeCustom];
_cancelBtn.frame = self.pickerStyle.cancelBtnFrame;
_cancelBtn.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin;
_cancelBtn.backgroundColor = self.pickerStyle.cancelColor;;
_cancelBtn.titleLabel.font = self.pickerStyle.cancelTextFont;
[_cancelBtn setTitleColor:self.pickerStyle.cancelTextColor forState:UIControlStateNormal];
if (self.pickerStyle.cancelBtnImage) {
[_cancelBtn setImage:self.pickerStyle.cancelBtnImage forState:UIControlStateNormal];
}
if (self.pickerStyle.cancelBtnTitle) {
[_cancelBtn setTitle:self.pickerStyle.cancelBtnTitle forState:UIControlStateNormal];
}
[_cancelBtn addTarget:self action:@selector(clickCancelBtn) forControlEvents:UIControlEventTouchUpInside];
// 设置按钮圆角或边框
if (self.pickerStyle.cancelBorderStyle == BRBorderStyleSolid) {
_cancelBtn.layer.cornerRadius = self.pickerStyle.cancelCornerRadius > 0 ? self.pickerStyle.cancelCornerRadius : 6.0f;
_cancelBtn.layer.borderColor = self.pickerStyle.cancelTextColor.CGColor;
_cancelBtn.layer.borderWidth = self.pickerStyle.cancelBorderWidth > 0 ? self.pickerStyle.cancelBorderWidth : 1.0f;
_cancelBtn.layer.masksToBounds = YES;
} else if (self.pickerStyle.cancelBorderStyle == BRBorderStyleFill) {
_cancelBtn.layer.cornerRadius = self.pickerStyle.cancelCornerRadius > 0 ? self.pickerStyle.cancelCornerRadius : 6.0f;
_cancelBtn.layer.masksToBounds = YES;
}
}
return _cancelBtn;
}
#pragma mark - 确定按钮
- (UIButton *)doneBtn {
if (!_doneBtn) {
_doneBtn = [UIButton buttonWithType:UIButtonTypeCustom];
_doneBtn.frame = self.pickerStyle.doneBtnFrame;
_doneBtn.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin;
_doneBtn.backgroundColor = self.pickerStyle.doneColor;
if (self.pickerStyle.doneBtnImage) {
[_doneBtn setImage:self.pickerStyle.doneBtnImage forState:UIControlStateNormal];
}
if (self.pickerStyle.doneBtnTitle) {
_doneBtn.titleLabel.font = self.pickerStyle.doneTextFont;
[_doneBtn setTitleColor:self.pickerStyle.doneTextColor forState:UIControlStateNormal];
[_doneBtn setTitle:self.pickerStyle.doneBtnTitle forState:UIControlStateNormal];
}
[_doneBtn addTarget:self action:@selector(clickDoneBtn) forControlEvents:UIControlEventTouchUpInside];
// 设置按钮圆角或边框
if (self.pickerStyle.doneBorderStyle == BRBorderStyleSolid) {
_doneBtn.layer.cornerRadius = self.pickerStyle.doneCornerRadius > 0 ? self.pickerStyle.doneCornerRadius : 6.0f;
_doneBtn.layer.borderColor = self.pickerStyle.doneTextColor.CGColor;
_doneBtn.layer.borderWidth = self.pickerStyle.doneBorderWidth > 0 ? self.pickerStyle.doneBorderWidth : 1.0f;
_doneBtn.layer.masksToBounds = YES;
} else if (self.pickerStyle.doneBorderStyle == BRBorderStyleFill) {
_doneBtn.layer.cornerRadius = self.pickerStyle.doneCornerRadius > 0 ? self.pickerStyle.doneCornerRadius : 6.0f;
_doneBtn.layer.masksToBounds = YES;
}
}
return _doneBtn;
}
#pragma mark - 中间标题label
- (UILabel *)titleLabel {
if (!_titleLabel) {
_titleLabel = [[UILabel alloc]initWithFrame:self.pickerStyle.titleLabelFrame];
_titleLabel.backgroundColor = self.pickerStyle.titleLabelColor;
_titleLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin;
_titleLabel.textAlignment = NSTextAlignmentCenter;
_titleLabel.font = self.pickerStyle.titleTextFont;
_titleLabel.textColor = self.pickerStyle.titleTextColor;
_titleLabel.text = self.title;
}
return _titleLabel;
}
#pragma mark - 点击蒙层视图事件
- (void)didTapMaskView:(UITapGestureRecognizer *)sender {
[self removePickerFromView:nil];
if (self.cancelBlock) {
self.cancelBlock();
}
}
#pragma mark - 取消按钮的点击事件
- (void)clickCancelBtn {
[self removePickerFromView:nil];
if (self.cancelBlock) {
self.cancelBlock();
}
}
#pragma mark - 确定按钮的点击事件
- (void)clickDoneBtn {
[self removePickerFromView:nil];
if (self.doneBlock) {
self.doneBlock();
}
}
#pragma mark - 添加视图方法
- (void)addPickerToView:(UIView *)view {
if (view) {
self.frame = view.bounds;
self.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
CGFloat accessoryViewHeight = 0;
if (self.pickerHeaderView) {
CGRect rect = self.pickerHeaderView.frame;
self.pickerHeaderView.frame = CGRectMake(0, 0, view.bounds.size.width, rect.size.height);
self.pickerHeaderView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self addSubview:self.pickerHeaderView];
accessoryViewHeight += self.pickerHeaderView.bounds.size.height;
}
if (self.pickerFooterView) {
CGRect rect = self.pickerFooterView.frame;
self.pickerFooterView.frame = CGRectMake(0, view.bounds.size.height - rect.size.height, view.bounds.size.width, rect.size.height);
self.pickerFooterView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self addSubview:self.pickerFooterView];
accessoryViewHeight += self.pickerFooterView.bounds.size.height;
}
[view addSubview:self];
} else {
[self initUI];
if (self.pickerHeaderView) {
CGRect rect = self.pickerHeaderView.frame;
CGFloat titleBarHeight = self.pickerStyle.hiddenTitleBarView ? 0 : self.pickerStyle.titleBarHeight;
self.pickerHeaderView.frame = CGRectMake(0, titleBarHeight, self.alertView.bounds.size.width, rect.size.height);
self.pickerHeaderView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self.alertView addSubview:self.pickerHeaderView];
}
if (self.pickerFooterView) {
CGRect rect = self.pickerFooterView.frame;
self.pickerFooterView.frame = CGRectMake(0, self.alertView.bounds.size.height - self.pickerStyle.paddingBottom - rect.size.height, self.alertView.bounds.size.width, rect.size.height);
self.pickerFooterView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self.alertView addSubview:self.pickerFooterView];
}
[self.keyView addSubview:self];
// iOS16:重新设置 alertView 高度(解决懒加载设置frame不生效问题)
CGFloat accessoryViewHeight = 0;
if (self.pickerHeaderView) {
accessoryViewHeight += self.pickerHeaderView.bounds.size.height;
}
if (self.pickerFooterView) {
accessoryViewHeight += self.pickerFooterView.bounds.size.height;
}
CGFloat height = self.pickerStyle.titleBarHeight + self.pickerStyle.pickerHeight + self.pickerStyle.paddingBottom + accessoryViewHeight;
self.alertView.frame = CGRectMake(0, self.keyView.bounds.size.height - height, self.keyView.bounds.size.width, height);
// 动画前初始位置
CGRect rect = self.alertView.frame;
rect.origin.y = self.bounds.size.height;
self.alertView.frame = rect;
// 弹出动画
if (!self.pickerStyle.hiddenMaskView) {
self.maskView.alpha = 0;
}
[UIView animateWithDuration:0.3f animations:^{
if (!self.pickerStyle.hiddenMaskView) {
self.maskView.alpha = 1;
}
CGFloat alertViewHeight = self.alertView.bounds.size.height;
CGRect rect = self.alertView.frame;
rect.origin.y -= alertViewHeight;
self.alertView.frame = rect;
}];
}
}
#pragma mark - 移除视图方法
- (void)removePickerFromView:(UIView *)view {
if (view) {
[self removeFromSuperview];
} else {
// 关闭动画
[UIView animateWithDuration:0.2f animations:^{
CGFloat alertViewHeight = self.alertView.bounds.size.height;
CGRect rect = self.alertView.frame;
rect.origin.y += alertViewHeight;
self.alertView.frame = rect;
if (!self.pickerStyle.hiddenMaskView) {
self.maskView.alpha = 0;
}
} completion:^(BOOL finished) {
[self removeFromSuperview];
}];
}
}
#pragma mark - 刷新选择器数据
- (void)reloadData {
}
#pragma mark - 添加自定义视图到选择器(picker)上
- (void)addSubViewToPicker:(UIView *)customView {
}
#pragma mark - 添加自定义视图到标题栏(titleBar)上
- (void)addSubViewToTitleBar:(UIView *)customView {
if (!self.pickerStyle.hiddenTitleBarView) {
[self.titleBarView addSubview:customView];
}
}
- (BRPickerStyle *)pickerStyle {
if (!_pickerStyle) {
_pickerStyle = [[BRPickerStyle alloc]init];
}
return _pickerStyle;
}
- (UIView *)keyView {
if (!_keyView) {
_keyView = BRGetKeyWindow();
}
return _keyView;
}
#pragma mark - setter 方法(支持动态设置标题)
- (void)setTitle:(NSString *)title {
_title = title;
if (_titleLabel) {
_titleLabel.text = title;
}
}
- (void)dealloc {
NSLog(@"%@ dealloc", NSStringFromClass([self class]));
}
@end
+251
View File
@@ -0,0 +1,251 @@
//
// BRPickerStyle.h
// BRPickerViewDemo
//
// Created by renbo on 2019/10/2.
// Copyright © 2019 irenb. All rights reserved.
//
// 最新代码下载地址:https://github.com/91renb/BRPickerView
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "BRPickerViewMacro.h"
NS_ASSUME_NONNULL_BEGIN
// 边框样式(左边取消按钮/右边确定按钮)
typedef NS_ENUM(NSInteger, BRBorderStyle) {
/** 无边框(默认) */
BRBorderStyleNone = 0,
/** 有圆角和边框 */
BRBorderStyleSolid,
/** 仅有圆角 */
BRBorderStyleFill
};
@interface BRPickerStyle : NSObject
/////////////////////////////// 蒙层视图(maskView///////////////////////////////
/** 设置背景颜色 */
@property (nullable, nonatomic, strong) UIColor *maskColor;
/** 隐藏 maskView,默认为 NO */
@property (nonatomic, assign) BOOL hiddenMaskView;
////////////////////////////// 弹框视图(alertView///////////////////////////////
/** 设置 alertView 弹框视图的背景颜色 */
@property (nullable, nonatomic, strong) UIColor *alertViewColor;
/** 设置 alertView 弹框视图左上和右上的圆角半径 */
@property (nonatomic, assign) NSInteger topCornerRadius;
/** 设置 alertView 弹框视图顶部边框线颜色 */
@property (nullable, nonatomic, strong) UIColor *shadowLineColor;
/** 设置 alertView 弹框视图顶部边框线高度 */
@property (nonatomic, assign) CGFloat shadowLineHeight;
/** 隐藏 alertView 弹框视图顶部边框线,默认为 NO */
@property (nonatomic, assign) BOOL hiddenShadowLine;
/** 设置 alertView 弹框视图底部内边距,默认为安全区域底部距屏幕底部的高度 */
@property (nonatomic, assign) CGFloat paddingBottom;
//////////////////////////// 标题栏视图(titleBarView ////////////////////////////
/** 设置 titleBarView 标题栏的背景颜色 */
@property (nullable, nonatomic, strong) UIColor *titleBarColor;
/** 设置 titleBarView 标题栏的高度 */
@property (nonatomic, assign) CGFloat titleBarHeight;
/** 设置 titleBarView 标题栏底部分割线颜色 */
@property (nullable, nonatomic, strong) UIColor *titleLineColor;
/** 隐藏 titleBarView 标题栏底部分割线,默认为 NO */
@property (nonatomic, assign) BOOL hiddenTitleLine;
/** 隐藏 titleBarView,默认为 NO */
@property (nonatomic, assign) BOOL hiddenTitleBarView;
////////////////////////// 标题栏中间labeltitleLabel///////////////////////////
/** 设置 titleLabel 的背景颜色 */
@property (nullable, nonatomic, strong) UIColor *titleLabelColor;
/** 设置 titleLabel 文本颜色 */
@property (nullable, nonatomic, strong) UIColor *titleTextColor;
/** 设置 titleLabel 字体大小 */
@property (nullable, nonatomic, strong) UIFont *titleTextFont;
/** 设置 titleLabel 的 frame */
@property (nonatomic, assign) CGRect titleLabelFrame;
/** 隐藏 titleLabel,默认为 NO */
@property (nonatomic, assign) BOOL hiddenTitleLabel;
/////////////////////////////// 取消按钮(cancelBtn//////////////////////////////
/** 设置 cancelBtn 的背景颜色 */
@property (nullable, nonatomic, strong) UIColor *cancelColor;
/** 设置 cancelBtn 标题的颜色 */
@property (nullable, nonatomic, strong) UIColor *cancelTextColor;
/** 设置 cancelBtn 标题的字体 */
@property (nullable, nonatomic, strong) UIFont *cancelTextFont;
/** 设置 cancelBtn 的 frame */
@property (nonatomic, assign) CGRect cancelBtnFrame;
/** 设置 cancelBtn 的边框样式 */
@property (nonatomic, assign) BRBorderStyle cancelBorderStyle;
/** 设置 cancelBtn 的圆角大小 */
@property (nonatomic, assign) CGFloat cancelCornerRadius;
/** 设置 cancelBtn 的边框宽度 */
@property (nonatomic, assign) CGFloat cancelBorderWidth;
/** 设置 cancelBtn 的 image */
@property (nullable, nonatomic, strong) UIImage *cancelBtnImage;
/** 设置 cancelBtn 的 title */
@property (nullable, nonatomic, copy) NSString *cancelBtnTitle;
/** 隐藏 cancelBtn,默认为 NO */
@property (nonatomic, assign) BOOL hiddenCancelBtn;
/////////////////////////////// 确定按钮(doneBtn////////////////////////////////
/** 设置 doneBtn 的背景颜色 */
@property (nullable, nonatomic, strong) UIColor *doneColor;
/** 设置 doneBtn 标题的颜色 */
@property (nullable, nonatomic, strong) UIColor *doneTextColor;
/** 设置 doneBtn 标题的字体 */
@property (nullable, nonatomic, strong) UIFont *doneTextFont;
/** 设置 doneBtn 的 frame */
@property (nonatomic, assign) CGRect doneBtnFrame;
/** 设置 doneBtn 的边框样式 */
@property (nonatomic, assign) BRBorderStyle doneBorderStyle;
/** 设置 doneBtn 的圆角大小 */
@property (nonatomic, assign) CGFloat doneCornerRadius;
/** 设置 doneBtn 的边框宽度 */
@property (nonatomic, assign) CGFloat doneBorderWidth;
/** 设置 doneBtn 的 image */
@property (nullable, nonatomic, strong) UIImage *doneBtnImage;
/** 设置 doneBtn 的 title */
@property (nullable, nonatomic, copy) NSString *doneBtnTitle;
/** 隐藏 doneBtn,默认为 NO */
@property (nonatomic, assign) BOOL hiddenDoneBtn;
/////////////////////////////// 选择器(pickerView///////////////////////////////
/** 设置 picker 的背景颜色 */
@property (nullable, nonatomic, strong) UIColor *pickerColor;
/** 设置 picker 中间两条分割线的背景颜色。暂不支持日期选择器前4种类型 */
@property (nullable, nonatomic, strong) UIColor *separatorColor;
/** 设置 picker 中间两条分割线的高度。暂不支持日期选择器前4种类型 */
@property (nonatomic, assign) CGFloat separatorHeight;
/** 设置 picker 文本的颜色。暂不支持日期选择器前4种类型 */
@property (nullable, nonatomic, strong) UIColor *pickerTextColor;
/** 设置 picker 文本的字体。暂不支持日期选择器前4种类型 */
@property (nullable, nonatomic, strong) UIFont *pickerTextFont;
/** 设置 picker 中间选中行的背景颜色。暂不支持日期选择器前4种类型 */
@property (nullable, nonatomic, strong) UIColor *selectRowColor;
/** 设置 picker 中间选中行文本的颜色。暂不支持日期选择器前4种类型 */
@property (nullable, nonatomic, strong) UIColor *selectRowTextColor;
/** 设置 picker 中间选中行文本的字体。暂不支持日期选择器前4种类型 */
@property (nullable, nonatomic, strong) UIFont *selectRowTextFont;
/** 设置 picker 的高度,系统默认高度为 216 */
@property (nonatomic, assign) CGFloat pickerHeight;
/** 设置 picker 的行高。暂不支持日期选择器前4种类型 */
@property (nonatomic, assign) CGFloat rowHeight;
/**
* 清除iOS14之后选择器默认自带的新样式。暂不支持日期选择器前4种类型
* 主要是:①隐藏中间选择行的背景样式,②清除默认的内边距,③新增中间选择行的两条分割线;与iOS14之前的样式保持一致),默认为 YES
*/
@property (nonatomic, assign) BOOL clearPickerNewStyle;
/**
* 设置语言(不设置或为nil时,将随系统的语言自动改变)
* language: zh-Hans(简体中文)、zh-Hant(繁体中文)、en(英语 )
*/
@property(nullable, nonatomic, copy) NSString *language;
/////// 日期选择器单位样式(showUnitType == BRShowUnitTypeOnlyCenter 时生效。暂不支持日期选择器前4种类型 )///////
/** 设置日期选择器单位文本的颜色 */
@property (nullable, nonatomic, strong) UIColor *dateUnitTextColor;
/** 设置日期选择器单位文本的字体 */
@property (nullable, nonatomic, strong) UIFont *dateUnitTextFont;
/** 设置日期选择器单位 label 的水平方向偏移量 */
@property (nonatomic, assign) CGFloat dateUnitOffsetX;
/** 设置日期选择器单位 label 的竖直方向偏移量 */
@property (nonatomic, assign) CGFloat dateUnitOffsetY;
//////////////////////////////// 常用的几种模板样式 ////////////////////////////////
/// 弹框模板样式1 - 取消/确定按钮圆角样式
/// @param themeColor 主题颜色
+ (instancetype)pickerStyleWithThemeColor:(nullable UIColor *)themeColor;
/// 弹框模板样式2 - 顶部圆角样式 + 完成按钮
/// @param doneTextColor 完成按钮标题的颜色
+ (instancetype)pickerStyleWithDoneTextColor:(nullable UIColor *)doneTextColor;
/// 弹框模板样式3 - 顶部圆角样式 + 图标按钮
/// @param doneBtnImage 完成按钮的 image
+ (instancetype)pickerStyleWithDoneBtnImage:(nullable UIImage *)doneBtnImage;
//////////////////////////////// 以下是组件内部使用的几个封装方法 ////////////////////////////////
/** 设置选择器中间选中行的样式 */
- (void)setupPickerSelectRowStyle:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;
/** 添加选择器中间行上下两条分割线(iOS14之后系统默认去掉,需要手动添加)*/
- (void)addSeparatorLineView:(UIView *)pickerView;
/** 设置 view 的部分圆角 */
// corners(枚举类型,可组合使用)UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight | UIRectCornerAllCorners
+ (void)br_setView:(UIView *)view roundingCorners:(UIRectCorner)corners withRadius:(CGFloat)radius;
@end
NS_ASSUME_NONNULL_END
+494
View File
@@ -0,0 +1,494 @@
//
// BRPickerStyle.m
// BRPickerViewDemo
//
// Created by renbo on 2019/10/2.
// Copyright © 2019 irenb. All dones reserved.
//
// 最新代码下载地址:https://github.com/91renb/BRPickerView
#import "BRPickerStyle.h"
#import "NSBundle+BRPickerView.h"
// 标题颜色
#define kBRDefaultTextColor BR_RGB_HEX(0x333333, 1.0f)
@implementation BRPickerStyle
- (instancetype)init {
if (self = [super init]) {
self.clearPickerNewStyle = YES;
}
return self;
}
/// 设置默认样式
- (UIColor *)maskColor {
if (!_maskColor) {
_maskColor = [self br_colorWithLightColor:BR_RGB_HEX(0x000000, 0.3f) darkColor:BR_RGB_HEX(0x666666, 0.3f)];
}
return _maskColor;
}
- (UIColor *)shadowLineColor {
if (!_shadowLineColor) {
if (@available(iOS 13.0, *)) {
// 边框线颜色,有透明度
_shadowLineColor = [UIColor separatorColor];
} else {
_shadowLineColor = BR_RGB_HEX(0xc6c6c8, 1.0f);
}
}
return _shadowLineColor;
}
- (CGFloat)shadowLineHeight {
if (_shadowLineHeight <= 0 || _shadowLineHeight > 5.0f) {
_shadowLineHeight = 0.5f;
}
return _shadowLineHeight;
}
- (CGFloat)paddingBottom {
if (_paddingBottom <= 0) {
_paddingBottom = BR_BOTTOM_MARGIN;
}
return _paddingBottom;
}
- (UIColor *)titleBarColor {
if (!_titleBarColor) {
if (@available(iOS 13.0, *)) {
// #ffffff(正常)、#1c1c1e(深色)
_titleBarColor = [UIColor secondarySystemGroupedBackgroundColor];
} else {
_titleBarColor = [UIColor whiteColor];
}
}
return _titleBarColor;
}
- (CGFloat)titleBarHeight {
if (!self.hiddenTitleBarView) {
if (_titleBarHeight < 44.0f && (!self.hiddenCancelBtn || !self.hiddenDoneBtn || !self.hiddenTitleLabel)) {
_titleBarHeight = 44.0f;
}
} else {
_titleBarHeight = 0;
}
return _titleBarHeight;
}
- (UIColor *)titleLineColor {
if (!_titleLineColor) {
_titleLineColor = [self br_colorWithLightColor:BR_RGB_HEX(0xededee, 1.0f) darkColor:BR_RGB_HEX(0x18181c, 1.0f)];
}
return _titleLineColor;
}
- (UIColor *)cancelColor {
if (!_cancelColor) {
_cancelColor = [UIColor clearColor];
}
return _cancelColor;
}
- (UIColor *)cancelTextColor {
if (!_cancelTextColor) {
if (@available(iOS 13.0, *)) {
_cancelTextColor = [UIColor labelColor];
} else {
_cancelTextColor = kBRDefaultTextColor;
}
}
return _cancelTextColor;
}
- (UIFont *)cancelTextFont {
if (!_cancelTextFont) {
_cancelTextFont = [UIFont systemFontOfSize:16.0f];
}
return _cancelTextFont;
}
- (NSString *)cancelBtnTitle {
if (!_cancelBtnTitle && !_cancelBtnImage) {
_cancelBtnTitle = [NSBundle br_localizedStringForKey:@"取消" language:self.language];
}
return _cancelBtnTitle;
}
- (CGRect)cancelBtnFrame {
if (CGRectEqualToRect(_cancelBtnFrame, CGRectZero) || _cancelBtnFrame.size.height == 0) {
_cancelBtnFrame = CGRectMake(5, 8, 60, 28);
}
return _cancelBtnFrame;
}
- (UIColor *)titleLabelColor {
if (!_titleLabelColor) {
_titleLabelColor = [UIColor clearColor];
}
return _titleLabelColor;
}
- (UIColor *)titleTextColor {
if (!_titleTextColor) {
if (@available(iOS 13.0, *)) {
_titleTextColor = [UIColor secondaryLabelColor];
} else {
_titleTextColor = BR_RGB_HEX(0x999999, 1.0f);
}
}
return _titleTextColor;
}
- (UIFont *)titleTextFont {
if (!_titleTextFont) {
_titleTextFont = [UIFont systemFontOfSize:15.0f];
}
return _titleTextFont;
}
- (CGRect)titleLabelFrame {
if (CGRectEqualToRect(_titleLabelFrame, CGRectZero) || _titleLabelFrame.size.height == 0) {
_titleLabelFrame = CGRectMake(5 + 60 + 2, 0, BRGetKeyWindow().bounds.size.width - 2 * (5 + 60 + 2), 44);
}
return _titleLabelFrame;
}
- (UIColor *)doneColor {
if (!_doneColor) {
_doneColor = [UIColor clearColor];
}
return _doneColor;
}
- (UIColor *)doneTextColor {
if (!_doneTextColor) {
if (@available(iOS 13.0, *)) {
_doneTextColor = [UIColor labelColor];
} else {
_doneTextColor = kBRDefaultTextColor;
}
}
return _doneTextColor;
}
- (UIFont *)doneTextFont {
if (!_doneTextFont) {
_doneTextFont = [UIFont systemFontOfSize:16.0f];
}
return _doneTextFont;
}
- (NSString *)doneBtnTitle {
if (!_doneBtnTitle && !_doneBtnImage) {
_doneBtnTitle = [NSBundle br_localizedStringForKey:@"确定" language:self.language];
}
return _doneBtnTitle;
}
- (CGRect)doneBtnFrame {
if (CGRectEqualToRect(_doneBtnFrame, CGRectZero) || _doneBtnFrame.size.height == 0) {
_doneBtnFrame = CGRectMake(BRGetKeyWindow().bounds.size.width - 60 - 5, 8, 60, 28);
}
return _doneBtnFrame;
}
- (UIColor *)pickerColor {
if (!_pickerColor) {
if (@available(iOS 13.0, *)) {
// #ffffff(正常)、#1c1c1e(深色)
_pickerColor = [UIColor secondarySystemGroupedBackgroundColor];
} else {
_pickerColor = [UIColor whiteColor];
}
}
return _pickerColor;
}
- (UIColor *)separatorColor {
if (!_separatorColor) {
if (@available(iOS 13.0, *)) {
// 分割线颜色,无透明度
_separatorColor = [UIColor opaqueSeparatorColor];
} else {
_separatorColor = BR_RGB_HEX(0xc6c6c8, 1.0f);
}
}
return _separatorColor;
}
- (UIColor *)pickerTextColor {
if (!_pickerTextColor) {
if (@available(iOS 13.0, *)) {
_pickerTextColor = [UIColor labelColor];
} else {
_pickerTextColor = kBRDefaultTextColor;
}
}
return _pickerTextColor;
}
- (UIFont *)pickerTextFont {
if (!_pickerTextFont) {
_pickerTextFont = [UIFont systemFontOfSize:18.0f];
}
return _pickerTextFont;
}
- (CGFloat)pickerHeight {
if (_pickerHeight < 40) {
_pickerHeight = 216.0f;
}
return _pickerHeight;
}
- (CGFloat)rowHeight {
if (_rowHeight < 20) {
_rowHeight = 35.0f;
}
return _rowHeight;
}
- (NSString *)language {
if (!_language) {
// 跟随系统的首选语言自动改变
// zh-Hans-CN(简体中文)、zh-Hant-CN(繁体中文)、en-CN(美式英语)、en-GB(英式英语)
// 其中`CN`是iOS9以后新增的地区代码,如:CN 代表中国,US 代表美国
_language = [NSLocale preferredLanguages].firstObject;
}
return _language;
}
- (UIColor *)dateUnitTextColor {
if (!_dateUnitTextColor) {
if (@available(iOS 13.0, *)) {
_dateUnitTextColor = [UIColor labelColor];
} else {
_dateUnitTextColor = kBRDefaultTextColor;
}
}
return _dateUnitTextColor;
}
- (UIFont *)dateUnitTextFont {
if (!_dateUnitTextFont) {
_dateUnitTextFont = [UIFont systemFontOfSize:18.0f];
}
return _dateUnitTextFont;
}
#pragma mark - 创建自定义动态颜色(适配深色模式)
- (UIColor *)br_colorWithLightColor:(UIColor *)lightColor darkColor:(UIColor *)darkColor {
if (@available(iOS 13.0, *)) {
UIColor *dyColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull traitCollection) {
if ([traitCollection userInterfaceStyle] == UIUserInterfaceStyleLight) {
return lightColor;
} else {
return darkColor;
}
}];
return dyColor;
} else {
return lightColor;
}
}
#pragma mark - 弹框模板样式1 - 取消/确定按钮圆角样式
+ (instancetype)pickerStyleWithThemeColor:(UIColor *)themeColor {
BRPickerStyle *customStyle = [[self alloc]init];
if (themeColor) {
customStyle.cancelTextColor = themeColor;
customStyle.cancelBorderStyle = BRBorderStyleSolid;
customStyle.doneColor = themeColor;
customStyle.doneTextColor = [UIColor whiteColor];
customStyle.doneBorderStyle = BRBorderStyleFill;
}
return customStyle;
}
#pragma mark - 弹框模板样式2 - 顶部圆角样式 + 完成按钮
+ (instancetype)pickerStyleWithDoneTextColor:(UIColor *)doneTextColor {
BRPickerStyle *customStyle = [[self alloc]init];
if (doneTextColor) {
customStyle.topCornerRadius = 16.0f;
customStyle.hiddenCancelBtn = YES;
customStyle.hiddenTitleLine = YES;
customStyle.titleLabelFrame = CGRectMake(20, 4, 100, 40);
customStyle.doneTextColor = doneTextColor;
customStyle.doneTextFont = [UIFont boldSystemFontOfSize:18.0f];
customStyle.doneBtnFrame = CGRectMake(BRGetKeyWindow().bounds.size.width - 60, 4, 60, 40);
customStyle.doneBtnTitle = [NSBundle br_localizedStringForKey:@"完成" language:customStyle.language];
customStyle.selectRowTextColor = doneTextColor;
customStyle.selectRowTextFont = [UIFont boldSystemFontOfSize:20.0f];
}
return customStyle;
}
#pragma mark - 弹框模板样式3 - 顶部圆角样式 + 图标按钮
+ (instancetype)pickerStyleWithDoneBtnImage:(UIImage *)doneBtnImage {
BRPickerStyle *customStyle = [[self alloc]init];
if (doneBtnImage) {
customStyle.topCornerRadius = 16.0f;
customStyle.hiddenTitleLine = YES;
customStyle.hiddenCancelBtn = YES;
customStyle.titleLabelFrame = CGRectMake(20, 4, 100, 40);
customStyle.doneBtnImage = doneBtnImage;
customStyle.doneBtnFrame = CGRectMake(BRGetKeyWindow().bounds.size.width - 44, 4, 40, 40);
}
return customStyle;
}
#pragma mark - 设置选择器中间选中行的样式
- (void)setupPickerSelectRowStyle:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
// 1.设置分割线的颜色
NSString *systemVersion = [UIDevice currentDevice].systemVersion;
if (systemVersion.doubleValue < 14.0) {
for (UIView *subView in pickerView.subviews) {
if (subView && [subView isKindOfClass:[UIView class]] && subView.frame.size.height <= 1) {
subView.backgroundColor = self.separatorColor;
// 设置分割线高度
if (self.separatorHeight > 0) {
CGRect rect = subView.frame;
rect.size.height = self.separatorHeight;
subView.frame = rect;
}
}
}
}
// 2.设置选择器中间选中行的背景颜色
UIView *contentView = nil;
NSArray *subviews = pickerView.subviews;
if (subviews.count > 0) {
id firstView = subviews.firstObject;
if (firstView && [firstView isKindOfClass:[UIView class]]) {
contentView = (UIView *)firstView;
}
}
if (self.selectRowColor) {
UIView *columnView = nil;
if (contentView) {
id obj = [contentView valueForKey:@"subviewCache"];
if (obj && [obj isKindOfClass:[NSArray class]]) {
NSArray *columnViews = (NSArray *)obj;
if (columnViews.count > 0) {
id columnObj = columnViews.firstObject;
if (columnObj && [columnObj isKindOfClass:[UIView class]]) {
columnView = (UIView *)columnObj;
}
}
}
}
if (columnView) {
id obj = [columnView valueForKey:@"middleContainerView"];
if (obj && [obj isKindOfClass:[UIView class]]) {
UIView *selectRowView = (UIView *)obj;
// 中间选中行的背景颜色
selectRowView.backgroundColor = self.selectRowColor;
}
}
}
if (contentView && self.clearPickerNewStyle) {
if (systemVersion.doubleValue >= 14.0) {
// ①隐藏中间选择行的背景样式
id lastView = subviews.lastObject;
if (lastView && [lastView isKindOfClass:[UIView class]]) {
UIView *rectBgView = (UIView *)lastView;
rectBgView.hidden = YES;
}
// ②清除iOS14上选择器默认的内边距
if (systemVersion.doubleValue < 15.0f) {
[self setPickerAllSubViewsStyle:contentView];
}
}
}
// 3.设置选择器中间选中行的字体颜色/字体大小
if (self.selectRowTextColor || self.selectRowTextFont) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 当前选中的 label
UILabel *selectLabel = (UILabel *)[pickerView viewForRow:row forComponent:component];
if (selectLabel) {
if (self.selectRowTextColor) {
selectLabel.textColor = self.selectRowTextColor;
}
if (self.selectRowTextFont) {
selectLabel.font = self.selectRowTextFont;
}
}
});
}
}
// 遍历子视图,重新设置 frame(清空在 iOS14 上 UIPickerView 出现的内边距)
- (void)setPickerAllSubViewsStyle:(UIView *)view {
NSArray *subViews = view.subviews;
if (subViews.count == 0 || [view isKindOfClass:[UILabel class]]) return;
for (UIView *subView in subViews) {
NSString *className = NSStringFromClass([subView class]);
if ([className isEqualToString:@"UIPickerColumnView"]) {
CGRect rect = subView.frame;
rect.origin.x = 0;
rect.size.width = view.bounds.size.width;
subView.frame = rect;
}
NSString *superClassName = NSStringFromClass([view class]);
if ([superClassName isEqualToString:@"UIPickerColumnView"]) {
CGRect rect = subView.frame;
rect.size.width = view.bounds.size.width;
subView.frame = rect;
}
if ([subView isKindOfClass:[UILabel class]]) {
CGRect rect = subView.frame;
rect.origin.x = 10;
subView.frame = rect;
}
[self setPickerAllSubViewsStyle:subView];
}
}
#pragma mark - 添加选择器中间行上下两条分割线(iOS14之后系统默认去掉,需要手动添加)
- (void)addSeparatorLineView:(UIView *)pickerView {
if ([UIDevice currentDevice].systemVersion.doubleValue >= 14.0) {
UIView *topLineView = [[UIView alloc]initWithFrame:CGRectMake(0, pickerView.bounds.size.height / 2 - self.rowHeight / 2, pickerView.bounds.size.width, 0.5f)];
topLineView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
topLineView.backgroundColor = self.separatorColor;
// 设置分割线高度
if (self.separatorHeight > 0) {
CGRect topRect = topLineView.frame;
topRect.size.height = self.separatorHeight;
topLineView.frame = topRect;
}
[pickerView addSubview:topLineView];
UIView *bottomLineView = [[UIView alloc]initWithFrame:CGRectMake(0, pickerView.bounds.size.height / 2 + self.rowHeight / 2, pickerView.bounds.size.width, 0.5f)];
bottomLineView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
bottomLineView.backgroundColor = self.separatorColor;
// 设置分割线高度
if (self.separatorHeight > 0) {
CGRect bottomRect = bottomLineView.frame;
bottomRect.size.height = self.separatorHeight;
bottomLineView.frame = bottomRect;
}
[pickerView addSubview:bottomLineView];
}
}
#pragma mark - 设置 view 的部分圆角
// corners(枚举类型,可组合使用)UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight | UIRectCornerAllCorners
+ (void)br_setView:(UIView *)view roundingCorners:(UIRectCorner)corners withRadius:(CGFloat)radius {
UIBezierPath *rounded = [UIBezierPath bezierPathWithRoundedRect:view.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(radius, radius)];
CAShapeLayer *shape = [[CAShapeLayer alloc]init];
[shape setPath:rounded.CGPath];
view.layer.mask = shape;
}
@end
@@ -0,0 +1,35 @@
/*
Localizable.strings
BRPickerViewDemo
Created by renbo on 2019/10/30.
Copyright © 2019 irenb. All rights reserved.
*/
"确定" = "OK";
"取消" = "Cancel";
"完成" = "Done";
"年" = " ";
"月" = " ";
"日" = " ";
"时" = " ";
"分" = " ";
"秒" = " ";
"周" = " ";
"季度" = " ";
"上午" = "AM";
"下午" = "PM";
"至今" = " Now";
"今天" = " Today";
"周一" = " Mon";
"周二" = " Tue";
"周三" = " Wed";
"周四" = " Thu";
"周五" = " Fri";
"周六" = " Sat";
"周日" = " Sun";
@@ -0,0 +1,35 @@
/*
Localizable.strings
BRPickerViewDemo
Created by renbo on 2019/10/30.
Copyright © 2019 irenb. All rights reserved.
*/
"确定" = "确定";
"取消" = "取消";
"完成" = "完成";
"年" = "年";
"月" = "月";
"日" = "日";
"时" = "时";
"分" = "分";
"秒" = "秒";
"周" = "周";
"季度" = "季度";
"上午" = "上午";
"下午" = "下午";
"至今" = "至今";
"今天" = "今天";
"周一" = "周一";
"周二" = "周二";
"周三" = "周三";
"周四" = "周四";
"周五" = "周五";
"周六" = "周六";
"周日" = "周日";
@@ -0,0 +1,35 @@
/*
Localizable.strings
BRPickerViewDemo
Created by renbo on 2019/10/30.
Copyright © 2019 irenb. All rights reserved.
*/
"确定" = "確定";
"取消" = "取消";
"完成" = "完成";
"年" = "年";
"月" = "月";
"日" = "日";
"时" = "時";
"分" = "分";
"秒" = "秒";
"周" = "周";
"季度" = "季度";
"上午" = "上午";
"下午" = "下午";
"至今" = "至今";
"今天" = "今天";
"周一" = "周壹";
"周二" = "周二";
"周三" = "周三";
"周四" = "周四";
"周五" = "周五";
"周六" = "周六";
"周日" = "周日";
+87
View File
@@ -0,0 +1,87 @@
//
// BRPickerViewMacro.h
// BRPickerViewDemo
//
// Created by renbo on 2018/4/23.
// Copyright © 2018 irenb. All rights reserved.
//
// 最新代码下载地址:https://github.com/91renb/BRPickerView
#ifndef BRPickerViewMacro_h
#define BRPickerViewMacro_h
#import <UIKit/UIKit.h>
// 屏幕安全区域下边距
#define BR_BOTTOM_MARGIN \
({CGFloat safeBottomHeight = 0;\
if (@available(iOS 11.0, *)) {\
safeBottomHeight = BRGetKeyWindow().safeAreaInsets.bottom;\
}\
(safeBottomHeight);})
// 静态库中编写 Category 时的便利宏,用于解决 Category 方法从静态库中加载需要特别设置的问题
#ifndef BRSYNTH_DUMMY_CLASS
#define BRSYNTH_DUMMY_CLASS(_name_) \
@interface BRSYNTH_DUMMY_CLASS_ ## _name_ : NSObject @end \
@implementation BRSYNTH_DUMMY_CLASS_ ## _name_ @end
#endif
// 打印错误日志
#ifdef DEBUG
#define BRErrorLog(...) NSLog(@"reason: %@", [NSString stringWithFormat:__VA_ARGS__])
#else
#define BRErrorLog(...)
#endif
/** RGB颜色(16进制) */
static inline UIColor *BR_RGB_HEX(uint32_t rgbValue, CGFloat alpha) {
return [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255.0
green:((CGFloat)((rgbValue & 0xFF00) >> 8)) / 255.0
blue:((CGFloat)(rgbValue & 0xFF)) / 255.0
alpha:(alpha)];
}
/** 获取 keyWindow */
static inline UIWindow *BRGetKeyWindow(void) {
UIWindow *keyWindow = nil;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 // 编译时检查SDK版本(兼容不同版本的Xcode,防止编译报错)
if (@available(iOS 13.0, *)) { // 运行时检查系统版本(兼容不同版本的系统,防止运行报错)
NSSet<UIScene *> *connectedScenes = [UIApplication sharedApplication].connectedScenes;
for (UIScene *scene in connectedScenes) {
if (scene.activationState == UISceneActivationStateForegroundActive && [scene isKindOfClass:[UIWindowScene class]]) {
UIWindowScene *windowScene = (UIWindowScene *)scene;
for (UIWindow *window in windowScene.windows) {
if (window.isKeyWindow) {
keyWindow = window;
break;
}
}
}
}
}
#endif
if (!keyWindow) {
keyWindow = [UIApplication sharedApplication].windows.firstObject;
if (!keyWindow.isKeyWindow) {
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
UIWindow *window = [UIApplication sharedApplication].keyWindow;
if (CGRectEqualToRect(window.bounds, UIScreen.mainScreen.bounds)) {
keyWindow = window;
}
#endif
}
}
return keyWindow;
}
#endif /* BRPickerViewMacro_h */
@@ -0,0 +1,26 @@
//
// NSBundle+BRPickerView.h
// BRPickerViewDemo
//
// Created by renbo on 2019/10/30.
// Copyright © 2019 irenb. All rights reserved.
//
// 最新代码下载地址:https://github.com/91renb/BRPickerView
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSBundle (BRPickerView)
/// 获取 BRPickerView.bundle
+ (instancetype)br_pickerBundle;
/// 获取国际化后的文本
/// @param key 代表 Localizable.strings 文件中 key-value 中的 key。
/// @param language 设置语言(可为空,为nil时将随系统的语言自动改变)
+ (NSString *)br_localizedStringForKey:(NSString *)key language:(NSString *)language;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,68 @@
//
// NSBundle+BRPickerView.m
// BRPickerViewDemo
//
// Created by renbo on 2019/10/30.
// Copyright © 2019 irenb. All rights reserved.
//
// 最新代码下载地址:https://github.com/91renb/BRPickerView
#import "NSBundle+BRPickerView.h"
#import "BRBaseView.h"
BRSYNTH_DUMMY_CLASS(NSBundle_BRPickerView)
@implementation NSBundle (BRPickerView)
#pragma mark - 获取 BRPickerView.bundle
+ (instancetype)br_pickerBundle {
static NSBundle *pickerBundle = nil;
if (!pickerBundle) {
/*
先拿到最外面的 bundle。
对 framework 链接方式来说就是 framework 的 bundle 根目录,
对静态库链接方式来说就是 target client 的 main bundle
然后再去找下面名为 BRPickerView 的 bundle 对象。
*/
NSBundle *bundle = [NSBundle bundleForClass:[BRBaseView class]];
NSURL *url = [bundle URLForResource:@"BRPickerView" withExtension:@"bundle"];
pickerBundle = [NSBundle bundleWithURL:url];
}
return pickerBundle;
}
#pragma mark - 获取国际化后的文本
+ (NSString *)br_localizedStringForKey:(NSString *)key language:(NSString *)language {
return [self br_localizedStringForKey:key value:nil language:language];
}
+ (NSString *)br_localizedStringForKey:(NSString *)key value:(NSString *)value language:(NSString *)language {
static NSBundle *bundle = nil;
if (!bundle) {
// 如果没有手动设置语言,将随系统的语言自动改变
if (!language) {
// 系统首选语言
language = [NSLocale preferredLanguages].firstObject;
}
if ([language hasPrefix:@"en"]) {
language = @"en";
} else if ([language hasPrefix:@"zh"]) {
if ([language rangeOfString:@"Hans"].location != NSNotFound) {
language = @"zh-Hans"; // 简体中文
} else { // zh-Hant、zh-HK、zh-TW
language = @"zh-Hant"; // 繁體中文
}
} else {
language = @"en";
}
// 从 BRPickerView.bundle 中查找资源
bundle = [NSBundle bundleWithPath:[[self br_pickerBundle] pathForResource:language ofType:@"lproj"]];
}
value = [bundle localizedStringForKey:key value:value table:nil];
return [[NSBundle mainBundle] localizedStringForKey:key value:value table:nil];
}
@end