Domanda

My App has a Camera section which is a modally presented UINavigationController containing a AVFoundation-based CameraView as it's rootViewController. The user can browse his photo libraries as follows: A ViewController (->Master) is pushed which shows all AssetGroups in a TableView. When the user selects a group, another ViewController is pushed showing all assets in this group in a CollectionView. For the sake of screen space and 'style' i decided to hide the statusBar when the CameraSection is shown (using setStatusBarHidden:withAnimation:) This leaves the NavigationController with a NavigationBar slided up by 20px (StatusBar height).

When i show the TableView / CollectionView for the Assets browsing, i take that into account and set the conentInset, etc. for them appropriately.

This all works nice and well until the the app is sent to the background (Home - button) while showing either the TableView or the CollectionView. (will call it "ScrollView" now)

When the app re-enters the foreground, the "ScrollView" is in the right state for a very short moment before it's frame is offset by 44px downwards. (44px = the actual size of a mere navigationBar - without statusBar).

Here are some pictures to illustrate the problem:

Before entering the background (Home-button): Before entering the background

After re-entering the foreground: enter image description here

When you look closely, you can the the dark hairline at the bottom edge of the navigationBar. In the first picture, everything is aligned just right. In the second, however, the scrollView seems to have a frame offset down by 44px.

When the collectionView's contentSize is bigger than "Screen-Height" (start being scrollable), you can also see the bottom edge being too low (e.g. the last row is not fully visible + the scrollIndicator-inset is also wrong).

I already tried registering for Notifications like UIApplicationDidBecomeActiveNotification or UIApplicationDidChangeStatusBarFrameNotification and re-setting the contentInset and frame of the collectionView i the callback. Key-Value observing the collectionView frame did never callback, just as KVO the "topLayoutGuide" of the viewController.

It seems the frame is quietly changed without firing any notification or event. Strangely, when i NSLog the collectionView's frame and contentInset before and after re-entering, they show exactly the same values !?

I'm not using InterfaceBuilder at all, so everything is done in code (no AutoLayout).

I would really appreciate any kind of help regarding this problem.

For now, I'm afraid I'll have to settle for writing a custom navigationBar and hiding the navigationController's to fix that :/

  • Another issue i noticed : When you hide the statusBar, a scrollView's "scrollToTop" mechanism does no longer work. I guess the tap has to be on the status bar to kick off the scrolling, so the get that to work while hiding the statusBar, a TapGestureRecog will be necessary ?

EDIT

FYI Every ViewController i use inherits from a base class which set automagicallyAdjustScrollViewInset to NO.

È stato utile?

Soluzione

EDIT

Actually, the solution below is also not right.

I figured out it has to do with the navigationBar's translucent property. I was setting this property on and off throughout the cameraSection several times.

After keeping a steady value for this property, everything works fine.

OLD ANSWER - NOT WORKING !!

Ok this is VERY VERY ugly but i was able to overcome this issue by doing this:

In viewWillAppear:animated: , register for being notified when the app reenters the foreground.

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(applicationDidBecomeActive:)
                                             name:UIApplicationDidBecomeActiveNotification
                                           object:nil];

The callback looks like this:

- (void)applicationDidBecomeActive:(NSNotification *)notification
{
    UIEdgeInsets scrollIndicatorInset = self.collectionView.scrollIndicatorInsets;
    UIEdgeInsets contentInset = self.collectionView.contentInset;

    scrollIndicatorInset.top -= 44.0;
    scrollIndicatorInset.bottom += 44.0;

    contentInset.top -= 44.0;
    contentInset.bottom += 44.0;

    [self.collectionView setScrollIndicatorInsets:scrollIndicatorInset];
    [self.collectionView setContentInset:contentInset];

    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
}

It's important to unregister when the callback was invoked once, because otherwise the offsets would be corrupted after additional re-entering.

Certainly not a nice solution, but a solution it is :/

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top