iOS scrollview中嵌套用xib写的UIViewController 大小不对

需求:一个界面需要加载多个控制器,最底部用UIScrollView来实现滑动,通过自定义顶部的view来实现点击跳转。
问题:子控制器创建的时候默认带了xib,如果不在xib里面直接拖东西,控制器的view那么添加到UIScrollView上的宽度就是正确的 ,
但是如果添直接在控制器的xib拖了东西之后,控制器的view添加到UIScrollView上的宽度就会是xib的宽度。

图片:
clipboard.png

如图,在vc01中的xib中拖了一个UITableView并设置约束距离左、右、下都为0,距离顶部一定距离。然后将控制器vc01作为子控制器加载到UIScrollView界面的控制器中。

打印结果:打印出来的这个vc01控制器的view的宽度是vc01 width = 375.000000

附上代码在主界面的代码,添加的子控制器就是带有xib的控制器:

@interface HomeViewController ()<UIScrollViewDelegate>
/** 标签底部的红色指示器 */
@property (nonatomic, weak) UIView  * indicatorView;
/** 当前选中的按钮 */
@property (nonatomic, weak) UIButton * selectedButton;
/** 顶部所有标签 */
@property (nonatomic, weak) UIView  * titlesView;
/** 底部的所有内容 */
@property (nonatomic, weak) UIScrollView  * contentView;
@end

@implementation HomeViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor clearColor];
    
    [self setupChildVCs];
    
    [self setupTitlesView];
    
    [self setupContentView];
}

- (void)viewDidLayoutSubviews{
    // 2. 在这里拿到的宽度是正确的
    NSLog(@"layo_self.view.frame.size.width = %f", self.view.bounds.size.width);
}

/**
 * 初始化子控制器
 */
- (void)setupChildVCs{
    
    Test01ViewController * vc01 = [[Test01ViewController alloc]init];
    vc01.title = @"vc01";
    vc01.view.backgroundColor = [UIColor redColor];
    [self addChildViewController:vc01];
    NSLog(@"vc01 width = %f", vc01.view.bounds.size.width);
    
    Test02ViewController * vc02 = [[Test02ViewController alloc]init];
    vc02.title = @"vc02";
    vc02.view.backgroundColor = [UIColor yellowColor];
    [self addChildViewController:vc02];
    NSLog(@"vc02 width = %f", vc02.view.bounds.size.width);
}

/**
 *设置顶部的标签栏
 */
- (void)setupTitlesView{
    
    // 标签栏整体
    UIView * titlesView = [[UIView alloc]init];
//    titlesView.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.7];
    titlesView.backgroundColor = [UIColor blueColor];
//    titlesView.width = self.view.width; // 宽度
    titlesView.width = [UIScreen mainScreen].bounds.size.width;
    titlesView.height = TitlesViewH;
    titlesView.y = TitlesViewY;
    titlesView.x = 0; // 可以不写
    [self.view addSubview:titlesView];
    self.titlesView = titlesView;
    
    // 底部的红色指示器
    UIView * indicatorView = [[UIView alloc]init];
    indicatorView.backgroundColor = [UIColor redColor];
    indicatorView.height = 2;
    indicatorView.tag = -1;
    indicatorView.y = titlesView.height - indicatorView.height;
    self.indicatorView = indicatorView;
    
    // 内部的子标签
    CGFloat width = titlesView.width / self.childViewControllers.count;
    NSLog(@"width = %f, all width = %f", width, self.view.width);
    CGFloat height = titlesView.height;
    for (NSInteger i = 0; i < self.childViewControllers.count; i++) {
        
        UIButton * button = [[UIButton alloc]init];
        button.tag = i;
        button.height = height;
        button.width = width;
        button.x = i * width;
        
        UIViewController * vc = self.childViewControllers[i];
        [button setTitle:vc.title forState:UIControlStateNormal];
        [button setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
        [button setTitleColor:[UIColor redColor] forState:UIControlStateDisabled];
        button.titleLabel.font = [UIFont systemFontOfSize:14];
        [button addTarget:self action:@selector(titleClick:) forControlEvents:UIControlEventTouchUpInside];
        [titlesView addSubview:button];
        
        //默认选中第一个按钮
        if (i ==0 ) {

            button.enabled = NO;
            self.selectedButton = button;
            
            // 让按钮内部的label根据文字的内容来计算尺寸
            [button.titleLabel sizeToFit];
            self.indicatorView.width = button.titleLabel.width;
            self.indicatorView.centerX = button.centerX;
        }
    }
    [titlesView addSubview:indicatorView];
}

/**
 * 按钮的点击事件
 */
- (void)titleClick:(UIButton *)button{
    
    // 修改按钮的状态
    self.selectedButton.enabled = YES;
    button.enabled = NO;
    self.selectedButton = button;
    
    // 动画
    [UIView animateWithDuration:0.15 animations:^{
        
        self.indicatorView.width = button.titleLabel.width;
        self.indicatorView.centerX = button.centerX;
    }];
    
    // 滚动
    CGPoint offset = self.contentView.contentOffset;
    offset.x = button.tag * self.contentView.width;
    [self.contentView setContentOffset:offset animated:YES];
}

/**
 * 设置底部的ScorllView
 */
- (void)setupContentView{
    
    // 不要自动调整inset
    self.automaticallyAdjustsScrollViewInsets = NO;
    
    UIScrollView * contentView = [[UIScrollView alloc]init];
    contentView.frame = self.view.frame;
    contentView.delegate = self;
    contentView.pagingEnabled = YES;
    [self.view insertSubview:contentView atIndex:0];
    // 计算方式就是 宽带 * 子控制器的个数
    contentView.contentSize = CGSizeMake(contentView.width * self.childViewControllers.count, 0);
    self.contentView = contentView;
    
    // 添加第一个控制器的view
    [self scrollViewDidEndScrollingAnimation:contentView];
}

#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{
    
    // 当前的索引
    NSInteger index = scrollView.contentOffset.x / scrollView.width;
    
    // 取出子控制器
    UIViewController * vc = self.childViewControllers[index];
    vc.view.x = scrollView.contentOffset.x;
    vc.view.y = 0; // 设置控制器的view的y值为0(默认为20)
    vc.view.height = scrollView.height; // 设置控制器的view的height的值为整个屏幕的高度(默认是比屏幕高度少20)
    [scrollView addSubview:vc.view];
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
    [self scrollViewDidEndScrollingAnimation:scrollView];
    
    // 点击按钮
    NSInteger index = scrollView.contentOffset.x / scrollView.width;
    [self titleClick:self.titlesView.subviews[index]];
}

求大神指教。万分感谢。

阅读 3.5k
1 个回答

原因是你并没有完全指定childViewController的frame,所以它默认是你的xib视图大小,并不会去适配
addChildViewController后调用类似如下方法以适配宽高


#pragma mark- 处理ChildViewController
/// 适配子视图控制器
- (void)fitFrameForChildViewController:(UIViewController *)childViewController{
    //[self.view layoutIfNeeded];
    CGRect frame = self.view.frame;
    frame.origin.y = 0;
    childViewController.view.frame = frame;
}

另外,请尽量不要主动调用代理方法,满足相应条件它会自己走的

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题