JFTabView 标签滑动视图封装

项目中好多个地方需要上面标签,下面滑动视图的界面,有时候个数还不同,于是写了个封装。封装的JFtabView内部的包括点击滑动,布局等都自动完成,只需要直接传入需要的子视图和按钮即可显示界面,当然,下面滑动控件具体每个视图,还是需要自己去根据需求来做。外部的按钮点击方法也需要自己去做(点击的各种切换已经实现,不需要额外去写)

一.h文件

//
//  JFTabView.h
//  JFTabViewMaster
//
//  Created by Jeffrey on 2017/5/16.
//  Copyright © 2017年 Jeffrey. All rights reserved.
//

#import <UIKit/UIKit.h>
typedef  void(^JFLayoutCallBack)(UIView *topView,NSArray *buttons);

@class JFTabObject;

@interface JFTabView : UIView

/**内部包含的关联控件类数组,每个包含一个scrollView里面的subview和上面的一个按钮*/
@property(nonatomic, strong, readonly) NSArray<JFTabObject*>*subTabObjects;

#pragma mark --- 头部topView相关属性
/**头部的topView,可用改变其属性,但是无法直接重新赋值,需要改变内部约束请使用layoutTopViewCustomCallback回调属性*/
@property(nonatomic, strong, readonly) UIView *topView;
/**一般下面的scrollView只会传视图即可,上方的topView肯能需要自定义布局,如果需要,
 * 拿这个回调布局即可(讨厌协议写法,来回倒腾遵守协议啥还不如block直观)*/
@property(nonatomic, copy) JFLayoutCallBack layoutTopViewCustomCallback;
/**上面topView高度,只读,展现的时候需要赋值*/
@property(nonatomic, assign,readonly) CGFloat topViewHeight;
/**每个bt的大小,内部是约束布局,大小只能通过它来设置*/
@property(nonatomic, assign) CGSize btSize;



#pragma mark --- 滑块相关属性
/**上面滑块高度,默认为5*/
@property(nonatomic, assign) CGFloat topViewLineHeight;
/**上面滑块高度,默认为和按钮等宽*/
@property(nonatomic, assign) CGFloat topViewLineWidth;
/**上面滑块高度对应按钮倍数,该参数生效优先级比上面topViewLineWidth高*/
@property(nonatomic, assign) CGFloat topViewLineWidthMultiplier;
/**滑块颜色,默认为红色*/
@property(nonatomic, strong) UIColor *topViewLineColor;


#pragma mark --- 主要显示方法
/**
 * 主要方法,传入subTabObjects数组,根据内部定义的按钮和子视图以及上方的高度来显示视图
 * @param subTabObjects 内部关联控件,每个包含一个scrollView的子视图和上方的按钮
 * @param topViewHeight 上方topView的高度
 */
- (void)showWithSubTabObjects:(NSArray <JFTabObject *> *)subTabObjects topViewHeight:(CGFloat)topViewHeight;
@end


@interface JFTabObject : NSObject
/**单个子视图,在scrollView内部每个块需要含一个*/
@property(nonatomic, strong) UIView *scrollSubView;
/**topView上方按钮,和下面scrollView一一对应*/
@property(nonatomic, strong) UIButton *btSubView;

#pragma mark --- 初始化方法

- (instancetype)initWithScrollSubView:(UIView *)scrollSubView btSubView:(UIButton *)btSubView;

+ (instancetype)objectWithScrollSubView:(UIView *)scrollSubView btSubView:(UIButton *)btSubView;


@end

二.m文件

//
//  JFTabView.m
//  JFTabViewMaster
//
//  Created by Jeffrey on 2017/5/16.
//  Copyright © 2017年 Jeffrey. All rights reserved.
//

#import "JFTabView.h"

@interface JFTabView () <UIScrollViewDelegate>
@property(nonatomic, strong) UIScrollView *scrollView;
@property(nonatomic, strong) UIView *topViewLine;
@property(nonatomic, strong) NSLayoutConstraint *layoutConstraintX;
@end

@implementation JFTabView
/**如果xib读取,则会按照这个方法来初始化*/
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self initializeFirst];
    }
    return self;
}

/**常规手写代码初始化*/
- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self initializeFirst];
    }
    return self;
}

/**初始化都调用它,让子控件也正确初始化出来*/
- (void)initializeFirst {
    [self setValue:[[UIView alloc] init] forKey:@"topView"];
    self.topView.translatesAutoresizingMaskIntoConstraints = NO;
    [self addSubview:self.topView];

    self.scrollView = [[UIScrollView alloc] init];
    self.scrollView.bounces = NO;
    self.scrollView.pagingEnabled = YES;
    self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
    self.scrollView.delegate = self;
    [self addSubview:self.scrollView];

    self.topViewLine = [[UIView alloc] init];
    [self.topView addSubview:self.topViewLine];

}

- (void)showWithSubTabObjects:(NSArray <JFTabObject *> *)subTabObjects topViewHeight:(CGFloat)topViewHeight {
    [self setValue:@(topViewHeight) forKey:@"topViewHeight"];
    [self setValue:subTabObjects forKey:@"subTabObjects"];
    /**设置第一个按钮未选中且不可用*/
    UIButton *btFirst = self.subTabObjects.firstObject.btSubView;
    btFirst.selected = YES;
    btFirst.userInteractionEnabled = NO;

    [self layoutTopView];
    [self layoutScrollView];
    [self layoutSubButtons];
    [self layoutTopViewLine];
    [self layoutTopViewCustom];
    [self layoutScrollViewSubViews];
}

/**头部topView布局,只会根据之前设置的topViewHeight属性在整个控件中布局高度,宽度和整个控件等宽*/
- (void)layoutTopView {
    NSDictionary *metricsTopView = @{
            @"topViewHeight": @(self.topViewHeight)
    };
    UIView *topView = self.topView;
    NSString *ltFtTopViewV = @"V:|-0-[topView(==topViewHeight)]";
    NSString *ltFtTopViewH = @"H:|-0-[topView]-0-|";
    NSArray *ltTopViewV = [NSLayoutConstraint constraintsWithVisualFormat:ltFtTopViewV options:(NSLayoutFormatOptions) 0 metrics:metricsTopView views:NSDictionaryOfVariableBindings(topView)];
    NSArray *ltTopViewH = [NSLayoutConstraint constraintsWithVisualFormat:ltFtTopViewH options:(NSLayoutFormatOptions) 0 metrics:metricsTopView views:NSDictionaryOfVariableBindings(topView)];
    NSMutableArray *ltConstraints = [[NSMutableArray alloc] init];
    [ltConstraints addObjectsFromArray:ltTopViewV];
    [ltConstraints addObjectsFromArray:ltTopViewH];
    [self addConstraints:ltConstraints];
}

/**scrollView布局,上方和topView对齐,下方和整个控件底部对齐*/
- (void)layoutScrollView {

    UIScrollView *scrollView = self.scrollView;
    UIView *topView = self.topView;
    NSString *ltFtScrollViewV = @"V:[topView]-0-[scrollView]-0-|";
    NSString *ltFtScrollViewH = @"H:|-0-[scrollView]-0-|";
    NSArray *ltScrollViewV = [NSLayoutConstraint constraintsWithVisualFormat:ltFtScrollViewV options:(NSLayoutFormatOptions) 0 metrics:nil views:NSDictionaryOfVariableBindings(scrollView, topView)];
    NSArray *ltScrollViewH = [NSLayoutConstraint constraintsWithVisualFormat:ltFtScrollViewH options:(NSLayoutFormatOptions) 0 metrics:nil views:NSDictionaryOfVariableBindings(scrollView, topView)];
    NSMutableArray *ltConstraints = [[NSMutableArray alloc] init];
    [ltConstraints addObjectsFromArray:ltScrollViewV];
    [ltConstraints addObjectsFromArray:ltScrollViewH];
    [self addConstraints:ltConstraints];
}


/**按钮布局,传入关联控件数组有n个,那么中心线就按照n+1分之一。高宽则根据属性btSize来确定*/
- (void)layoutSubButtons {
    for (int i = 0; i < self.subTabObjects.count; i++) {
        JFTabObject *tabObject = self.subTabObjects[(NSUInteger) i];
        UIButton *button = tabObject.btSubView;
        button.tag = i;
        [self.topView addSubview:button];
        button.translatesAutoresizingMaskIntoConstraints = NO;
        if (!CGSizeEqualToSize(self.btSize, CGSizeZero)) {
            [self setLayoutWidth:self.btSize.width view:button];
            [self setLayoutHeight:self.btSize.height view:button];
        }

        [button addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside];

        CGFloat multiplierH = (CGFloat) (1 / ((CGFloat) self.subTabObjects.count + 1) * (i + 1));

        /**竖直约束*/
        NSLayoutConstraint *layoutConstraintY = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.topView attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
        [self.topView addConstraint:layoutConstraintY];
        /**横向约束*/
        NSLayoutConstraint *layoutConstraintX = [NSLayoutConstraint constraintWithItem:button attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.topView attribute:NSLayoutAttributeTrailing multiplier:multiplierH constant:0];
        [self.topView addConstraint:layoutConstraintX];

    }
}

/**滑块布局,和第一个按钮的布局一样,只是高宽分别有属性topViewLineHeight和
 * topViewLineWidth(topViewLineWidthMultiplier也可以)来控制*/
- (void)layoutTopViewLine {

    CGFloat multiplierH = (CGFloat) (1 / ((CGFloat) self.subTabObjects.count + 1));
    self.topViewLine.translatesAutoresizingMaskIntoConstraints = NO;
    self.topViewLine.backgroundColor = self.topViewLineColor ? self.topViewLineColor : [UIColor redColor];
    UIButton *btFirst = self.subTabObjects.firstObject.btSubView;
    /**滑块宽度,如果有精确宽度且没指定按钮宽度倍数,那么按照精确的宽度。否则按照指定倍数(没指定则按1倍默认走)*/
    BOOL hasExactWidth = self.topViewLineWidth > 0 && self.topViewLineWidthMultiplier == 0;

    if (hasExactWidth) {
        [self setLayoutWidth:self.topViewLineWidth view:self.topViewLine];
    } else {
        /**要么精确高度没有指定,倍数也没指定,要么精确高度指定且倍数也指定*/
        CGFloat multiplier = self.topViewLineWidthMultiplier > 0 ? self.topViewLineWidthMultiplier : 1;
        NSLayoutConstraint *layoutConstraintWidth = [NSLayoutConstraint constraintWithItem:self.topViewLine attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:btFirst attribute:NSLayoutAttributeWidth multiplier:multiplier constant:0];
        [self.topView addConstraint:layoutConstraintWidth];
    }
    self.topViewLineHeight = self.topViewLineHeight > 0 ? self.topViewLineHeight : 5.0f;
    [self setLayoutHeight:self.topViewLineHeight view:self.topViewLine];

    /**竖直约束*/
    NSLayoutConstraint *layoutConstraintY = [NSLayoutConstraint constraintWithItem:self.topViewLine attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.topView attribute:NSLayoutAttributeBottom multiplier:1 constant:0];
    [self.topView addConstraint:layoutConstraintY];
    /**横向约束,这里会滑动,所以设置为属性*/
    self.layoutConstraintX = [NSLayoutConstraint constraintWithItem:self.topViewLine attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.topView attribute:NSLayoutAttributeTrailing multiplier:multiplierH constant:0];

    [self.topView addConstraint:self.layoutConstraintX];

}

/**自定义布局,回传所有buttons和topiew*/
- (void)layoutTopViewCustom {
    if (self.layoutTopViewCustomCallback) {
        NSMutableArray *buttons = [NSMutableArray array];
        for (JFTabObject *tabObject in self.subTabObjects) {
            [buttons addObject:tabObject.btSubView];
        }
        self.layoutTopViewCustomCallback(self.topView, buttons);
    }

}


/**scrollView内部布局,根据给的数组属性subTabObjects以及其内部的scrollSubView确定子视图的布局*/
- (void)layoutScrollViewSubViews {
    UIView *lastView = nil;
    UIScrollView *scrollView = self.scrollView;
    UIView *topView = self.topView;
    for (JFTabObject *tabObject in self.subTabObjects) {
        UIView *scrollSubView = tabObject.scrollSubView;
        [self.scrollView addSubview:scrollSubView];
        scrollSubView.translatesAutoresizingMaskIntoConstraints = NO;
    }
    for (int i = 0; i < self.subTabObjects.count; i++) {
        JFTabObject *tabObject = self.subTabObjects[(NSUInteger) i];
        UIView *subView = tabObject.scrollSubView;
        NSMutableArray *ltConstraints = [[NSMutableArray alloc] init];


        /**垂直方向参照为superView,即scrollView,高度也为scrollView的高度*/
        NSString *ltFtSubViewV = @"V:|-0-[subView(scrollView)]-0-|";
        NSArray *ltSubViewV = [NSLayoutConstraint constraintsWithVisualFormat:ltFtSubViewV options:(NSLayoutFormatOptions) 0 metrics:nil views:NSDictionaryOfVariableBindings(subView, topView, scrollView, self)];
        [ltConstraints addObjectsFromArray:ltSubViewV];



        /**subview左边约束均为0,如果是第一个视图,那么左边为superview,否则为lastView*/
        NSString *ltFtSubViewHLeft = i == 0 ? @"H:|-0-[subView(topView)]" : @"H:[lastView]-0-[subView(topView)]";

        /**如果是第一个视图,添加约束的时候不用添加lastView,因为还没生成*/
        NSDictionary *views = i == 0 ? NSDictionaryOfVariableBindings(subView, topView, scrollView, self) : NSDictionaryOfVariableBindings(subView, lastView, topView, scrollView, self);
        NSArray *ltSubViewHLeft = [NSLayoutConstraint constraintsWithVisualFormat:ltFtSubViewHLeft options:(NSLayoutFormatOptions) 0 metrics:nil views:views];
        [ltConstraints addObjectsFromArray:ltSubViewHLeft];
        /**到最后右边约束和scrollView为0即可*/
        if (i == (self.subTabObjects.count - 1)) {
            NSString *ltFtSubViewHRight = @"H:[subView(topView)]-0-|";
            NSArray *ltSubViewHRight = [NSLayoutConstraint constraintsWithVisualFormat:ltFtSubViewHRight options:(NSLayoutFormatOptions) 0 metrics:nil views:NSDictionaryOfVariableBindings(subView, topView, scrollView, self)];
            [ltConstraints addObjectsFromArray:ltSubViewHRight];
        }
        [self addConstraints:ltConstraints];
        lastView = subView;
    }
}

/**高度约束简写*/
- (void)setLayoutHeight:(CGFloat)height view:(UIView *)view {
    NSDictionary *views = NSDictionaryOfVariableBindings(view);
    NSString *format = @"V:[view(height)]";
    NSDictionary *metrics = @{
            @"height": @(height)
    };

    NSArray *array = [NSLayoutConstraint constraintsWithVisualFormat:format options:(NSLayoutFormatOptions) 0 metrics:metrics views:views];
    [view.superview addConstraints:array];
}

/**宽度约束简写*/
- (void)setLayoutWidth:(CGFloat)width view:(UIView *)view {
    NSDictionary *views = NSDictionaryOfVariableBindings(view);
    NSString *format = @"H:[view(width)]";
    NSDictionary *metrics = @{
            @"width": @(width)
    };
    NSArray *array = [NSLayoutConstraint constraintsWithVisualFormat:format options:(NSLayoutFormatOptions) 0 metrics:metrics views:views];
    [view.superview addConstraints:array];
}

/**点击事件,选中单个按钮,其他按钮都变为未选中,如果点击已选中的按钮,其不可用,外部代码也不可点击*/
- (void)clickButton:(UIButton *)clickButton {
    NSLog(@"点击了%d", clickButton.tag);
    for (JFTabObject *tabObject in self.subTabObjects) {
        UIButton *currentBt = tabObject.btSubView;
        /**当前点击的如果被选中,设置不可选中,如果没被选中,改为选中,其它按钮变为未选中*/
        if (currentBt == clickButton) {
            clickButton.selected = !clickButton.selected;
            clickButton.userInteractionEnabled = !clickButton.selected;

        } else {
            currentBt.selected = NO;
            currentBt.userInteractionEnabled = YES;

        }

    }


    CGFloat width = CGRectGetWidth(self.bounds);
    [UIView animateWithDuration:0.3 animations:^{
        self.scrollView.contentOffset = CGPointMake(width * (clickButton.tag), 0);
        self.layoutConstraintX.constant = (CGFloat) ((1.0 / (self.subTabObjects.count + 1)) * width * clickButton.tag);
    }                completion:^(BOOL finished) {

    }];
}


#pragma mark --- scrollView代理

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGFloat width = CGRectGetWidth(self.bounds);
    CGFloat index = scrollView.contentOffset.x / width;
    self.scrollView.contentOffset = CGPointMake((width * (index)), 0);
    self.layoutConstraintX.constant = (CGFloat) ((1.0 / (self.subTabObjects.count + 1)) * width * index);

}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    CGFloat width = CGRectGetWidth(self.bounds);
    CGFloat index = scrollView.contentOffset.x / width;
    NSNumber *indexNumber = [[NSNumber alloc] initWithFloat:index];
    /**整数和小数相等则表示滑动到了按钮位置*/
    if (indexNumber.intValue == indexNumber.floatValue) {
        UIButton *clickBtAuto = self.subTabObjects[(NSUInteger) indexNumber.integerValue].btSubView;
        if (clickBtAuto.userInteractionEnabled) {
            [self clickButton:clickBtAuto];
        }
    }

}

@end


@implementation JFTabObject
- (instancetype)initWithScrollSubView:(UIView *)scrollSubView btSubView:(UIButton *)btSubView {
    self = [super init];
    if (self) {
        self.scrollSubView = scrollSubView;
        self.btSubView = btSubView;
    }

    return self;
}

+ (instancetype)objectWithScrollSubView:(UIView *)scrollSubView btSubView:(UIButton *)btSubView {
    return [[self alloc] initWithScrollSubView:scrollSubView btSubView:btSubView];
}

@end

三.使用

主要使用- (void)showWithSubTabObjects:(NSArray <JFTabObject *> *)subTabObjects topViewHeight:(CGFloat)topViewHeight

这里JFTabObject为关联对象,每个对象包含一个子视图和一个按钮,这样上面的按钮和下面的每个视图一一对应。设置好后直接调用上面方法即可显示。

四.其它设置

常规来说,只需要调用showWith方法,传入对应的参数即可显示,你还可以根据h文件里的一些可选参数来设置如何显示,例如可以设置滑块的高宽,按钮的高宽等,具体可以在h文件中查看

五.原理

其实只是简单的一个UIView,里面包含了上部的topView,下面为UIScrollView,内部会根据showWith方法传入的参数来进行视图和按钮的初始化,可选参数则可以进行定制显示,另外可选参数中的layoutTopViewCustomCallback属性是个block,可以利用它和内部的按钮和topView配合在topView中进行添加额外视图的操作。scrollView里则没有配置相关方法,因为本身就需要传入各个视图,每个视图都是你已经需要的了。

五.例子

代码请点:这里
使用的代码如下

//
//  ViewController.m
//  JFTabViewMaster
//
//  Created by Jeffrey on 2017/5/16.
//  Copyright (c) 2017 Jeffrey. All rights reserved.
//

#import "ViewController.h"
#import "JFTabView.h"


@interface ViewController () <UITableViewDelegate, UITableViewDataSource>
@property(nonatomic, weak) IBOutlet JFTabView *tabView;

@property(nonatomic, strong) UITableView *tableViewNone;
@property(nonatomic, strong) NSArray *dataSourceOne;
@end

@implementation ViewController


- (void)viewDidLoad {
    [super viewDidLoad];

    /**第一页tableview以及其数据源设置*/
    self.tableViewNone = [[UITableView alloc] init];
    self.tableViewNone.delegate = self;
    self.tableViewNone.dataSource = self;
    NSMutableArray *dataSourceOne = [NSMutableArray array];
    for (int i = 0; i < 100; i++) {
        [dataSourceOne addObject:@(i)];
    }
    self.dataSourceOne = dataSourceOne;
    self.tableViewNone.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
    /**第一页的buuton和关联对象初始化*/
    UIButton *button1 = [[UIButton alloc] init];
    [button1 setTitle:@"第一页" forState:UIControlStateNormal];
    [button1 setTitle:@"第一页" forState:UIControlStateSelected];
    [button1 setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
    [button1 setTitleColor:[UIColor redColor] forState:UIControlStateSelected];
    JFTabObject *object1 = [JFTabObject objectWithScrollSubView:self.tableViewNone btSubView:button1];



    /**第二页常规View,加载了一个xib里的View*/
    UIView *ViewTwo = [[NSBundle mainBundle] loadNibNamed:@"CustomView" owner:nil options:nil].firstObject;
    /**第二页的buuton和关联对象初始化*/
    UIButton *button2 = [[UIButton alloc] init];
    [button2 setTitle:@"第二页" forState:UIControlStateNormal];
    [button2 setTitle:@"第二页" forState:UIControlStateSelected];
    [button2 setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
    [button2 setTitleColor:[UIColor redColor] forState:UIControlStateSelected];
    JFTabObject *object2 = [JFTabObject objectWithScrollSubView:ViewTwo btSubView:button2];


    UIView *viewThree = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
    viewThree.backgroundColor = [UIColor redColor];
    UIButton *button3 = [[UIButton alloc] init];
    [button3 setTitle:@"第三页" forState:UIControlStateNormal];
    [button3 setTitle:@"第三页" forState:UIControlStateSelected];
    [button3 setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
    [button3 setTitleColor:[UIColor redColor] forState:UIControlStateSelected];
    JFTabObject *object3 = [JFTabObject objectWithScrollSubView:viewThree btSubView:button3];


    /**传入指定对象数组*/
    NSArray *subTabObjects = @[object1, object2, object3];
    /**设置按钮高宽*/
//    self.tabView.btSize = CGSizeMake(20, 30);
    /**滑块高度,默认就是5*/
    self.tabView.topViewLineHeight = 5;
    /**滑块宽度倍数默认,具体看注释*/
    self.tabView.topViewLineWidthMultiplier = 2;


    /**手动添加布局到topView*/
    UILabel *label = [[UILabel alloc] init];
    label.text = @"外部添加在topView上的测试";
    self.tabView.layoutTopViewCustomCallback = ^(UIView *topView, NSArray *buttons) {
        label.translatesAutoresizingMaskIntoConstraints = NO;
        [topView addSubview:label];
        label.font = [UIFont systemFontOfSize:10];
        NSLayoutConstraint *layoutConstraintTop = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:topView attribute:NSLayoutAttributeTop multiplier:1 constant:0];
        [topView addConstraint:layoutConstraintTop];

        NSLayoutConstraint *layoutConstraintV = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:topView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
        [topView addConstraint:layoutConstraintV];

    };


    /**开始展现*/
    [self.tabView showWithSubTabObjects:subTabObjects topViewHeight:60];
    // Do any additional setup after loading the view, typically from a nib.
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.dataSourceOne.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *ID = @"cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    }
    NSNumber *number = self.dataSourceOne[(NSUInteger) indexPath.row];
    cell.textLabel.text = number.stringValue;
    return cell;
}


@end

效果如下图:

1.png
2.png
3.png

第一页是加载的UITableview,第二页加载是xib的常规UIView,第三页直接手写初始化的UIView。注意,如果手动添加view,最好是用代码布局,不要仅仅是使用fram。因为内部都是用布局写的,不是用frame写的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 重点参考链接: View Programming Guide for iOS https://developer....
    Kevin_Junbaozi阅读 4,395评论 0 15
  • 有人选择二,二着自己的生活 有人选择狂,狂着自己的梦想 有人选择愣,愣着傻帽的娱乐 有人选择纯,纯着不食五谷粮 有...
    栋赵阅读 1,732评论 4 6
  • 【生活】早晨硬是把自己折磨醒,我也是不容易,希望明天能按时起床,多看会儿书。假期恢复中,继续自律吧。 【学习】交了...
    晴天猫小喵阅读 84评论 0 0
  • 写个故事,不知道会不会有人看。 这是一个关于成长的故事,充满了阳光与欢笑,泪水与悲伤。 2014年的暑假,...
    wqzkai_阅读 143评论 1 0
  • instancetype和id区别? instancetype在类型表示上,跟id一样,可以表示任何对象类型 in...
    韩旭杰阅读 166评论 0 0