前言
需求:商户交易汇总表使用tab滑块进行切换/筛选不同级别的代理商数据
I、自定义tab滑块的用法
1.1 demo
需求:商户交易汇总表使用tab滑块进行切换/筛选不同级别的代理商数据
接口设计:如果数据比较大,就把统计和列表数据分开请求,这样可先展示列表数据,再展示统计数据
1.2 用法
- 初始化控件
/**
本级代理商数据
下级代理商数据
*/
- (CRMMultipleSwitch *)MultipleSwitch{
if (nil == _MultipleSwitch) {
CRMMultipleSwitch *switch1 = [[CRMMultipleSwitch alloc]init];
_MultipleSwitch = switch1;
[self addSubview:_MultipleSwitch];
__weak __typeof__(self) weakSelf = self;
[[switch1 rac_signalForControlEvents:UIControlEventTouchUpInside] subscribeNext:^(__kindof CRMMultipleSwitch * multipleSwitch) {
NSLog(@"点击了第%zd个",multipleSwitch.selectedSegmentIndex);
}];
[switch1 mas_makeConstraints:^(MASConstraintMaker *make) {
// switch1.frame = CGRectMake(0, 0, 180, 30);
make.height.mas_equalTo(kAdjustRatio(33));
make.top.offset(kAdjustRatio(18));
make.bottom.offset(kAdjustRatio(-18));
make.left.offset(kAdjustRatio(74));
make.right.offset(kAdjustRatio(-74));
}];
}
//>推荐MultipleSwitch初始化的时候进行数据模型的赋值
return _MultipleSwitch;
}
- 设置模型数据
推荐MultipleSwitch初始化的时候进行数据模型的赋值
- (void)setModels:(CRMMultipleSwitchCellTableViewCellModel *)models{
_models = models;
if(models.items.count>0){
self.MultipleSwitch.items= models.items;
[self setupswitchStyle];
}
}
- (CRMMerchantTransactionByPageMiddleViewModel *)viewModel{
if (_viewModel == nil) {
_viewModel = [CRMMerchantTransactionByPageMiddleViewModel new];
self.viewModel.multipleSwitchCellTableViewCellModel = [CRMMultipleSwitchCellTableViewCellModel new];
// @[@" 1",@"2 "];
self.viewModel.multipleSwitchCellTableViewCellModel.items = @[@"本级代理商数据",@"下级代理商数据"];
}
return _viewModel;
}
- 设置更新滑块样式
- (void)layoutSubviews {
[super layoutSubviews];
[self setupswitchStyle];
}
- (void)setupswitchStyle{
[[self MultipleSwitch] layoutIfNeeded];
CRMMultipleSwitch *switch1 = self.MultipleSwitch;
// switch1.layer.borderWidth = 1 / [UIScreen mainScreen].scale;
// switch1.layer.borderColor = [UIColor whiteColor].CGColor;
switch1.layer.backgroundColor = [[UIColor colorWithRed:255.0f/255.0f green:122.0f/255.0f blue:144.0f/255.0f alpha:1.0f] CGColor];
switch1.selectedTitleColor = [UIColor redColor];
// @property (nonatomic, copy) UIColor *trackerColor; // 滑块的颜色
// @property (nonatomic, copy) UIImage *trackerImage; // 滑块的图片
switch1.titleColor = [UIColor whiteColor];
switch1.titleFont = kPingFangFont(14);
switch1.trackerColor = [UIColor whiteColor];
}
II、代码实现
头文件
CRMMultipleSwitch.h
NS_ASSUME_NONNULL_BEGIN
/**
类似segment功能,label混合显示
*/
@interface CRMMultipleSwitch : UIControl
- (instancetype)initWithItems:(NSArray *)items;
@property(nonatomic) NSInteger selectedSegmentIndex;
@property (nonatomic, strong) UIColor *titleColor;
@property (nonatomic, strong) UIColor *selectedTitleColor;
@property (nonatomic, strong) UIFont *titleFont;
@property (nonatomic, assign) CGFloat spacing; // label之间的间距
@property (nonatomic, assign) CGFloat contentInset; // 内容内宿边距
@property (nonatomic, copy) UIColor *trackerColor; // 滑块的颜色
@property (nonatomic, copy) UIImage *trackerImage; // 滑块的图片
@property (nonatomic, strong) NSArray *items;
// *)
@end
视图内部的实现
CRMMultipleSwitch.m
@interface SPMultipleSwitchLayer : CALayer
@end
@implementation SPMultipleSwitchLayer
- (instancetype)init {
if (self = [super init]) {
self.masksToBounds = YES;
}
return self;
}
- (void)setFrame:(CGRect)frame {
[super setFrame:frame];
self.cornerRadius = frame.size.height/2.0;
}
- (void)setCornerRadius:(CGFloat)cornerRadius {
[super setCornerRadius:self.bounds.size.height/2.0];
}
+ (Class)layerClass{
return [SPMultipleSwitchLayer class];
}
- (void)layoutSublayers {
[super layoutSublayers];
[self layoutIfNeeded];
self.cornerRadius = self.frame.size.height/2.0;
}
@end
@interface CRMMultipleSwitch()
@property (nonatomic, strong) UIView *labelContentView;
@property (nonatomic, strong) UIView *selectedLabelContentView;
@property (nonatomic, strong) UIImageView *tracker;
@property (nonatomic, strong) NSMutableArray *labels;
@property (nonatomic, strong) NSMutableArray *selectedLabels;
@property (nonatomic, strong) UIView *maskTracker;
@property (nonatomic, assign) CGPoint beginPoint;
@end
@implementation CRMMultipleSwitch
+ (Class)layerClass{
return [SPMultipleSwitchLayer class];
}
- (instancetype)initWithItems:(NSArray *)items {
if (self = [self init]) {
// 创建子控件
// [self setupSubviewsWithItems:items];
self.items = items;
// [self.tracker addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
}
return self;
}
//- (NSArray *)setit
- (void)setItems:(NSArray *)items{
_items = items;
[self setupSubviewsWithItems:items];
}
//- (void)setupSubviewsWithItems{
// 创建子控件
//}
- (instancetype)init {
if (self = [super init]) {
_titleFont = [UIFont systemFontOfSize:17];
_titleColor = [UIColor redColor];
_selectedTitleColor = [UIColor whiteColor];
}
return self;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if (object == self.tracker) {
if ([keyPath isEqualToString:@"frame"]) {
self.maskTracker.frame = self.tracker.frame;
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
[super beginTrackingWithTouch:touch withEvent:event];
_beginPoint = [touch locationInView:self];
NSInteger index = [self indexForPoint:_beginPoint];
self.selectedSegmentIndex = index;
return YES;
}
- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
[super continueTrackingWithTouch:touch withEvent:event];
CGRect contentRect = CGRectInset(self.bounds, self.contentInset, self.contentInset);
CGPoint currentPoint = [touch locationInView:self];
CGFloat diff = currentPoint.x - _beginPoint.x;
CGRect trackerFrame = self.tracker.frame;
trackerFrame.origin.x += diff;
trackerFrame.origin.x = MAX(MIN(CGRectGetMinX(trackerFrame),contentRect.size.width - trackerFrame.size.width), 0);
self.tracker.frame = trackerFrame;
_beginPoint = currentPoint;
[self sendActionsForControlEvents:UIControlEventValueChanged];
return YES;
}
- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
[super endTrackingWithTouch:touch withEvent:event];
NSInteger index = [self indexForPoint:self.tracker.center];
self.selectedSegmentIndex = index;
}
- (void)cancelTrackingWithEvent:(UIEvent *)event {
[super cancelTrackingWithEvent:event];
NSInteger index = [self indexForPoint:self.tracker.center];
self.selectedSegmentIndex = index;
}
// 根据一个点,取出离该点最近的label对应的index
- (NSInteger)indexForPoint:(CGPoint)point {
CGRect contentRect = CGRectInset(self.bounds, self.contentInset, self.contentInset);
NSInteger index = MAX(0, MIN(_labels.count - 1, point.x / (contentRect.size.width / (CGFloat)(_labels.count))));
return index;
}
- (void)setSelectedSegmentIndex:(NSInteger)selectedSegmentIndex {
_selectedSegmentIndex = MAX(0, MIN(selectedSegmentIndex, _labels.count-1));
UILabel *label = _labels[_selectedSegmentIndex];
CGPoint trackerCenter = self.tracker.center;
trackerCenter.x = label.center.x;
self.tracker.center = trackerCenter;
// 这行代码主要是为了走一遍KVO监听的方法
self.tracker.frame = self.tracker.frame;
}
- (void)setContentInset:(CGFloat)contentInset {
_contentInset = contentInset;
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (void)setSpacing:(CGFloat)spacing {
_spacing = spacing;
[self setNeedsLayout];
[self layoutIfNeeded];
}
- (void)setTrackerColor:(UIColor *)trackerColor {
_trackerColor = trackerColor;
self.tracker.backgroundColor = _trackerColor;
}
- (void)setTrackerImage:(UIImage *)trackerImage {
_trackerImage = trackerImage;
self.tracker.image = _trackerImage;
}
- (void)setTitleColor:(UIColor *)titleColor {
_titleColor = titleColor;
[_labels setValue:_titleColor forKeyPath:@"textColor"];
}
- (void)setSelectedTitleColor:(UIColor *)selectedTitleColor {
_selectedTitleColor = selectedTitleColor;
[_selectedLabels setValue:_selectedTitleColor forKeyPath:@"textColor"];
}
- (void)setTitleFont:(UIFont *)titleFont {
_titleFont = titleFont;
[_labels setValue:_titleFont forKeyPath:@"font"];
[_selectedLabels setValue:_titleFont forKeyPath:@"font"];
}
- (void)setupSubviewsWithItems:(NSArray *)items {
if(self.labelContentView){
[self.labelContentView removeFromSuperview];
}
//
if(self.labels.count>0){
[self.labels makeObjectsPerformSelector:@selector(removeFromSuperview)];
}
if(self.selectedLabels.count>0){
[self.selectedLabels makeObjectsPerformSelector:@selector(removeFromSuperview)];
}
if(self.tracker){
[self.tracker removeFromSuperview];
}
//
if(self.maskTracker){
[self.maskTracker removeFromSuperview];
}
if(self.selectedLabelContentView){
[self.selectedLabelContentView removeFromSuperview];
}
self.labels = [NSMutableArray array];
self.selectedLabels = [NSMutableArray array];
// 第一层
{
UIView *labelContentView = [[UIView alloc] init];
labelContentView.userInteractionEnabled = NO;
labelContentView.layer.masksToBounds = YES;
[self addSubview:labelContentView];
_labelContentView = labelContentView;
for (int i = 0; i < items.count; i++) {
UILabel *label = [[UILabel alloc] init];
label.textAlignment = NSTextAlignmentCenter;
label.text = items[i];
label.textColor = [UIColor blackColor];
[labelContentView addSubview:label];
[self.labels addObject:label];
}
UIImageView *tracker = [[UIImageView alloc] init];
tracker.userInteractionEnabled = NO;
tracker.layer.masksToBounds = YES;
tracker.backgroundColor = [UIColor redColor];
[labelContentView addSubview:tracker];
_tracker = tracker;
[self.tracker addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
}
// 第二层
{
UIView *selectedLabelContentView = [[UIView alloc] init];
selectedLabelContentView.userInteractionEnabled = NO;
selectedLabelContentView.layer.masksToBounds = YES;
[self addSubview:selectedLabelContentView];
_selectedLabelContentView = selectedLabelContentView;
for (int i = 0; i < items.count; i++) {
UILabel *label = [[UILabel alloc] init];
label.textAlignment = NSTextAlignmentCenter;
label.text = items[i];
label.textColor = [UIColor whiteColor];
[selectedLabelContentView addSubview:label];
[self.selectedLabels addObject:label];
}
UIView *maskTracker = [[UIView alloc] init];
maskTracker.userInteractionEnabled = NO;
maskTracker.backgroundColor = [UIColor redColor];
_maskTracker = maskTracker;
// 设置selectedLabelContentView的maskView,stackView是UIView的非渲染型子类,它无法设置backgroundColor,maskView等属性
_selectedLabelContentView.maskView = maskTracker;
}
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect contentRect = CGRectInset(self.bounds, self.contentInset, self.contentInset);
self.labelContentView.frame = contentRect;
self.selectedLabelContentView.frame = contentRect;
self.labelContentView.layer.cornerRadius = contentRect.size.height / 2.0;
self.selectedLabelContentView.layer.cornerRadius = contentRect.size.height / 2.0;
CGFloat labelW = (contentRect.size.width - _spacing * self.labels.count) / self.labels.count;
[self.labels enumerateObjectsUsingBlock:^(UILabel *label, NSUInteger idx, BOOL * _Nonnull stop) {
label.frame = CGRectMake(self->_spacing * 0.5 + idx * (labelW + self->_spacing) , 0, labelW, contentRect.size.height);
}];
[self.selectedLabels enumerateObjectsUsingBlock:^(UILabel *label, NSUInteger idx, BOOL * _Nonnull stop) {
label.frame = CGRectMake(self->_spacing * 0.5 + idx * (labelW + self->_spacing), 0, labelW, contentRect.size.height);
}];
CGFloat averageWidth = contentRect.size.width / self.labels.count;
self.tracker.frame = CGRectMake(_selectedSegmentIndex * averageWidth, 0, averageWidth, contentRect.size.height);
self.tracker.layer.cornerRadius = contentRect.size.height / 2.0;
self.maskTracker.layer.cornerRadius = contentRect.size.height / 2.0;
}
- (void)dealloc {
[self.tracker removeObserver:self forKeyPath:@"frame"];
}
@end
see also
更多内容请关注 #小程序:iOS逆向
,只为你呈现有价值的信息,专注于移动端技术研究领域。
作者:公众号iOS逆向
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。