Question

I basically have a Master-Detail style app that uses a PageViewController in the DetailViewController. The PageViewController has three different scenes. Depending on the current scene I am setting different rightBarButtonItems in each of the three. Two of the scenes only have one rightBarButtonItem, but one of the scenes uses two.

If the user scrolls fully from one page to the next there is no issue. However if the user only scrolls part way in the direction of the rightBarButton items and lets the screen pop back, only one of the bar button items will appear.

According to the Apple documentation:

If there is not enough room to display all of the items in the array, those that would overlap the title view (if present) or the buttons on the left side of the bar are not displayed.

This explains what is happening. When the view loads the buttons it must perform a check of the frame size available for the buttons. The controller sees the buttons will overlap the title and therefore eliminates one. I simply need to delay when the buttons appear or something of this nature. Does anyone have any ideas on how to overcome this?

Here is how I have the buttons declared in viewDidLoad of the DetailViewController

//Generate buttons 
    barButton = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
    [barButton setImage:[UIImage imageNamed:@"arrow-up.png"]];

    barButton2 = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
    [barButton2 setImage:[UIImage imageNamed:@"arrow-down.png"]];

The buttons are then passed into the required viewController and displayed in viewDidAppear.

- (void) viewDidAppear:(BOOL)animated
{
    //downButton and upButton are set from barButton and barButton2 which were created in the `DetailViewController`

    [upButton setTarget:self];
    [downButton setTarget:self];
    [downButton setAction:@selector(action1)];
    [upButton setAction:@selector(action2)];

    navItem.rightBarButtonItems = @[downButton, upButton];
}

Here is some images to see the before and after

BeforePic

AfterPic

Was it helpful?

Solution

Well I stumbled upon this work around. It isn't perfect but it has the desired effect. If someone has a more sound solution please volunteer your thoughts and I'll accept your answer over mine.

I got the idea from the accepted answer to this question: Placing a custom view based UIBarButtonItem in the navigation bar without default horizontal padding

I have simply added a new bar button item that acts as a spacer.

- (void) viewDidAppear:(BOOL)animated
{
    // Create a spacer to go to the right of our custom button,

    UIBarButtonItem *zeroSpacer = [[UIBarButtonItem alloc]
                                   initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
                                   target:nil action:nil];
    zeroSpacer.width = 0;

    [upButton setTarget:self];
    [downButton setTarget:self];
    [downButton setAction:@selector(action1)];
    [upButton setAction:@selector(action2)];

    navItem.rightBarButtonItems = @[zeroSpacer, downButton, upButton];

}

I also did some work in the creation of the buttons to get them a little closer together for aesthetic reasons.

Here is how I am generating the buttons in viewDidLoad of the DetailViewController. The numbers in UIEdgeInsetsMake really don't make that much sense to me but I just messed around until they looked right.

barButton = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
[barButton setImage:[UIImage imageNamed:@"arrow-up.png"]];
barButton.imageInsets = UIEdgeInsetsMake(0.0, -10, 0, -40);

barButton2 = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
[barButton2 setImage:[UIImage imageNamed:@"arrow-down.png"]];
barButton2.imageInsets = UIEdgeInsetsMake(0.0, -10, 0, 5);

Here is the result of before and after the partial scroll swipe.

BeforePic1

AfterPic1

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top