设置tableViewContentSize为自身高度时,布局出错的解决办法

项目中需求,tableView 需要被 add到一个scrollView上。tableView的内容完全平铺出来,即设置tableView的height等于tableView.ContentSize.height。 当数据刷新的时候,table的frame也需要动态改变,这时候有可能出现ui上的问题。

原因:当你reloadData后,contentsize有可能没有及时改变。这时候你设置的话就有可能出错。

方法1: 当tableView重新布局完成后,再设置frame。你可以在下一个runloop里设置frame。

 

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

        CGFloat calendarMinHeight = self.s_CalendarView.m_MinHeight;

        CGSize remindTableViewContentSize = self.s_remindTableView.contentSize;

        CGFloat bottomPadding = [UIScreen mainScreen].bounds.size.height - 64 - calendarMinHeight - remindTableViewContentSize.height;

        bottomPadding = bottomPadding>=0 ? bottomPadding : 0;

        // 根据tableview内容高度修改其frame高度约束

        self.s_RemindTableViewHeightConstraint.equalTo(@(remindTableViewContentSize.height));

        self.s_BottomPaddingViewHeightConstraint.equalTo(@(bottomPadding));

        

        [self.s_BackdropScrollView updateConstraintsIfNeeded];

        [self.s_BackdropScrollView layoutIfNeeded];

    });

 

此延时函数,可以 理解为将代码放到下一个runloop里运行。而这时tableView 已经重新布局完成。

这种方法的缺陷是,当数据多的时候,经测试,延时时间需要设置大一点,才能布局成功。

(tableVIew计算contentSize,你需要等他布局完成)。

方法2: 自己手动计算contentSize。即你拿到新的数据,需要reloadDate时。你自己根据数据计算高度并赋值。然后reloadData。这样不用等到下一个runloop。效果较好。

 

    NSInteger modelNum = 0;

    for (int i = 0; i < modelArray.count; i++)

    {

            modelNum += [modelArray[i] count];

    }

    CGRect frame = ScheduleTable.frame;

    frame.size.height = workListAry.count    * HistoryCellHeight;

    // 根据tableview内容高度修改其frame高度约束

    self.s_RemindTableViewHeightConstraint.equalTo(@(frame.size.height));

    self.s_BottomPaddingViewHeightConstraint.equalTo(@(bottomPadding));

    

    [self.s_BackdropScrollView updateConstraintsIfNeeded];

    [self.s_BackdropScrollView layoutIfNeeded];

    [ScheduleTable reloadData];

 

 

 

 

题外:另外一个场景很类似。我需要在界面显示的时候,将scrollVIew指定的contentoffSet展示出来。 我在ViewDidLoad里设置scrollView.contentoffSet = (0,200),没有效果。写在ViewDidAppear里有效果。因为ViewDidLoad 和VIewWillAppear在一个runloop里,这时还没有布局完成。而ViewDidAppear已经布局完成了。但是别的问题又来了,如果你写在ViewDidAppera里,你会看到界面闪一下。 我的临时做法是

在ViewDidload里,

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

 

    CGFloat topInset = TimeScroll.contentInset.top;

    CGFloat beginOffsetY = -topInset;

    CGFloat calendarViewHiddenHeight = [self.s_CalendarView intrinsicContentSize].height-self.s_CalendarView.m_MinHeight;

    CGFloat endOffsetY = beginOffsetY + calendarViewHiddenHeight;

    [self.s_BackdropScrollView setContentOffset:CGPointMake(0, endOffsetY) animated:NO];

    });

。这相当于在下一个runloop里设置了,那是已经布局完成了。不过建议尽量不用

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值