EsoErik

Tuesday, November 27, 2012

 

Centering a UIToolbar Button on iOS

I blew a couple hours figuring this out.  Hopefully it will save someone else's time.  The relevant code:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    isRotating = YES;
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    isRotating = NO;
    [self layoutToolbar];
}

- (void)viewDidLayoutSubviews
{
    _groupedTableBackground.frame = self.view.bounds;
    // If rotation is in progress, he system has not completed updating toolbar layout.  Because our adjustment of toolbar layout is based on the
    // layout made by the system, our adjustment of toolbar layout is postponed until the system indicates rotation is complete, at which point
    // the system has finished its layout.
    if(!isRotating)
    {
        [self layoutToolbar];
    }
}

- (void)layoutToolbar
{
    UIToolbar* tb = self.navigationController.toolbar;
    UIView* lb = [_saveButton valueForKey:@"view"];
    UIView* mb = [_makeCopyButton valueForKey:@"view"];
    UIView* rb = [_deleteButton valueForKey:@"view"];
    CGRect lbf = [tb convertRect:((UIView*)lb.subviews[0]).frame fromView:lb];
    CGRect mbf = [tb convertRect:((UIView*)mb.subviews[0]).frame fromView:mb];
    CGRect rbf = [tb convertRect:((UIView*)rb.subviews[0]).frame fromView:rb];
    CGRect tbb = tb.bounds;
    CGFloat lspacerCur = _leftCenteringSpacer.width;
    // The right edge of the left button
    CGFloat lbr = lbf.origin.x + lbf.size.width;
    // The distance the system leaves from the edge of a button aligned directly against the side of the toolbar
    CGFloat edgeBorder = lbf.origin.x;
    // The distance the system leaves between adjacent buttons aligned directly against each other
    CGFloat border = mbf.origin.x - lbr - lspacerCur - tbb.origin.x;
    // The width of the bar button item fixed space control between the left and middle buttons required order to center the middle button
    CGFloat lspacer = floorf(tbb.size.width / 2 - lbr - border - mbf.size.width / 2);
    if(lspacer < 0)
    {
        lspacer = 0;
    }
    else
    {
        // The width that the system will assign to the bar button item flexible space control between the middle and right buttons
        // after the width of the fixed space control to the left of the middle button has been set and the toolbar's layout method is
        // called.  We calculate this in order to ensure that centering does not cause the middle button to overlap the right button.
        CGFloat rspacer = (tbb.size.width - rbf.size.width - border - edgeBorder) - (lbr + border + lspacer + mbf.size.width);
        if(rspacer < 0)
        {
            lspacer = 0;
        }
    }
    if(lspacer != lspacerCur)
    {
        _leftCenteringSpacer.width = lspacer;
        [tb layoutSubviews];
    }
}
A UIViewController using this code to center the Make Copy button:
Without the centering code, the Make Copy button would be off-center to the right.  Note that I center the middle button by adjusting the width of a fixed space toolbar item placed between the left and middle buttons.  A flexible space toolbar item placed between the middle and right buttons keeps the right button aligned against the right edge of the toolbar.
Comments:

Post a Comment

Subscribe to Post Comments [Atom]





<< Home

Archives

July 2009   August 2009   September 2009   October 2009   November 2009   December 2009   January 2010   September 2010   December 2010   January 2011   February 2011   April 2011   June 2011   August 2011   February 2012   June 2012   July 2012   August 2012   October 2012   November 2012   January 2014   April 2014   June 2014   August 2014   September 2014   October 2014   January 2015   March 2015   April 2015   June 2015   November 2015   December 2015   January 2016   June 2016   August 2016   January 2017   March 2017   April 2018   April 2019   June 2019   January 2020  

This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]