iOS 简单一步步实现一个分段选择器

2017-07-29  本文已影响534人  翻滚的炒勺2013
0824ab18972bd4078f84c1027b899e510eb30989.jpg
参考链接

0.首先创建一个SegmentView 集成于Uivew

1.在.h中声明一个传入标题数组的方法,我们用这个方法创建label


/**
 传入标题数组

 @params titlesArray 存放标题的数组
 */
- (void)creatWithTitlesArray: (NSArray *)titlesArray;

2.在.m中实现- (void)creatWithTitlesArray: (NSArray *)titlesArray;


/**
    循环创建label
 */
- (void)creatWithTitlesArray: (NSArray *)titlesArray {
    /// 如果数组为空,返回
    if (titlesArray.count == 0) {
        return;
    }
    /// 循环便利数组
    for (NSInteger index = 0; index < titlesArray.count; index++) {
        /// 0. 创建label
        UILabel *label = [[UILabel alloc]init];
        /// 1. 设置label的文字
        label.userInteractionEnabled = YES;
        label.text = titlesArray[index];
        /// 2. 设置label的tag, 用于区分是哪个label
        label.tag = index + 10;
        /// 3. 添加label
        [self addSubview:label];
        [self.labelArray addObject:label];
    }
}

注意:这里为什么label.tag = index + 10 ?其实除了加0都是可以的,主要是为了和当前SegmentView 区分开,因为SegmentView .tag不设置的话就是0,有可能会取到SegmentView

3.在layoutSubviews方法找那个设置label的frame


- (void)layoutSubviews {
    [super layoutSubviews];
    
    if (self.labelArray.count == 0) {
        return;
    }
    for (NSInteger index = 0; index < self.labelArray.count; index++) {
        /// 0. 从数组中取出label
        UILabel *label = self.labelArray[index];
        /// 1. 返回label的外包围
        CGRect rect = [self boundsWithLabel:label];
        /// 2 设置label的frame
        label.frame = CGRectMake(100 + index * rect.size.width, 0, rect.size.width, rect.size.height);

    }
    
}


其中boundsWithLabel:方法是返回label的宽度.需要传入label,实现如下:

/**
    boundingRectWithSize:CGSizeMake
    CGSize:外包围的限制
    CGFLOAT_MAX返回的是最大的浮点数, 也就是这里在计算宽度时不做限
    NSStringDrawingUsesFontLeading属性表示用自字体作为计算行高的标准
    attributes字典传入的是文字的渲染样式,NSFontAttributeName键传入文字的字体和字号,。
 
 @param label 传入的label
 @return 返回的CGRect是文字根据以上要求,渲染出来的外包围
 */
- (CGRect)boundsWithLabel:(UILabel*)label {
    return [label.text boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, label.frame.size.height) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:label.font} context:nil];
}

4.接下来是实现label的点击方法,在这个方法里计算是哪个lable被点击了

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesEnded:touches withEvent:event];
    
    UITouch *touch = [touches anyObject];
    CGPoint point = [touch locationInView:self];
    NSInteger detla = self.frame.size.width / self.labelArray.count;
    NSInteger touchNumber = point.x / detla;
    self.selected = touchNumber;

    [self setSelectItemAtIndex:touchNumber animate:YES];
}

[self setSelectItemAtIndex:touchNumber animate:YES]; 是点击label实现的动画

- (void)setSelectItemAtIndex:(NSUInteger)idx animate:(BOOL)animated {
   
    self.selected = idx;
    
    [self.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        if ([obj isKindOfClass:[UILabel class]]) {
            UILabel* label = obj;
            if (self.selected + 10 == label.tag ) {
                label.textColor = self.tintColor;
            }
            else {
                label.textColor = [UIColor redColor];
            }
            
        }
    }];
    
  
}



便利所有的lable如果是当前被点击的label颜色变色

5.在控制器把SegmentView实例出来,就是一下效果

SegmentView *segmentView = [[SegmentView alloc]initWithFrame:CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
    [segmentView creatWithTitlesArray:@[@"我是标题1",@"我是标题2222222"]];

    [self.view addSubview:segmentView];
Untitled.gif

6.在lable下面添加一根线,当点击lable的有一个滑动的动画,在SegmentView.m中声明一个selectView

@property (nonatomic, strong) UIView *selectView;

懒加载selectView

- (UIView *)selectView
{
    if (!_selectView) {
        
        UILabel *label = self.labelArray[0];
        _selectView = [[UIView alloc] initWithFrame:CGRectMake(label.frame.origin.x, label.frame.size.height + label.frame.origin.y   + 10, label.frame.size.width,1)];        [self addSubview:_selectView];
        _selectView.backgroundColor = [UIColor blueColor];
    }
    return _selectView;
}

selectView的默认位置要根据第一个label的frame来计算,所有从数组中取出第一个label的frame

7.- (void)setSelectItemAtIndex:(NSUInteger)idx animate:(BOOL)animated 在这方法加滑动动画

 [UIView animateWithDuration:0.5 animations:^{
        
        UILabel *label = (UILabel*)[self viewWithTag:idx + 10];
        [self.selectView setFrame:CGRectMake(label.frame.origin.x, label.frame.size.height + label.frame.origin.y   + 10, label.frame.size.width,1)];
               
        
    }];


Untitled.gif

8.现在想在增加两个子控制器并把他们显示出来

建立一个控制器Test1ViewController继承自UIViewController,在主控制器建立父子关系

  Test1ViewController *test1Vc = [[Test1ViewController alloc]init];
    Test1ViewController *test2Vc = [[Test1ViewController alloc]init];
    
    [self addChildViewController:test1Vc];
    [self addChildViewController:test2Vc];

9. SegmentView.h中增加两个控制器的属性.并在.m中实现set方法

@property (nonatomic , strong)UIViewController *test1Vc;
@property (nonatomic , strong)UIViewController *test2Vc;
- (void)setTest2Vc:(UIViewController *)test2Vc {
    _test2Vc = test2Vc;
    if (self.test2Vc) {
        self.test2Vc.view.frame = CGRectMake([UIScreen mainScreen].bounds.size.width, 60, [UIScreen mainScreen].bounds.size.width, self.bounds.size.height - 40);
        self.test2Vc.view.backgroundColor = [UIColor orangeColor];
//        [self addSubview:self.test2Vc.view];
    }
}
- (void)setTest1Vc:(UIViewController *)test1Vc {
    _test1Vc = test1Vc;
    if (self.test1Vc) {
        self.test1Vc.view.frame = CGRectMake(0, 60, [UIScreen mainScreen].bounds.size.width, self.bounds.size.height - 40);
        self.test1Vc.view.backgroundColor = [UIColor redColor];
//        [self addSubview:self.test1Vc.view];
    }
}

这样控制器就加上了,因为每个控制的view宽度是屏幕的宽度,所有要点击label的时候以动画的形势切换他们的位置在- (void)setSelectItemAtIndex:(NSUInteger)idx animate:(BOOL)animated 方法实现动画

- (void)setSelectItemAtIndex:(NSUInteger)idx animate:(BOOL)animated {
   
    self.selected = idx;
    
    [self.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        if ([obj isKindOfClass:[UILabel class]]) {
            UILabel* label = obj;
            if (self.selected + 10 == label.tag ) {
                label.textColor = self.tintColor;
            }
            else {
                label.textColor = [UIColor redColor];
            }
            
        }
    }];
    
    //这里是我们下方的那根线,移动的动画,下面详细说
    [UIView animateWithDuration:0.5 animations:^{
        
        UILabel *label = (UILabel*)[self viewWithTag:idx + 10];
        [self.selectView setFrame:CGRectMake(label.frame.origin.x, label.frame.size.height + label.frame.origin.y   + 10, label.frame.size.width,2)];
        
        if (label.tag == 10) {
            self.test2Vc.view.frame = CGRectMake([UIScreen mainScreen].bounds.size.width, 60, [UIScreen mainScreen].bounds.size.width, self.bounds.size.height - 40);
            self.test1Vc.view.frame = CGRectMake(0, 60, [UIScreen mainScreen].bounds.size.width, self.bounds.size.height - 40);
        } else if (label.tag == 11) {
             self.test2Vc.view.frame = CGRectMake(0, 60, [UIScreen mainScreen].bounds.size.width, self.bounds.size.height - 40);
             self.test1Vc.view.frame = CGRectMake(-[UIScreen mainScreen].bounds.size.width, 60, [UIScreen mainScreen].bounds.size.width, self.bounds.size.height - 40);
        }

    }];
}


10 在Test1ViewController创建一个tableView,实现代理数据源方法


//
//  Test1ViewController.m
//  GHSegmentLabel
//
//  Created by admin on 17/7/29.
//  Copyright © 2017年 admin. All rights reserved.
//

#import "Test1ViewController.h"
#import "PushViewController.h"

@interface Test1ViewController ()<UITableViewDelegate,UITableViewDataSource>
@property (nonatomic , strong) UITableView *tableView;
@end

@implementation Test1ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    [self.view addSubview:self.tableView];
    NSLog(@"子控制器:%@",self.navigationController);
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    
    
    NSLog(@"%@",self.navigationController);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 10;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    cell.textLabel.text = [NSString stringWithFormat:@"%ld",(long)indexPath.row];
    cell.backgroundColor = indexPath.row % 2 == 0 ? [UIColor orangeColor]:[UIColor brownColor];
    return cell;
}
- (UITableView *)tableView {
    if (_tableView == nil) {
        _tableView = [[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStylePlain];
        _tableView.delegate = self;
        _tableView.dataSource = self;
        [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
    }
    return _tableView;
}

@end




11.给ViewController增加一个导航条

BE0CC3CC-BC51-4B77-9BB5-CD17C29AAD59.png

在tableView的点击事件里打印导航条

    NSLog(@"%@",self.navigationController);

控制台输出:

A5705EB3-C9C7-41FC-856F-9B56E96D2982.png

说明建立父子控制器成功,并且拿到了导航条

最后效果

10590187-6985-438F-967F-1B9196B0856C.png
上一篇下一篇

猜你喜欢

热点阅读