How align 2 uibuttons programmatically in a layout? - constraints

I use the KLCPopup library to display a popup in my app.
I have to add 2 buttons horizontally on the bottom of this popup, like the standard iOS UIAlerView. I cannot align this two buttons horizontally.
Here is the result I want:
But here is the result I have:
Here is the code I use to create this popup:
UIView* contentView = [[UIView alloc] init];
contentView.translatesAutoresizingMaskIntoConstraints = NO;
UILabel* dismissLabel = [[UILabel alloc] init];
dismissLabel.translatesAutoresizingMaskIntoConstraints = NO;
dismissLabel.numberOfLines = 0;
[dismissLabel setTextAlignment:NSTextAlignmentCenter];
dismissLabel.lineBreakMode = NSLineBreakByWordWrapping;
dismissLabel.preferredMaxLayoutWidth = 200;
UIButton* dismissButton = [UIButton buttonWithType:UIButtonTypeCustom];
dismissButton.translatesAutoresizingMaskIntoConstraints = NO;
dismissButton.contentEdgeInsets = UIEdgeInsetsMake(10, 20, 10, 20);
[contentView addSubview:dismissLabel];
[contentView addSubview:dismissButton];
UIButton* cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
cancelButton.translatesAutoresizingMaskIntoConstraints = NO;
cancelButton.contentEdgeInsets = UIEdgeInsetsMake(10, 20, 10, 20);
[contentView addSubview:cancelButton];
NSDictionary* views = NSDictionaryOfVariableBindings(contentView, dismissButton, cancelButton, dismissLabel);
[contentView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-(16)-[dismissLabel]-(16)-[dismissButton]-(16)-[cancelButton]-(16)-|"
options:NSLayoutFormatAlignAllCenterX
metrics:nil
views:views]];
[contentView addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(18)-[dismissLabel]-(18)-|"
options:0
metrics:nil
views:views]];
// Show in popup
KLCPopupLayout layout = KLCPopupLayoutMake(KLCPopupHorizontalLayoutCenter,
KLCPopupVerticalLayoutCenter);
KLCPopup* popup = [KLCPopup popupWithContentView:contentView
showType:KLCPopupShowTypeFadeIn
dismissType:KLCPopupDismissTypeGrowOut
maskType:KLCPopupMaskTypeDimmed
dismissOnBackgroundTouch:NO
dismissOnContentTouch:NO];
[popup showWithLayout:layout];
I think the problem on my code is the constraint.I've tried many possibilities but I cannot find the right way to do this.
Any advice will be helpful!
Thanks

You've added all three views to the vertical constraint and that's why they are all one after another. Do something like this:
V:|-16-[dismissLabel]
V:|-80-[dismissButton]
V:|-80-[cancelButton]
H:|-18-[dismissLabel]-18-|
H:[dismissButton(50)]-100-[cancelButton(50)]
I haven't tested it but something like that could work. You might have to modify the last H value or maybe add a centering option to it. There are probably better ways where you could group some of those things but this should work too.

Related

NSLayoutConstraint for view on UITableView

I have a UIViewController with a UITableView as well as a UIView that is above the UITableView but aligned to the bottom of the screen. Problem is when the user is on a phone call, the frame settings don't work, and the UIView is pushed below the screen (so it is slightly covered. I'm trying to just align the UIView to the view bottom and simply not getting it to align. I have the constraints defined as below:
[self.view addSubview:self.signupView];
[self.view addSubview:self.tableView];
[self.view bringSubviewToFront:self.signupView];
NSArray *v = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_signupView(70)]-0-|"
options:NSLayoutFormatAlignAllBaseline
metrics:nil
views:NSDictionaryOfVariableBindings(_signupView)];
NSArray *h = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[_signupView]|"
options:NSLayoutFormatAlignAllBottom
metrics:nil
views:NSDictionaryOfVariableBindings(_signupView)];
[self.view addConstraints:h];
[self.view addConstraints:v];
The height of signupView is 70, and it should just be aligned at the bottom of the screen with the width of the entire screen. The above code is putting the view at the top of the view. Is there something i'm missing here? Why is it not aligning with the bottom as I put above? I tried to read the below on this:
http://commandshift.co.uk/blog/2013/01/31/visual-format-language-for-autolayout/
http://makeapppie.com/2014/07/26/the-swift-swift-tutorial-how-to-use-uiviews-with-auto-layout-programmatically/
Use autolayout to set dynamic UIView to match container view
Figured it out.
Here is the below that worked for me:
NSArray *v = [NSLayoutConstraint constraintsWithVisualFormat:#"V:[_signupView(70)]-0-|"
options:NSLayoutFormatAlignAllBaseline
metrics:nil
views:NSDictionaryOfVariableBindings(_signupView)];
NSArray *h = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[_signupView]|"
options:NSLayoutFormatAlignAllBottom
metrics:nil
views:NSDictionaryOfVariableBindings(_signupView)];
[self.view addConstraints:h];
[self.view addConstraints:v];

After Taking Picture cannot select Use Photo or Retake

So I'm trying to update an app for iOS 7 and I'm running into issues with my custom overlay. The overlay is an image that I'm framing the photo with (both live and using a full resolution version to frame the final result in the camera roll). The problem is that now, under iOS 7, the overlay, while transparent at the bottom, provides access to the regular "take picture" button, but for some reason will not let me tap on the "Use Photo" or "Retake" buttons that come up after the picture is snapped. Here's the code snippet calling the view controller:
- (IBAction)takePhoto:(UIButton *)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = NO;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.showsCameraControls = YES;
// Overlay Creation
UIView* overlayView = [[UIView alloc] initWithFrame:picker.view.frame];
overlayView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"PBOverlayView.png"]];
[overlayView.layer setOpaque:NO];
overlayView.opaque = NO;
picker.cameraOverlayView = overlayView;
[self presentViewController:picker animated:YES completion:NULL];
}
Another approach could be to observe the notifications when the ImagePicker changes state and remove (or disable) your overlay when you move into the "Use Photo" screen.
- (void) addPhotoObservers {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(removeCameraOverlay) name:#"_UIImagePickerControllerUserDidCaptureItem" object:nil ];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(addCameraOverlay) name:#"_UIImagePickerControllerUserDidRejectItem" object:nil ];
}
- (void) removePhotoObservers {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(void)addCameraOverlay {
if (self.cameraPicker) {
self.cameraPicker.cameraOverlayView = self.myCameraOverlayView;
}
}
-(void)removeCameraOverlay {
if (self.cameraPicker) {
self.cameraPicker.cameraOverlayView = nil;
}
}
You could set User Enteraction Enabled to NO on Overlay View ;) works for me
Your problem: When you initialised the overlayView, you've set the frame to be the same size as that of the picker.
UIView* overlayView = [[UIView alloc] initWithFrame:picker.view.frame];
Explanation: Before capturing an image, the camera buttons are in the foreground of the overlayView, so that there's no issue pressing them.
After capturing an image (on the "retake/use preview page"), the overlayView is the one to be in the foreground, thus blocking the access to the buttons.
I know this to be an issue on iOS7, and not sure about other versions.
Possible solutions: Since this is a native problem within Apple's UIImagePickerController, I can only think of two solutions: (1) If possible, configure the overlayView to have a shorter frame which doesn't cover the bottom of the picker; (2) If you need the overlay to cover these buttons, you still have the exhausting option of configuring self.imagePicker.showsCameraControls = NO; but then you'd have to customize ALL of the camera behaviour (you can find many examples for that on the web).
After taking a photo, or animation on your overlay is done, i made it work by removing the overlay from its superview.
[UIView animateWithDuration:1
delay:1
options:UIViewAnimationOptionCurveEaseOut
animations:^{
} completion:^(BOOL finished) {
[self.view removeFromSuperview];
}];

UILabel double text

I'm creating a UILabel this way and it works just fine the first time..
CGRect labelFrame = CGRectMake(98, 286, 600, 180);
UILabel *lblQuestionTitle = [[UILabel alloc] initWithFrame:labelFrame];
[lblQuestionTitle setBackgroundColor:[UIColor clearColor]];
[lblQuestionTitle setFont: [UIFont fontWithName:#"Helvetica" size:17.0]];
[lblQuestionTitle setText:labelText];
[lblQuestionTitle setNumberOfLines:0];
[lblQuestionTitle sizeToFit];
[self.view addSubview:lblQuestionTitle];
The problem is when I use this code later, the new text appears over the old text.. How can I fix this?
Instead of reusing the code, simply overwrite the Label text.
[lblQuestionTitle setText:#"New label text!"];
If you really want an entire new button, simply set lblQuestionTitle to hidden before adding the new label
[lblQuestionTitle hidden:YES];

UINavigationItem multiple line prompt text

Can any body give me the solution for displaying UINavigationItem prompt text in 2 lines?
There is not a built-in way to do this. Below is a work-around that seems to work pretty well that I put together from stackOverflow post UINavigationItem with prompt and activity indicator
Here is a simulator screen shot of what it creates:
Note that since the text is a UILabel you can modify its color, font, or anything else too.
// I have this code in viewDidLoad
UIView *viewContainingPrompt;
UIBarButtonItem *promptButtonItem;
// Configuring the prompt title of the navigation bar so it is present but empty
[self.navigationItem setPrompt: #""];
// We will create a UIBarButtonItem that has a custom view (viewContainingPrompt).
// A subview of viewContainingPrompt will be a UILabel (headerLabel)
// We need to have this "intermediate" view to position the label at the right position
// (the UIBarButtonItem ignores the origin and height of its custom view)
viewContainingPrompt = [[UIView alloc] initWithFrame: CGRectMake(0, 0, 0, 85)];
viewContainingPrompt.autoresizingMask = UIViewAutoresizingFlexibleWidth;
// Choose a width that puts 10 points on either end...
CGFloat labelWidth = self.navigationController.navigationBar.bounds.size.width - 20.0;
// Note that the '-60' below is determined by the width of the back button
// If someone can figure out how to determine this width at runtime this code
// would be much more robust.
UILabel *headerLabel = [[UILabel alloc] initWithFrame: CGRectMake(-60,-8,labelWidth,36)];
headerLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
headerLabel.text = #"A quite long prompt string that will wrap to a second line to demonstrate multiline prompt.";
headerLabel.font = [UIFont systemFontOfSize: 14];
headerLabel.numberOfLines = 0; // Zero gives as many lines as will fit, could be 2
headerLabel.backgroundColor = [UIColor clearColor];
headerLabel.textColor = [UIColor colorWithRed: .1 green: .1 blue: .2 alpha: 0.8f];
headerLabel.shadowColor = [UIColor colorWithRed: 1 green: 1 blue: 1 alpha: 0.5f];
headerLabel.shadowOffset = CGSizeMake( 0, 1 );
headerLabel.textAlignment = UITextAlignmentCenter;
[viewContainingPrompt addSubview: headerLabel];
//[headerLabel release]; // Uncomment if not using ARC
promptButtonItem = [[UIBarButtonItem alloc] initWithCustomView: viewContainingPrompt];
self.navigationItem.leftBarButtonItem = promptButtonItem;
self.navigationItem.leftItemsSupplementBackButton = YES;
//[viewContainingPrompt release]; // Uncomment if not using ARC
//[promptButtonItem release]; // Uncomment if not using ARC
I would appreciate anyone's feedback on how to figure out the width of the back button during execution so that width did not have to be hard coded.
As it is I do not think there are any private APIs or other illegal code contained.

Sharekit customise modelview button colour

Lovin' Sharekit
Have custom backgrounds happening for the toolbars, but want to change the button colour in the modal view that displays which link to share (ie the Twitter link model view)...just can't find which file to add my customise nav bar button bar code to
Been trying but can't seem to find right combo... anyone know?
- (void)viewDidLoad
{
[super viewDidLoad];
/*
Colour the Nav Bar buttons
*/
[self.navigationController.navigationBar applyCustomTintColor];
}
In SHKConfig.h
Amend
#define SHKBarTintColorRed 219 /255.0
#define SHKBarTintColorGreen 83 /255.0
#define SHKBarTintColorBlue 106 /255.0
Add / 255.0 to your number(s)
This pre-divides our RGB color into the floating point percentage for a UIColor
In SHK.m
Amend showViewController function
// Wrap the view in a nav controller if not already
if (![vc respondsToSelector:#selector(pushViewController:animated:)])
{
UINavigationController *nav = [[[UINavigationController alloc] initWithRootViewController:vc] autorelease];
if ([nav respondsToSelector:#selector(modalPresentationStyle)])
nav.modalPresentationStyle = [SHK modalPresentationStyle];
if ([nav respondsToSelector:#selector(modalTransitionStyle)])
nav.modalTransitionStyle = [SHK modalTransitionStyle];
nav.navigationBar.barStyle = nav.toolbar.barStyle = [SHK barStyle];
// Added code
UIColor* c = [UIColor colorWithRed:SHKBarTintColorRed green:SHKBarTintColorGreen blue:SHKBarTintColorBlue alpha:1.0];
[(UINavigationController *)vc navigationBar].tintColor = c;
// End added code
[topViewController presentModalViewController:nav animated:YES];
self.currentView = nav;
}
// Show the nav controller
else
{
if ([vc respondsToSelector:#selector(modalPresentationStyle)])
vc.modalPresentationStyle = [SHK modalPresentationStyle];
if ([vc respondsToSelector:#selector(modalTransitionStyle)])
vc.modalTransitionStyle = [SHK modalTransitionStyle];
[topViewController presentModalViewController:vc animated:YES];
[(UINavigationController *)vc navigationBar].barStyle =
[(UINavigationController *)vc toolbar].barStyle = [SHK barStyle];
// Added code
UIColor* c = [UIColor colorWithRed:SHKBarTintColorRed green:SHKBarTintColorGreen blue:SHKBarTintColorBlue alpha:1.0];
[(UINavigationController *)vc navigationBar].tintColor = c;
// End added code
self.currentView = vc;
}
This tints all navigationBar buttons (including the Cancel button)
Viola!

Resources