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.

Sunday, November 25, 2012

 

Using p7zip in Multithreaded Mode to Make a .tar.xz from a Tar Stream Sent Across the Network

My laptop's CPU is slow compared to my Linux workstation's.  I store my backups on my workstation's array, so in the past, I streamed uncompressed tar output through netcat to my workstation, where I piped it through xz and into a .tar.xz file.

Doing a little research, I found that p7zip supports multithreaded xz compatible LZMA2 compression.  With a little experimenting, p7zip worked as a drop-in replacement for xz.

Command executed on the laptop: tar cvp --one-file-system --exclude=/.SWAP /efi / | netcat 192.168.0.115 61710

Command executed on the workstation:  netcat -l -p 61710 | 7z a -mmt=4 -si tektite.tar.xz.  htop running on the workstation shows that all four cores are utilized:

The resulting .tar.xz file is successfully extracted by tar -xJvf tektite.tar.xz.

Labels: , ,


Friday, November 2, 2012

 

iOS 6: Using the Grouped Table Pinstripe Background in Other Views

It took some trial and error to find a way to use the built in methods in iOS 6 to draw the grouped table style pinstriped background in views that are not tables.  In iOS 6, doing self.view.background = [UIColor groupTableViewBackgroundColor] is deprecated and, furthermore, does not work.

Duplicating the iOS 6 table pinstriping by setting a view's background to a custom pattern color would be trivial, but it won't match the style for other iOS versions.  Using Apple's drawing routine guarantees that view backgrounds will always look correct.  I accomplished this by setting my view's background to transparent and then programmatically making an empty grouped table and placing it behind everything else:

// An empty table view useful for putting last in a view's Z-order to draw the grouped table view pinstripe background
@interface S3PersonViewBackground : UITableView<UITableViewDataSource, UITableViewDelegate>
@end


@implementation S3PersonViewBackground

-(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
{
    return 0;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 0;
}

@end


//


@interface S3PersonViewController : UIViewController

@property (nonatomic, retain) S3Person* person;

@end


@interface S3PersonViewController ()
{
    // Used only for drawing the grouped table style background
    S3PersonViewBackground* backgroundDrawingView;
}
@end


@implementation S3PersonViewController

-(void)dealloc
{
    [_person release];
    [backgroundDrawingView release];
    [super dealloc];
}

-(void)viewDidLoad
{
    [super viewDidLoad];
    self.title = [NSString stringWithFormat:@"%@ %@", self.person.firstName, self.person.lastName];
    //[self.view setBackgroundColor:[UIColor groupTableViewBackgroundColor]];
    backgroundDrawingView = [[S3PersonViewBackground alloc] initWithFrame:CGRectMake(0.0, 0.0, 0.0, 0.0) style:UITableViewStyleGrouped];
    backgroundDrawingView.dataSource = backgroundDrawingView;
    backgroundDrawingView.delegate = backgroundDrawingView;
    [self.view addSubview:backgroundDrawingView];
    [self.view sendSubviewToBack:backgroundDrawingView];
}

-(void)viewDidLayoutSubviews
{
    backgroundDrawingView.frame = self.view.bounds;
}

@end

Labels: , ,


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  

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

Subscribe to Posts [Atom]