objective-c iOS 7 表格视图无法自动调整内容插入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19091737/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:02:55  来源:igfitidea点击:

iOS 7 Table view fail to auto adjust content inset

iphoneobjective-cuitableviewios7

提问by Tony Fung Choi Fung

I am transiting my project to iOS7. I am facing a strange problem related to the translucent navigation bar.

我正在将我的项目转移到 iOS7。我正面临一个与半透明导航栏相关的奇怪问题。

I have a view controller and it has a tableview as subview (let's call it ControllerA) . I init a new uinavigationcontroller with the controllerA and present it modally using presentviewcontroller. The presented view controller's table view is blocked by the navigation bar. I set the automaticallyAdjustsScrollViewInsetsto YESbut the result did not change. I knew I can set the edgesForExtendedLayoutto UIRectEdgeNone, but it will make the navigation bar no more translucent.

我有一个视图控制器,它有一个 tableview 作为子视图(我们称之为 ControllerA)。我使用 controllerA 初始化一个新的 uinavigationcontroller,并使用presentviewcontroller 以模态方式呈现它。呈现的视图控制器的表格视图被导航栏挡住了。我将automaticAdjustsScrollViewInsets设置为YES但结果没有改变。我知道我可以将edgeForExtendedLayout设置为UIRectEdgeNone,但它会使导航栏不再透明。

Table view get blocked

表视图被阻塞

After that, I tried to create a new view controller for testing. It contains almost the same elements. But the result is much different. The table view content does not get blocked.

之后,我尝试创建一个新的视图控制器进行测试。它包含几乎相同的元素。但结果却大不相同。表视图内容不会被阻止。

enter image description here

在此处输入图片说明

Conclusion

结论

  1. Two View Controllers' automaticallyAdjustsScrollViewInsets set to YES
  2. The project is not using storyboard
  3. The first one is created at Xcode 4.6, The second one is newly created on Xcode 5
  4. I have compared two classes xib and code, not much different
  1. 两个视图控制器的 automaticAdjustsScrollViewInsets 设置为 YES
  2. 该项目没有使用故事板
  3. 第一个是在 Xcode 4.6 上创建的,第二个是在 Xcode 5 上新创建的
  4. 我比较了两个类xib和code,差别不大

回答by Tony Fung Choi Fung

I have found the answer on apple developer forum. There are two different case.

我在苹果开发者论坛上找到了答案。有两种不同的情况。

The first one, the view controller added is a UITableViewController.And the issue should not be appeared since apple will auto padding it.

第一个,添加的视图控制器是一个 UITableViewController。而且这个问题不应该出现,因为苹果会自动填充它。

The second one, the view controller is NOT a UITableViewController.And in the view hierarchy, it contains a UITableView. In this case, if the UITableview(or ScrollView) is the viewController's mainview or the first subview of the mainview, it will work. Otherwise, the view controller doesn't know which scroll view to padding and it will happen the issue.

第二个,视图控制器不是 UITableViewController。在视图层次结构中,它包含一个 UITableView。在这种情况下,如果 UITableview(或 ScrollView)是 viewController 的主视图或主视图的第一个子视图,它将起作用。否则,视图控制器不知道要填充哪个滚动视图,就会发生问题。

In my case, the view controller is the second one. And there is a background image view as the first subview of the main view. So, it fails.

就我而言,视图控制器是第二个。并且有一个背景图像视图作为主视图的第一个子视图。所以,它失败了。

Here is the Apple developer forum link (need developer account to access): https://devforums.apple.com/message/900138#900138

这是苹果开发者论坛链接(需要开发者账号才能访问):https: //devforums.apple.com/message/900138#900138

回答by Christopher Pickslay

If you want the view to underlap the navigation bar, but also want it positioned so the top of the scrollview's content is positioned below the navigation bar by default, you can add a top inset manually once the view is laid out. This is essentially what the view layout system does when the top-level view is a scroll view.

如果您希望视图与导航栏重叠,但也希望它被定位以便滚动视图内容的顶部默认位于导航栏下方,您可以在视图布局后手动添加顶部插入。当顶层视图是滚动视图时,这本质上就是视图布局系统所做的。

-(void)viewDidLayoutSubviews {
    if ([self respondsToSelector:@selector(topLayoutGuide)]) {
        UIEdgeInsets currentInsets = self.scrollView.contentInset;
        self.scrollView.contentInset = (UIEdgeInsets){
            .top = self.topLayoutGuide.length,
            .bottom = currentInsets.bottom,
            .left = currentInsets.left,
            .right = currentInsets.right
        };
    }
}

回答by awulf

Based on Tony's answer I was able to get around this problem programatically with temporarily sending the table view to the back, let the adjustments be made and then send the background view back to the back. In my case there is no flickering to this approach.

根据托尼的回答,我能够通过临时将表格视图发送到后面来以编程方式解决这个问题,进行调整,然后将背景视图发送回后面。在我的情况下,这种方法没有闪烁。

In the View Controller:

在视图控制器中:


- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

    [self.view sendSubviewToBack:self.tableView];
}

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    [self.view sendSubviewToBack:self.backgroundView];
}

Obviously if there are other subviews on self.viewyou may need to re-order those too.

显然,如果还有其他子视图,self.view您可能也需要重新订购这些子视图。

回答by Ell Neal

There's probably too many answers on this already, but I had to take Christopher's solution and modify it slightly to support view resizing andallowing the content inset to be changed in a subclass of the UIViewController.

关于这个问题的答案可能已经太多了,但我不得不采用 Christopher 的解决方案并稍微修改它以支持视图调整大小允许在UIViewController.

@interface MyViewController ()

@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (assign, nonatomic) UIEdgeInsets scrollViewInitialContentInset;

@end


@implementation MyViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self setScrollViewInitialContentInset:UIEdgeInsetsZero];
}

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

    if (UIEdgeInsetsEqualToEdgeInsets([self scrollViewInitialContentInset], UIEdgeInsetsZero)) {
        [self setScrollViewInitialContentInset:[self.scrollView contentInset]];
    }
}

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    UIEdgeInsets scrollViewInset = [self scrollViewInitialContentInset];

    if (UIEdgeInsetsEqualToEdgeInsets(scrollViewInset, UIEdgeInsetsZero) {

        if ([self respondsToSelector:@selector(topLayoutGuide)]) {
            scrollViewInset.top = [self.topLayoutGuide length];
        }

        if ([self respondsToSelector:@selector(bottomLayoutGuide)]) {
            scrollViewInset.bottom = [self.bottomLayoutGuide length];
        }

        [self.scrollView setContentInset:scrollViewInset];
    }
}

@end

To explain the point:

为了解释这一点:

Any subclass of MyViewControllercan now modify the contentInsetof scrollViewin viewDidLoadand it will be respected. However, if the contentInsetof scrollViewis UIEdgeInsetsZero: it will be expanded to topLayoutGuideand bottomLayoutGuide.

的任何子类MyViewController现在可以修改contentInsetscrollViewviewDidLoad,它会受到尊重。但是,如果contentInsetofscrollViewUIEdgeInsetsZero: 它将扩展为topLayoutGuideand bottomLayoutGuide

回答by Avt

@Christopher Pickslay solution in Swift 2:

Swift 2 中的@Christopher Pickslay 解决方案:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    let topInset = topLayoutGuide.length
    inTableView.contentInset.top = topInset
    inTableView.contentOffset.y = -topInset
    inTableView.scrollIndicatorInsets.top = topInset
}

回答by Peter

Yeah - a bit annoying.

是的 - 有点烦人。

I have a nib with a single tableview within the main view, not using autolayout. There is a tabbar, navigationbar and a statusbar and the app needs to work back to 5.0. In Interface builder that neat 'see it in iOS7 and iOS6.1 side-by-side' thing works, showing the tables neatly fitting (once the iOS6/7 deltas were set properly).

我在主视图中有一个带有单个 tableview 的笔尖,不使用自动布局。有一个标签栏、导航栏和一个状态栏,应用程序需要恢复到 5.0。在界面构建器中,整洁的“在 iOS7 和 iOS6.1 中并排查看”的东西可以正常工作,显示表格整齐合适(一旦 iOS6/7 增量设置正确)。

However running on a device or simulator there was a large gap at the top of the table, which was as a result of a content inset (which pretty much matched by iOS6/7 vertical delta) that was set to zero in the nib.

然而,在设备或模拟器上运行时,表格顶部有一个很大的空白,这是由于内容插入(与 iOS6/7 垂直增量非常匹配)在笔尖中设置为零。

Only solution I got was in viewWillAppear to put in [_tableView setContentInset:UIEdgeInsetsZero].

我得到的唯一解决方案是在 viewWillAppear 中放入 [_tableView setContentInset:UIEdgeInsetsZero]。

Another ugly hack with a pretty on-screen result.....

另一个丑陋的黑客,在屏幕上显示出漂亮的结果.....

回答by carlos

[self.navigationController setNavigationBarHidden:YES animated:YES]; 

in:

在:

- (void)viewDidLoad