以上就是实现的效果,支持左右滚动进行切换。
我们在实现上用到了Masonry 和UIView+LGJExtension,其中UIView+LGJExtension中包含了
@property (nonatomic, assign) CGPoint origin;
@property (nonatomic, assign) CGSize size;
@property (nonatomic, assign) CGFloat top;
@property (nonatomic, assign) CGFloat left;
@property (nonatomic, assign) CGFloat bottom;
@property (nonatomic, assign) CGFloat right;
@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;
@property (nonatomic, assign) CGFloat x;
@property (nonatomic, assign) CGFloat y;
@property (nonatomic, assign) CGFloat centerX;
@property (nonatomic, assign) CGFloat centerY;
以及其具体实现。
首先我们自定义LGJSegmentView 继承UIView
#import <UIKit/UIKit.h>
@interface LGJSegmentView : UIView
@property(nonatomic,copy)void (^segmentClickBlock)(NSInteger index);
/**
根据标题个数进行初始化
@param titles 标题数组
@return 创建好的视图返回
*/
-(instancetype)initWithSegmentedTitles:(NSArray *)titles;
/**
滚动到第几个标题处
@param index 下表 0 1 2.。
*/
-(void)sliderToCurrentSelectedIndex:(NSInteger )index;
@end
在.m中声明以下属性
@property(nonatomic,strong)NSArray *titleArr;
@property(nonatomic,strong)NSMutableArray *buttonArr;
@property(nonatomic,strong)UIView *segmentedContainer;
@property(nonatomic,strong)UIView *sliderLine;
@property(nonatomic,strong)UIView *bottomLine;
同时,我们把控件距离左右边的边距,高,宽等也出去出来,方便改写。
#define ScreenWidth [UIScreen mainScreen].bounds.size.width
#define Margin 15
#define Height 40
#define LineWidth (ScreenWidth - Margin * 2)/(self.titleArr.count)
LGJSegmentedView.m
@implementation LGJSegmentView
-(instancetype)initWithSegmentedTitles:(NSArray *)titles{
if (self = [super init]) {
self.titleArr = titles;
self.backgroundColor = [UIColor whiteColor];
[self createSegmentView];
[self setUpViews];
}
return self;
}
-(void)createSegmentView{
self.buttonArr = [NSMutableArray array];
for (int index = 0; index < self.titleArr.count; index++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
[button setTitle:self.titleArr[index] forState:UIControlStateNormal];
[button setTitle:self.titleArr[index] forState:UIControlStateSelected];
[button setTitleColor:RGB_HEX(0x666666) forState:UIControlStateNormal];
[button setTitleColor:RGB_HEX(0xff4400) forState:UIControlStateSelected];
button.titleLabel.font = [UIFont systemFontOfSize:15.0f];
button.titleLabel.adjustsFontSizeToFitWidth = YES;
if (index == 0) {
button.selected = YES;
}else{
button.selected
= NO;
}
button.tag = index;
[button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.buttonArr addObject:button];
}
}
-(void)setUpViews{
[self addSubview:self.segmentedContainer];
for (UIButton *button in self.buttonArr) {
[self.segmentedContainer addSubview:button];
}
[self addSubview:self.sliderLine];
[self addSubview:self.bottomLine];
}
-(void)layoutSubviews{
[super layoutSubviews];
self.segmentedContainer.top = 0;
self.segmentedContainer.left = Margin;
self.segmentedContainer.width = self.width - Margin*2;
self.segmentedContainer.height = self.height;
self.bottomLine.frame = CGRectMake(0, self.height-APPCONFIG_UNIT_LINE_WIDTH, self.width, APPCONFIG_UNIT_LINE_WIDTH);
//每个子segment的宽度
CGFloat segmentWith = (self.width-15*2) / self.buttonArr.count;
for (int i=0; i<self.buttonArr.count; i++) {
UIButton *button = (UIButton *)self.buttonArr[i];
button.top = 0;
button.left = i * segmentWith;
button.width = segmentWith;
button.height = Height;
}
//设置底部红色滑动线条的位置
self.sliderLine.bottom = self.bottomLine.top;
self.sliderLine.left = self.segmentedContainer.left;
self.sliderLine.width = segmentWith;
self.sliderLine.height = 2.0f;
}
-(void)buttonClicked:(UIButton *)sender{
[self selectedSegmentButton:sender];
if (self.segmentClickBlock) {
self.segmentClickBlock(sender.tag);
}
}
-(void)selectedSegmentButton:(UIButton *)selectedButton{
selectedButton.selected = YES;
[self changeSelectedWithSelectedButton:selectedButton];
}
-(void)changeSelectedWithSelectedButton:(UIButton *)selectedButton{
for (UIButton *button in _buttonArr) {
if (![button isEqual:selectedButton]) {
button.selected = NO;
}
}
[self setSliderLinePosition];
}
-(void)setSliderLinePosition{
UIButton *button = [self selectedButton];
[UIView animateWithDuration:0.3f animations:^{
self.sliderLine.left = Margin + button.tag * LineWidth;
}];
}
-(UIButton *)selectedButton{
NSInteger selIndex = [self selectedIndex];
if (selIndex == -1 || self.buttonArr.count <= selIndex) {
return nil;
}
return self.buttonArr[selIndex];
}
- (NSInteger)selectedIndex
{
for(int i = 0; i < self.buttonArr.count; i++) {
UIButton *button = (UIButton *)self.buttonArr[i];
if (button.selected) {
return i;
}
}
return -1;
}
-(void)sliderToCurrentSelectedIndex:(NSInteger)index{
UIButton *button = self.buttonArr[index];
[self selectedSegmentButton:button];
}
#pragma mark - 懒加载
- (UIView *)segmentedContainer
{
if (!_segmentedContainer) {
_segmentedContainer = [[UIView alloc] init];
_segmentedContainer.backgroundColor = [UIColor whiteColor];
}
return _segmentedContainer;
}
-(UIView *)sliderLine
{
if (!_sliderLine) {
_sliderLine = [[UIView alloc] init];
_sliderLine.backgroundColor = RGB_HEX(0xff4400);
}
return _sliderLine;
}
-(UIView *)bottomLine
{
if (!_bottomLine) {
_bottomLine = [[UIView alloc] init];
_bottomLine.backgroundColor = RGB_HEX(0xeeeeee);
}
return _bottomLine;
}
@end
在使用的时候也是很方便。多数时候我们会结合多个控制器来实现。这个时候往往的做法就是添加子控制器。
#pragma mark - 懒加载
[self.view addSubview:self.segment];
[self.view addSubview:self.scrollView];
[self.segment mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_equalTo(self.view);
make.top.mas_equalTo(LGJNavigationBarAdapterContentInsetTop);
make.size.mas_equalTo(CGSizeMake(APPCONFIG_UI_SCREEN_FWIDTH, 40));
}];
[self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.bottom.mas_equalTo(self.view);
make.top.mas_equalTo(self.segment.mas_bottom);
}];
self.scrollView.contentSize = CGSizeMake(self.childViewControllers.count*APPCONFIG_UI_SCREEN_FWIDTH, 0);
- (LGJSegmentView *)segment
{
if (!_segment) {
NSArray *titles = @[@"广州",@"北京",@"上海",@"深圳"];
_segment = [[LGJSegmentView alloc] initWithSegmentedTitles:titles];
__weak typeof(self)weakSelf = self;
_segment.segmentClickBlock = ^(NSInteger index) {
// 让底部的内容scrollView滚动到对应位置
CGPoint offset = weakSelf.scrollView.contentOffset;
offset.x = index * weakSelf.scrollView.frame.size.width;
[weakSelf.scrollView setContentOffset:offset animated:YES];
};
}
return _segment;
}
//添加子控制器
NSArray *titles = @[@"广州",@"北京",@"上海",@"深圳"];
for (int i=0; i<titles.count; i++) {
LGJViewController *childCtrl = [[LGJViewController alloc] initWithChildViewType:i];
[self addChildViewController:childCtrl];
}
我们在点击标题进行切换,或者是滚动标题以下视图进行切换,需要绑定。
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self scrollViewDidEndScrollingAnimation:scrollView];
}
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
CGFloat width = scrollView.frame.size.width;
CGFloat height = scrollView.frame.size.height;
CGFloat offsetX = scrollView.contentOffset.x;
// 当前位置需要显示的控制器的索引
NSInteger index = offsetX / width;
//设置optionalNewsSegment滚动到控制器对应的位置
[self.segment sliderToCurrentSelectedIndex:index];
//容错处理
if (index<0) return;
// 取出需要显示的控制器
LGJViewController *willShowVC = self.childViewControllers[index];
// 如果当前位置已经显示过了,就直接返回
if ([willShowVC isViewLoaded]) return;
// 添加控制器的view到scrollView中;
willShowVC.view.frame = CGRectMake(offsetX, 0, width, height);
[scrollView addSubview:willShowVC.view];
}