I am using a UIButton to represent number of notification on bar of a table that slides up/down when the button is placed. The title of the button changes dynamically to represent number of un-read notifications.
Please see partial screenshots attached.
Start Frame of Animation - Notifications showing as 2 - Correctly
End Frame of Animation - Notifications Showing as 0 - This should not change
Below is the code I am using to animate
-(IBAction) showNotifications {
if (notificationTableIsUp) {
CGRect notificationsHeaderFrame = notificationsHeader.frame;
CGRect notificationsTableFrame = notificationsTable.frame;
// Animate to pull up Notification Table
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
notificationTableIsUp = !notificationTableIsUp;
notificationsHeaderFrame.origin.y += 220;
notificationsHeader.frame = notificationsHeaderFrame;
notificationsTableFrame.origin.y += 220;
notificationsTable.frame = notificationsTableFrame;
[UIView commitAnimations];
} else {
CGRect notificationsHeaderFrame = notificationsHeader.frame;
CGRect notificationsTableFrame = notificationsTable.frame;
// Animate to pull down Notification Table
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
notificationTableIsUp = !notificationTableIsUp;
notificationsHeaderFrame.origin.y -= 220;
notificationsHeader.frame = notificationsHeaderFrame;
notificationsTableFrame.origin.y -= 220;
notificationsTable.frame = notificationsTableFrame;
[UIView commitAnimations];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
notificationTableIsUp = NO;
[self updateNotificationBadgeTo:2];
}
- (void) updateNotificationBadgeTo:(NSInteger)numberOfNotifications {
notificationBadgeButton.titleLabel.font = [UIFont boldSystemFontOfSize:14];
notificationBadgeButton.titleLabel.textColor = [UIColor whiteColor];
notificationBadgeButton.titleLabel.text = [NSString stringWithFormat:#"%d", numberOfNotifications];
}
Note that the Green bar is a UIView and Notifications is a UILabel and Round button is a UIButton all set up in IB. 0 is the initial title for the button set in IB. I am setting it to 2 in viewDidLoad.
So basic problem here is when I click on the button, the value it changing from white 2 (set in viewDidLoad) to Blue 0 (Set in IB).
How can I remove this part when I am animating the slide up/down?
Thanks
Dev.
No Solution found so far. Ended up removing this feature altogether :(
Related
I have a custom uiview that i am trying to update the frame size. I do it like this in a method once it is clicked. The method is called, and the frame value changes, however on the screen nothing happens!
if (!touched) {
GameBox *box = (GameBox *)[self.view viewWithTag:40];
[box setFrame:CGRectMake(20, 20, 100, 73)];
NSLog(#"%f", box.frame.origin.x);
markButton.enabled = NO;
guessButton.enabled = NO;
[self.view reloadInputViews];
NSLog(#"The action bar should now be hidden");
}
else if (touched) {
guessButton.enabled = YES;
markButton.enabled = YES;
[self.view reloadInputViews];
NSLog(#"The action bar should now be visible");
}
I guess you have hooked self.view to UIView in Interface Builder.
In order to change UIView frame, in Interface Builder go to File Inspector, and uncheck Use Autolayout, then in the code change the frame.
Hope this helps.
You need to set adjust the frame in the viewDidAppear (not viewDidLoad).
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
CGRect frame = self.tableView.frame;
frame.origin.y += 100.0;
frame.size.height -= 100.0;
self.tableView.frame = frame;
}
Apparently this has something to do with table views within navigation controllers.
It is because of Auto Layout, however you could do it after Auto Layout done its work or change constraints of it. If you want to do it after auto layout add following.
- (void)viewDidAppear:(BOOL)animated {
dispatch_async(dispatch_get_main_queue(), ^{
box.frame = CGRectMake(20, 20, 100, 73)];
});
[self.view reloadInputViews] is generally used for FirstResponders. I Don't have much of an idea about your customview, but I think for just settings the frame you can use:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelay:1.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
viewFrame.frame=frame;//Frame Defined by you
[UIView commitAnimations];
can give better solution if i get a look at your custom view.
I am using below code to show hide my subview:
[self.view addSubview:selectorView];
[selectorView setFrame:CGRectOffset([selectorView frame], 0, -selectorView.frame.size.height)];
viewVisible = NO;
- (IBAction)onButtonClick:(id)sender {
[self showHideView]; // Show and hide our imageView in an animated fashion}
- (void)showHideView {
if (viewVisible) { // If our imageView is on screen hide the view
[UIView beginAnimations:#"animateImageOff" context:NULL]; // Begin animation
[selectorView setFrame:CGRectOffset([selectorView frame], 0, -selectorView.frame.size.height)]; // Move imageView off screen
[UIView commitAnimations]; // End animations
viewVisible = NO;
[showHideButton setTitle:#"Show" forState:UIControlStateNormal]; // Change button title to "Show"
} else { // if our imageView is off screen show the view
[UIView beginAnimations:#"animateImageOn" context:NULL]; // Begin animation
[selectorView setFrame:CGRectOffset([selectorView frame], 0, selectorView.frame.size.height)]; // Move imageView on screen
[UIView commitAnimations]; // End animations
viewVisible = YES;
[showHideButton setTitle:#"Hide" forState:UIControlStateNormal]; // Change button title to "Hide"
}}
How can I set the subview Y-axis value in this code because when the subview gets on the screen it hides my screen header bar And I am using a button to show/hide the subview, I also want to animate that button so that when the button is clicked, button's position should also be changed along Y-axis.
Here are the screenshots for what I want
Try to bring your your header view to front in the MainView:
[self.view bringSubviewToFront:headerView];
And the image button animation you can do this:
[UIView animateWithDuration:1.0 animations:^{
CGFloat degrees = 180;
CGAffineTransform transform =
CGAffineTransformMakeRotation(degrees/180 * 3.14);
imageButton.transform = transform;
}];
I have a button on the extreme right of the cell.
Now I have a picker view which needs to be displayed on button click.
Its working fine with the following code:
-(IBAction)buttonPressed:(id)sender
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
CGAffineTransform transform = CGAffineTransformMakeTranslation(0, 200);
monthPicker.transform = transform;
[self.view addSubview:monthPicker];
[UIView commitAnimations];
}
But I searched for making picker view hide when it is visible and be shown when no picker view is present,I found out a solution for it.....added the following code to above method:
monthPicker.hidden = [monthPicker isHidden] ? NO : YES;
Now the picker view is not getting displayed on 1st attempt when I click button,but it's working perfect from 2nd attempt and later.
Any suggestions?
The answer from #Padavan should work, but if you want fading effect "in animation", hidden property does not do the job. You have to use UIView.alpha property instead. Here is my sample code for that.
- (void) viewDidLoad {
[super viewDidLoad];
/////////////////////////////////////////////////
// ... Initialize your month picker here //
/////////////////////////////////////////////////
monthPicker.alpha = 0;
[self.view addSubview:monthPicker];
}
- (void)buttonPressed:(id)sender
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
CGAffineTransform transform = CGAffineTransformMakeTranslation(0, 200);
monthPicker.transform = transform;
monthPicker.alpha = monthPicker.alpha * (-1) + 1;
[UIView commitAnimations];
}
Are monthPicker initially hidden? When method called first time. If no - it hides and you can't see it. Maybe you need set monthPicker.hidden=YES in init method.
I need to create a expandable and collapsible UIView of some sort and am not able to pay for a third party control.
This is basically how I would like it to behave:
At the top there should be a UIButton (or similar) that allows the user to toggle between expanded and collapsed.
When expanded I want to be able to place other UIView (e.g. calendar)and when collapsed the surrounding controls should move up.
Does anyone have any ideas how to implement this simply - noob here :(
Subclass a ViewController and have two methods that your button can fire like 'collapse' and 'expand', this might get you started: You can assign new selectors to UIButtons dynamically:
[button addTarget:self action:#selector(eventMethod:)
forControlEvents:UIControlEventTouchUpInside];
Code:
#define COLAPSED_HEIGHT 30
-(void)expand
{
CGRect s= [self getScrerenBoundsForCurrentOriantation];
CGRect f = self.view.frame;
f.origin.y =s.size.height-self.view.frame.size.height;
[UIView beginAnimations:#"expand" context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationFinished:finished:context:)];
self.view.frame=f;
//CHANGE YOUR EXPAND/COLLAPSE BUTTON HERE
[UIView commitAnimations];
self.thumbScrollerIsExpanded=YES;
}
-(void)collapseView
{
//re-factored so that this method can be called in ViewdidLoad
CGRect s= [self getScrerenBoundsForCurrentOriantation];
CGRect f = self.view.frame;
f.origin.y =(s.size.height-COLAPSED_HEIGHT);
self.view.frame = f;
self.thumbScrollerIsExpanded=NO; //thumbScrollerIsExpanded is a BOOL property
}
- (void)collapse
{
[UIView beginAnimations:#"collapse" context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationFinished:finished:context:)];
[self collapseView];
//CHANGE YOUR EXPAND/COLLAPSE BUTTON HERE
[UIView commitAnimations];
}
-(CGRect)getScrerenBoundsForCurrentOriantation
{
return [self getScrerenBoundsForOriantation:[[UIDevice currentDevice] orientation]];
}
-(CGRect)getScrerenBoundsForOriantation:(UIInterfaceOrientation)_orientation
{
UIScreen *screen = [UIScreen mainScreen];
CGRect fullScreenRect = screen.bounds; // always implicitly in Portrait orientation.
if (UIInterfaceOrientationIsLandscape(_orientation))
{
CGRect temp;
temp.size.width = fullScreenRect.size.height;
temp.size.height = fullScreenRect.size.width;
fullScreenRect = temp;
}
return fullScreenRect;
}
- (void)animationFinished:(NSString *)animationID finished:(BOOL)finished context:(void *)context
{
if ([animationID isEqualToString:#"expand"])
{
//example
}
else if ([animationID isEqualToString:#"collapse"])
{
//example
}
}
You could try adding a UIView (either in xib or programmatically) off screen, then use a UIView animation to slide it into your main viewing area.
The button would have an IBAction which would toggle the animation (slide in/slide out). You can slide it off screen then set UIView's hidden property to true. When you recall the IBAction, have it check if the view's hidden property is true. If it is, you know to play the animation of it sliding in, if not, then you play the animation of sliding out.
I've a serious problem, and I cannot solve it by myself. I've spent hours searching the documentations, programming guides as well as developer forums and stack overflow.
The problem is I want to display a picker view in UITableViewController. I have a screen that has multiple text fields allowing me to search by title/author/keywords... and I'd also like to specify the minimum and maximum dates, using the UIDatePicker (or UIPickerView - to specify "last 5 days" for example).
I want to use UITableViewController because it saves me a lot of time resizing the table while the keyboard pops up when user presses the text field. In fact I've never been able to reproduce this animation using UIViewController and listening to textfields' delegate. It was almost perfect but there were some visible disadvantages comparing to the behaviour of table if displayed using UITableViewController.
So everything's fine when there are only textfields. But what about the date fileds? I want to make it exactly like the Contacts.app by Apple when I want to add a new contact and specify the birthday. In that application the Date Picker is shown, the table is resized, switching between email/phone field and birthday works great. I could believe that the date picker is in this case the keyboard but not for typing phone/email but date because it slides in/out just like a keyboard and is replaced instantly when the keyboard/picker is opened.
How did thet accomplished it?
Or where can I find the easiest solution to reproduce it. I believe it cannot be as hard because it's very common situation.
Regards
Chris
All of that is pointless. We should deal with the inputView and inputAccessoryView, where inputView should has the picker and inputAccessoryView the toolbar.
You're going to have to create a UIWindow object, then add a view. The windowLevel property makes it higher than the statusBar, which you may or may not want.
//statusWindow is a UIWindow ivar declared in the header
//pickerShowing is declared as a BOOL in header
//release and removeFromSuperview is done in the animation delegate methods
//ANIMATE IN
-(void)slideIn {
CGRect pickerFrame = CGRectMake(0.0f, 0.0f, 320.0f, 200.0f); //guessing on height
UIView *viewForPicker = [[UIView alloc] init];
UIPickerView *aPicker = [[UIPickerView alloc] init]; //don't forget to set delegate and dataSource
viewForPicker.frame = pickerFrame;
statusWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0.0, 480.0, 320.0f, 200.0f)];//guessing on height, y value is off the screen (bottom)
statusWindow.windowLevel = UIWindowLevelStatusBar;
statusWindow.hidden = NO;
statusWindow.backgroundColor = [UIColor clearColor];
[statusWindow makeKeyAndVisible];
[viewForPicker addSubview:aPicker];
[statusWindow addSubview:viewForPicker];
[viewForPicker release];
[aPicker release];
[UIView beginAnimations:#"slideUp" context:nil];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationFinished:)];
statusWindow.frame = CGRectMake(0.0f, 200.0f, 320.0f, 200.0f); //guessing on y and height values, change them to suit needs
[UIView commitAnimations];
pickerShowing = YES;
}
//ANIMATE out:
-(void)slideOut {
[UIView beginAnimations:#"slideDown" context:nil];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationFinished:)];
statusWindow.frame = CGRectMake(0.0f, 480.0f, 320.0f, 200.0f);
[UIView commitAnimations];
pickerShowing = NO;
}
-(void)animationFinished:(NSString *)name {
if ([name isEqualToString:#"slideDown"]) {
[statusWindow release];
}
}
If you want to slide in/out the picker view, you can use Core Animation.
Simplest snippet:
// Slide picker view in
[UIView beginAnimations: #"SlideIn" context: nil];
myPickerView.frame = upFrame;
[UIView commitAnimations];
// ...
// Slide picker view out
[UIView beginAnimations: #"SlideOut" context: nil];
myPickerView.frame = downFrame;
[UIView commitAnimations];
upFrame and downFrame are CGRect you make with the right position for your picker view on screen and off screen respectively.
Hope this helps.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *targetCell = [tableView cellForRowAtIndexPath:indexPath];
self.pickerView.date = [self.dateFormatter dateFromString:targetCell.detailTextLabel.text];
// check if our date picker is already on screen
if (self.pickerView.superview == nil)
{
[self.view.window addSubview: self.pickerView];
// size up the picker view to our screen and compute the start/end frame origin for our slide up animation
//
// compute the start frame
CGRect screenRect = [[UIScreen mainScreen] applicationFrame];
CGSize pickerSize = [self.pickerView sizeThatFits:CGSizeZero];
CGRect startRect = CGRectMake(0.0,
screenRect.origin.y + screenRect.size.height,
pickerSize.width, pickerSize.height);
self.pickerView.frame = startRect;
// compute the end frame
CGRect pickerRect = CGRectMake(0.0,
screenRect.origin.y + screenRect.size.height - pickerSize.height,
pickerSize.width,
pickerSize.height);
// start the slide up animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
// we need to perform some post operations after the animation is complete
[UIView setAnimationDelegate:self];
self.pickerView.frame = pickerRect;
// shrink the table vertical size to make room for the date picker
CGRect newFrame = self.tableView.frame;
newFrame.size.height -= self.pickerView.frame.size.height;
self.tableView.frame = newFrame;
[UIView commitAnimations];
// add the "Done" button to the nav bar
self.navigationItem.rightBarButtonItem = self.doneButton;
}
}
- (void)slideDownDidStop
{
// the date picker has finished sliding downwards, so remove it
[self.pickerView removeFromSuperview];
}
- (IBAction)dateAction:(id)sender
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
cell.detailTextLabel.text = [self.dateFormatter stringFromDate:self.pickerView.date];
}
- (IBAction)doneAction:(id)sender
{
CGRect screenRect = [[UIScreen mainScreen] applicationFrame];
CGRect endFrame = self.pickerView.frame;
endFrame.origin.y = screenRect.origin.y + screenRect.size.height;
// start the slide down animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
// we need to perform some post operations after the animation is complete
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(slideDownDidStop)];
self.pickerView.frame = endFrame;
[UIView commitAnimations];
// grow the table back again in vertical size to make room for the date picker
CGRect newFrame = self.tableView.frame;
newFrame.size.height += self.pickerView.frame.size.height;
self.tableView.frame = newFrame;
// remove the "Done" button in the nav bar
self.navigationItem.rightBarButtonItem = nil;
// deselect the current table row
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
You can download a full working sample app from Apple demonstrating just this.
http://developer.apple.com/library/ios/#samplecode/DateCell/Introduction/Intro.html