前言
需求:商户交易汇总表使用tab滑块进行切换/筛选不同级别的代理商数据
应用场景:商户交易汇总表使用tab滑块进行切换/筛选不同级别的代理商数据
视频地址:https://live.csdn.net/v/156406
下载Demo:https://download.csdn.net/download/u011018979/19790950
I、自定义tab滑块的用法
下载Demo:https://download.csdn.net/download/u011018979/19790950视频地址:https://live.csdn.net/v/156406
需求:商户交易汇总表使用tab滑块进行切换/筛选不同级别的代理商数据
应用场景:商户交易汇总表使用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
#import "CRMMultipleSwitch.h" @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; } #pragma mark - KVO - (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]; } } #pragma mark - UIControl Override - (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; } #pragma mark - setter - (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"]; } #pragma mark - 添加子控件 - (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