I'm trying to flip the UIBarButtonItem in a navigation bar like Apple does in the iPod app to switch between track listings and album art.
I've dragged a button onto my navigation bar in interface builder which as I understand inserts a UIBarButtonItem with the button as its customView.
I'm using the following method to flip the button's customView but it ends up flipping the entire navigation bar!
I was hoping it was a weird emulator glitch but it's also happening on device.
Has anyone encountered this or see where I might be going wrong?
[UIView transitionFromView:self.mapToggleBarButton.customView
toView:self.mapToggleBarButton.customView
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromLeft completion:^(BOOL finished) {
}];
Turns out that this is exactly the expected behavior for UIView.transitionFromView and UIView.transitionWithView ...
The animation is applied to the superview of the object that you're swapping between. You don't have to have a reference to it or anything - just a plain UIView to enclose the button and the flip should work as expected!
I've written a little about it here: http://mathewsanders.com/animations-in-swift-part-two/
In your code, the fromView seems the same as the toView and that's why no animation. For example:
UIBarButtonItem *refresh = self.navigationItem.rightBarButtonItem;
UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"On.png"]];
[UIView transitionFromView:((UIButton*)refresh.customView).imageView toView:imgView duration:1 options:UIViewAnimationOptionTransitionFlipFromLeft completion:^(BOOL finished) {
//
UIButton *btn = ((UIButton*)refresh.customView);
[btn setImage:[UIImage imageNamed:#"On.png"] forState:UIControlStateNormal];
[btn addTarget:self action:#selector(tap:) forControlEvents:UIControlEventTouchUpInside];
}];
Remember after flip animation, you should reset the UIButton, such as image, action and so on.
Related
I am trying to add a custom bar button to my project and I'm having a few problems. First lets go over the requirement for my button, it needs:
- to display a custom font
- to be enabled/disabled
- to have its colour animated based to provide user feedback.
So I first tried connecting a barButtonItem up through the storyboard and I could change the colour and enable disable it. However I could not change the font or add colour animation to it. I want to be able to use the following method which I am already using in the app to animate the colour:
- (void)textFlashTextfieldAnimation:(nonnull UITextField *)view duration:(NSTimeInterval)duration animateToColour:(UIColor*)animationColour textColor:(UIColor*)textColour completion:(void (^)(BOOL finished))completion {
[UIView transitionWithView:view duration:0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
view.textColor = animationColour;
} completion:^(BOOL finished) {
[UIView transitionWithView:view duration:2.0f options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
view.textColor = textColour;
} completion:completion];
}];
}
Ideally I would be able to change this function to accept a barButtonItem / UIButton so that I could animate it easily. However if I connect the button up through storyboards I cannot access the button's layer so the animation is not possible.
I had started to go about this through code but I've gone down 2 dead ends. Here is a really basic implementation of a barButtonItem:
UIBarButtonItem *myButton=[[UIBarButtonItem alloc] initWithTitle:#"My Custom Button" style:UIBarButtonItemStylePlain target:self action:#selector(/*do something*/)];
[self.navigationItem setRightBarButtonItem:myButton];
Now this will work in the fact that I can use it like a storyboard button however I cannot alter the font or access the button's layer so it is also no good.
I then tried creating a fully custom view for my bar button by creating a UIView and a UIButton and then adding them to a barButtonItem, this can be seen here:
UIFont *barButtonFonts = [UIFont fontWithName:kFont size:16];
//Right Button
//create view
UIView *rightButtonView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 45, 25)];
//create button
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeSystem];
rightButton.backgroundColor = [UIColor clearColor];
rightButton.frame = rightButtonView.frame; //set frame = to view
[rightButton setTitle:NSLocalizedString(#"Save", nil) forState:UIControlStateNormal];
rightButton.titleLabel.font = barButtonFonts;
rightButton.tintColor = [UIColor redColor];
[rightButton addTarget:self action:#selector(actionMethod) forControlEvents:UIControlEventTouchUpInside];
[rightButtonView addSubview:rightButton];
UIBarButtonItem *rightBarButton = [[UIBarButtonItem alloc] initWithCustomView:rightButtonView];
self.navigationItem.rightBarButtonItem = rightBarButton;
Now I have a barButtonItem that will display a custom font however it is has no UI interaction at all. It looks the same when enabled/disabled and when not-highlighted/highlighted. The button works as it should it just doesn't look like it should.
Should I create an outlet to this button somewhere in my code so that I can alter the button when in the view? Is it even possible to alter a button after it has been added to the navigation bar?
If anybody has any suggestions it would be appreciated!
Yeah barbuttonitem isn't modifieable after you added it to the bar. only way i can think is to remove the button and add a new one (with the new characteristics) when user interact with it. I suggest you to use a custom toolbar (like a normal UIView), then add a normal button to it. it would be easier to customize
When I change my UIBarButtonItems they change abruptly, unlike the default which gives a nice but speedy fade animation. You can see this when segueing between view controllers, for instance, the back button will fade in and out. How can I simulate the same effect?
Update - Based on this answer - https://stackoverflow.com/a/10939684/2649021
It looks like you would have to do something like this to make the button itself fade out.
[self.navigationItem setRightBarButtonItem:nil animated:YES];
And do something like this to make it fade in
[self.navigationItem setRightBarButtonItem:myButton animated:YES];
Otherwise if you want more control over animation properties you would have to create a custom view I believe.
EDIT: I just confirmed that you can fade a UIBarButtonItem custom view using this.
As a test I created a simple project and dropped a UIBarButtonItem onto the navigation bar. I created an outlet to the view controller. In viewDidLoad on the view controller I setup a custom view
-(void)viewDidLoad{
[super viewDidLoad];
UILabel *lbl = [[UILabel alloc]initWithFrame:CGRectMake(0,0,40,40)];
lbl.text = #"test";
UIView *customView = [[UIView alloc]initWithFrame:CGRectMake(0,0,40,40)];
[customView addSubview:lbl];
self.barButtonItem.customView = customView;
}
As a test in viewDidAppear I animated it
-(void)viewDidAppear:(BOOL)animated
{
[UIView animateWithDuration:3.0
delay:3.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
self.barButtonItem.customView.alpha = 0;
}
completion:^(BOOL finished) {
NSLog(#"animation complete");
}];
EDIT: Here's a link to Apples Documentation for a full explanation of UIView animations.
https://developer.apple.com/library/ios/documentation/windowsviews/conceptual/viewpg_iphoneos/animatingviews/animatingviews.html
You might have to create a custom bar button item using a view or an image, and then animate the properties of the view as digitalHound shows.
Do any of you know how I could possibly add an animation that is triggered when a UIButton is pressed, and the UIButton turns aand enlarges at the same time, and on the other side I can show another view? A bit like in dashboard on a Mac, with the info button on the widgets...
You can use transitions:
[UIView transitionWithView:containerView duration:1 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
buttonView.hidden = YES;
otherView1.hidden = NO;
otherView2.hidden = NO;
otherViewEtc.hidden = NO;
} completion:nil];
You would then have a containerView which contains the flip button and the alternate view hidden, and in the transition, you can hide the first view and show the alternate view...
I have a case where I need to open a new UIViewController on IBAction. This new UIViewController is supposed to be transparent. When I do a normal modal transition it hides the old UIViewController. Any suggestions on this?
For your purposes you will want to tell your modal View Controllers view property to change alpha. (best done in the view controllers viewDidLoad)
It's as simple as:
- (void) viewDidLoad
{
[self.view setAlpha:0.5];
}
Now, the other approach would be to just use a new UIView added as a subview of your main view controller. The following will show your how to animate it in.
UIView *myNewView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
[myNewView setAlpha:0.0];
[self.view addSubview:myNewView];
[UIView animateWithDuration:1.5 animations:^{
[myNewView setAlpha:0.5];
}];
EDIT: To change the alpha of the background view and preserve the alpha of its subviews, try setting it up like this.
[myNewView setBackgroundColor:[[UIColor blueColor] colorWithAlphaComponent:0.2]];
[myNewViewsSubView setBackgroundColor:[[UIColor redColor] colorWithAlphaComponent:1.0]];
How can I develop a toolbar like this one, with a button that when it's pressed reveals another toolbar (sliding on top of the current one)? This is a screenshot from the iPhoto application from Apple.
http://i.stack.imgur.com/dKYZq.png
I got this to work using the following (Disclaimer: THIS MAY VIOLATE THE HIG!):
I added a new, basic UIViewController.
I added a UIToolbar to the view of the UIViewController. I connected this UIToolbar to a property in my UIViewController named "BaseToolbar".
To "BaseToolbar", I added a button. I connected this button to an IBAction called "AddPressed:" in my UIViewController.
I added a UIToolbar to the UIViewController's xib, BUT NOT ON THE UIViewController's view. I just added it onto the design surface. I connected this UIToolbar to a property in my UIViewController named "SecondToolbar".
To "SecondToolbar", I added a button. I connected this button to an IBAction called "TrashPressed:" in my UIViewController.
I used the following code:
- (IBAction)AddPressed:(id)sender {
CGRect secondCurrRect = [[self SecondToolbar] frame];
[[self SecondToolbar] setFrame:CGRectMake(0, -1 * secondCurrRect.size.height, secondCurrRect.size.width, secondCurrRect.size.height)];
[[self view] addSubview:[self SecondToolbar]];
[[self view] bringSubviewToFront:[self SecondToolbar]];
[UIView animateWithDuration:1.0
animations:^(void){
[[self SecondToolbar] setFrame:CGRectMake(0, 0, secondCurrRect.size.width, secondCurrRect.size.height)];
}];
}
- (IBAction)TrashPressed:(id)sender {
CGRect secondCurrRect = [[self SecondToolbar] frame];
[UIView animateWithDuration:1.0
animations:^(void){
[[self SecondToolbar] setFrame:CGRectMake(0, -1 * secondCurrRect.size.height, secondCurrRect.size.width, secondCurrRect.size.height)];
}
completion:^(BOOL finished) {
[[self SecondToolbar] removeFromSuperview];
}];
}
Using that code, the new UIToolbar slides on/off ON TOP OF the "base" UIToolbar.
Edit/Update
Let's try a different tactic.
(This assumes you're adding the UIToolbar objects to your xib at design time)
Add Toolbar #1 (the one that is always on-screen) to the top of the view and position it like you want.
Add Toolbar #2 (the one that slides on/of) underneath Toolbar #1 and build it out with the buttons you want.
Put the following line of code into your -(void)viewDidLoad method (this will move the second toolbar off-screen):
[[self Toolbar2] setFrame:
CGRectMake(0, // origin.x
-[[self Toolbar2] frame].size.height, // origin.y
[[self Toolbar2] frame].size.width, // size.width (remains the same)
[[self Toolbar2] frame].size.height) // size.height (remains the same)
];
Then, use the code from above, but skip the calls to addSubview: and removeFromSuperview.
Does that make sense now?