Adding a TabBarController as the Subview of a View - cocoa-touch

I am loading a splash screen when my app starts. Then I want to load a TabBarController and it's ViewControllers. However, my TabBarController window does not scale to the screen size.
Probably 3/4 of the TabBar at the bottom is getting cut off and There is a slim aprox 20 pixel gap at the top of the screen below the status bar. How do I resize the TabBarController properly?
Here is the code in my SplashViewController loading the splash view, and the TabBarController:
-(void)loadView{
// Init the view
CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
UIView *view = [[UIView alloc] initWithFrame:appFrame];
view.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
self.view = view;
[view release];
splashImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Splash.png"]];
splashImageView.frame = CGRectMake(0,0,320,458);
[self.view addSubview:splashImageView];
viewController = [[FlashCardViewController alloc] initWithNibName:#"FlashCardViewController" bundle:[NSBundle mainBundle]];
//viewController.view.bounds = [[UIScreen mainScreen]bounds];
viewController.title = #"Quiz";
viewController.tabBarItem.image = [UIImage imageNamed:#"puzzle.png"];
UIViewController *viewController2 = [[UIViewController alloc] initWithNibName:nil bundle:nil];
viewController2.title = #"Nada";
viewController2.tabBarItem.image = [UIImage imageNamed:#"magnifying-glass.png"];
//viewController.view.alpha = 0.0;
//[self.view addSubview:viewController.view];
tabBarController = [[UITabBarController alloc] init];
tabBarController.viewControllers = [NSArray arrayWithObjects:viewController, viewController2, nil];
[viewController2 release];
tabBarController.view.alpha = 0.0;
//tabBarController.tabBarItem.image = [UIImage imageNamed:#"State_California.png"];
//tabBarController.tabBarItem.title = #"State_California.png";
tabBarController.view.bounds = [[self view] bounds];
//tabBarController.view.frame = [[UIScreen mainScreen] applicationFrame];
[self.view addSubview:tabBarController.view];
timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(fadeScreen) userInfo:nil repeats:NO];
}
-(void) fadeScreen
{
[UIView beginAnimations:nil context:nil]; // begin animation block
[UIView setAnimationDuration:0.75]; // sets animation duration
[UIView setAnimationDelegate:self]; // sets the delegate for this block
[UIView setAnimationDidStopSelector:#selector(finishedFading)]; // Calls finishFading
self.view.alpha = 0.0; // // Fades the alpha to 0 over animation
[UIView commitAnimations]; // Commits this block, done
}
-(void) finishedFading
{
[UIView beginAnimations:nil context:nil]; // Begin animation block
[UIView setAnimationDuration:0.75]; // set duration
self.view.alpha = 1.0; // fades the view to 1.0 alpha over .75 seconds
//viewController.view.alpha = 1.0;
tabBarController.view.alpha = 1.0;
[UIView commitAnimations];
[splashImageView removeFromSuperview];
}

I've just completed pretty much the same and ran into the same problems but eventually I got it working.
Create a View Controller class in Xcode called Test1ViewController and add the following:
#interface Test1ViewController : UIViewController {
IBOutlet UITabBarController *tbc;
}
#property (nonatomic,retain) IBOutlet UITabBarController *tbc;
#end
Create a View XIB called Test1View
Add a TabBarViewController to the XIB
Set the File's Owner in the XIB to be the Test1ViewController.
Connect the tbc IBOutlet in the File's Owner to the Tab Bar Controller in the XIB.
Connect the view IBOutlet in the File's Owner to the View in the XIB.
In your SplashViewController.h add the property
Test1ViewController *tabBarViewController;
Synthesize the tabBarViewController in your SplashViewController.m.
Replace your TabBarController creation code in your loadView method in SplashViewController with the following:
tabBarViewController = [[Test1ViewController alloc] initWithNibName:
#"Test1View" bundle:[NSBundle mainBundle]];
tabBarViewController.view.alpha = 0.0;
[self.view addSubview:[tabBarViewController view]];
Here's the bit that was missing for me. In Test1ViewController.m, you need to add the following line to the viewDidLoad method:
self.view = tbc.view;
Finally, I also had to change the finishedFading method in SplashViewController.m to set the alpha to 1.0 on the tabBarViewController view.
-(void) finishedFading
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.75];
self.view.alpha = 1.0;
tabBarViewController.view.alpha = 1.0;
[UIView commitAnimations];
[splashImageView removeFromSuperview];
}
I hope this helps.

I finally found someting that works. Instead of:
tabBarController.view.frame = [[UIScreen mainScreen] applicationFrame];
or
tabBarController.view.bounds = [[self view] bounds];
Because I couldn't find and automatic or named settings for this size, I had to create my own rectangle that is the size of the screen minus the statusBar.
tabBarController.view.frame = CGRectMake(0,0,320,460);

Related

How to animate a UIImageview to display fullscreen by tapping on it?

I have an UIImageView in a UITableviewCell. When it is tapped, the UIImageView should animated to be displayed fullscreen. When the image is tapped when it is fullscreen it should shrink back to the original position.
How can this be achieved?
Add a gesture recognizer to the view controller.
Add the gesture Recognizer to your header file
#interface viewController : UIViewController <UIGestureRecognizerDelegate>{
UITapGestureRecognizer *tap;
BOOL isFullScreen;
CGRect prevFrame;
}
In your viewDidLoad add this:
isFullScreen = false;
tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imgToFullScreen)];
tap.delegate = self;
Add the following delegatemethod:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
{
BOOL shouldReceiveTouch = YES;
if (gestureRecognizer == tap) {
shouldReceiveTouch = (touch.view == yourImageView);
}
return shouldReceiveTouch;
}
Now you just need to implement your imgToFullScreen method.
Make sure you work with the isFullScreen Bool (fullscreen if it is false and back to old size if it's true)
The imgToFullScreen method depends on how you want to make the image become fullscreen.
One way would be:
(this is untested but should work)
-(void)imgToFullScreen{
if (!isFullScreen) {
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
//save previous frame
prevFrame = yourImageView.frame;
[yourImageView setFrame:[[UIScreen mainScreen] bounds]];
}completion:^(BOOL finished){
isFullScreen = true;
}];
return;
} else {
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
[yourImageView setFrame:prevFrame];
}completion:^(BOOL finished){
isFullScreen = false;
}];
return;
}
}
The code from #AzzUrr1, small error corrections (brackets) and tapper implemented slightly different.
Worked for me. Now it would be great to have this implemented with a scrollView, that the user can zoom in/out if the picture is bigger.. Any suggestion?
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIGestureRecognizerDelegate>{
UITapGestureRecognizer *tap;
BOOL isFullScreen;
CGRect prevFrame;
}
#property (nonatomic, strong) UIImageView *imageView;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
isFullScreen = FALSE;
tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imgToFullScreen)];
tap.delegate = self;
self.view.backgroundColor = [UIColor purpleColor];
_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 300, 200)];
_imageView.contentMode = UIViewContentModeScaleAspectFill;
[_imageView setClipsToBounds:YES];
_imageView.userInteractionEnabled = YES;
_imageView.image = [UIImage imageNamed:#"Muppetshow-2.png"];
UITapGestureRecognizer *tapper = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imgToFullScreen:)];
tapper.numberOfTapsRequired = 1;
[_imageView addGestureRecognizer:tapper];
[self.view addSubview:_imageView];
}
-(void)imgToFullScreen:(UITapGestureRecognizer*)sender {
if (!isFullScreen) {
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
//save previous frame
prevFrame = _imageView.frame;
[_imageView setFrame:[[UIScreen mainScreen] bounds]];
}completion:^(BOOL finished){
isFullScreen = TRUE;
}];
return;
}
else{
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
[_imageView setFrame:prevFrame];
}completion:^(BOOL finished){
isFullScreen = FALSE;
}];
return;
}
}
I ended up using MHFacebookImageViewer. Integration is easy, no subclassing UIImageView, and it also has image zooming and flick dismiss.
Although it requires AFNetworking (for loading larger image from URL), you can comment out some code (about 10 lines) to remove this dependency. I can post my AFNetworking-free version if someone needs it. Let me know :)
One possible implementation would be to use a modal view controller with UIModalPresentationFullScreen presentation style.
Just finished a version in swift, just download and add into your project:
GSSimpleImageView.swift
And usage:
let imageView = GSSimpleImageView(frame: CGRectMake(20, 100, 200, 200))
imageView.image = UIImage(named: "test2.png")
self.view.addSubview(imageView)

iOS – Animation glitch with UIToolbar

I'm getting a "weird" animation glitch when I add a UIToolbar to the view. I'm animating the UIToolbar so it slides up from the bottom together with either a UIPickerView or a UIDatePicker. At first I see it's sliding up but after the animation is finished it quickly disappears. This happens when I slide down (animating the UIPickerView to slide down off the screen) and right after that I have another UIPickerView slide up.
I noticed that if I set a delay (- performSelector...) on the slide up call for 0.3 seconds it will display the UIToolbar properly (anything less than 0.3 seconds will still have the same glitch). What might be causing this?
EDIT: Perhaps I should place both the UIToolbar and UIDatePicker in a new UIView container?
This is the code I'm using:
if ([self.view.subviews containsObject:self.dateRepeatPicker]) {
[self dismissDateRepeatPickerSegmentChanged:NO];
// "Hack", if I don't delay this call the UIToolbar will not display
[self performSelector:#selector(showDatePicker) withObject:nil afterDelay:0.3];
} else if (![self.view.subviews containsObject:self.datePicker]) {
[self showDatePicker];
}
- (void)dismissDateRepeatPickerSegmentChanged:(BOOL)segmentChanged {
CGRect toolbarTargetFrame = CGRectMake(0, self.view.bounds.size.height, 320, 44);
CGRect dateRepeatPickerTargetFrame = CGRectMake(0, self.view.bounds.size.height+44, 320, 216);
[UIView animateWithDuration:0.2
animations:^{
self.pickerToolbar.frame = toolbarTargetFrame;
self.dateRepeatPicker.frame = dateRepeatPickerTargetFrame;
}
completion:^(BOOL finished) {
if (segmentChanged) {
[self.pickerToolbar removeFromSuperview];
[self.dateRepeatPicker removeFromSuperview];
[self.remindMeTableView reloadData];
} else {
[self.pickerToolbar removeFromSuperview];
[self.dateRepeatPicker removeFromSuperview];
}
}];
}
- (void)showDatePicker {
// Create the Toolbar over the Picker
CGRect toolbarTargetFrame = CGRectMake(0, self.view.bounds.size.height-216-44, 320, 44);
if (self.pickerToolbar == nil) {
self.pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height, 320, 44)];
self.pickerToolbar.barStyle = UIBarStyleBlack;
self.pickerToolbar.translucent = YES;
}
UIBarButtonItem *spacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"picker-dismiss.png"] style:UIBarButtonItemStyleBordered target:self action:#selector(dismissDatePickerToolbar)];
[self.pickerToolbar setItems:[NSArray arrayWithObjects:spacer, doneButton, nil]];
[self.view addSubview:self.pickerToolbar];
// Create the Picker under the Toolbar
CGRect datePickerTargetFrame = CGRectMake(0, self.view.bounds.size.height-216, 320, 216);
if (self.datePicker == nil) {
self.datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height+44, 320, 216)];
[self.datePicker setMinuteInterval:5];
[self.datePicker addTarget:self action:#selector(changeDate:) forControlEvents:UIControlEventValueChanged];
}
[self.view addSubview:self.datePicker];
[UIView animateWithDuration:0.2 animations:^{
self.pickerToolbar.frame = toolbarTargetFrame;
self.datePicker.frame = datePickerTargetFrame;
}];
}
Solved by adding the UIPickerView and the UIToolbar to a containing UIView and then animating the containing UIView.

View Controller Animation in Xcode

I need to animate a view when user click on the button. i am using the following code for animating
App Delegate
ViewController2 *vc2_controller = [[ViewController2 alloc]init];
UINavigationController *baseViewController = [[UINavigationController alloc]initWithRootViewController:vc2_controller];
[self.window addSubview:baseViewController.view];
self.window.rootViewController = vc2_controller;
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
[self.window addSubview:navigationController.view];
self.viewController = [[vc1controller alloc]initWithNibName:nil bundle:nil];
//ViewController1.m -- This is Working
[self.navigationController pushSlideViewController:self.navigationController];
I created function definition inside the category
//Category
- (void)pushSlideViewController:(UIViewController *)viewController
{
// NSLog(#"In Navigation Controller");
//[UIView transitionWithView:viewController.view duration:0.5 options:UIViewAnimationOptionTransitionFlipFromLeft animations:nil completion:nil];
CGRect screensize = [[UIScreen mainScreen]bounds];
[UIView animateWithDuration:0.5 animations:^{
NSLog(#"In View ANimatin");
CGRect current_rect = viewController.view.frame;
viewController.view.frame = current_rect;
current_rect.origin.x = screensize.size.width-50;
viewController.view.frame = current_rect;
}];
}
Now i am calling ViewController1.m from ViewController2.m -- Animation is Not Working
ViewController1 *view_control = [[ViewController1 alloc]init];
[self.navigationController popSlideViewController:view_control];
//Category
-(void)popSlideViewController:(UIViewController *)viewController
{
CGRect screensize = [[UIScreen mainScreen]bounds];
//NSLog(#"In Pop");
[UIView animateWithDuration:0.5 animations:^{
//View is not coming to original position.
CGRect current_rect = viewController.view.frame;
NSLog(#"In View ANimatin %f",current_rect.origin.x);
viewController.view.frame = current_rect;
current_rect.origin.x = 0.0;
viewController.view.frame = current_rect;
}];
}
Note: i am not using ios5 :-)
Thanks,
You're loading VC2 from VC1, which, as you say, works fine. Then you're trying to load VC1 from VC2, which is where the problem lies - VC1 is still loaded, behind VC2, so you just need to dismiss VC2 in a similar way to how you brought it up in the first place, just animate it back off the screen, remove it from the view, then release it (unless you released it when you showed it). Alternatively you could use the built-in methods,
presentViewController:animated:completion:
and
dismissViewControllerAnimated:completion:
which have their own animation.

Animation not working when view presented with an UIModalTransitionStyleFlipHorizontal

I try to make an animation with an image in my view but it doesn't work: my image is at the final position without animation.
UIImage *myImg = [UIImage imageNamed : #"Img72.png"];
UIImageView *myImgView =[ [UIImageView alloc] initWithImage: myImg ];
myImgView.frame= CGRectMake(250,50,72,72);
[self.view addSubview:myImgView];
[UIView animateWithDuration:0.5
delay: 0.0
options: UIViewAnimationOptionCurveEaseInOut
animations:^{
[UIView setAnimationRepeatCount:100.0];
[UIView setAnimationRepeatAutoreverses:YES];
myImgView.frame= CGRectMake(50,250,72,72);
}
completion:NULL];
[myImgView release];
The same animation code work perfectly in another view. I finally find that it's come from the way I display the view with this code:
FlipsideViewController *controller = [[[FlipsideViewController alloc] initWithNibName:#"FlipsideViewController" bundle:nil] autorelease];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; //KO
[self presentModalViewController:controller animated:YES];
The problem is the modalTransitionStyle. When I comment the line (with //KO) it finally works. I test the other transition style and all the other works (UIModalTransitionStyleCoverVertical, UIModalTransitionStyleCrossDissolve, UIModalTransitionStylePartialCurl)
I made an viewDidLoadProject (Utility App) and just add the animation code in the two view in viewDidLoad method.
Where is the problem? Is it an Apple bug? How can I have a flip transition AND my animation working in the second view?
Here is my example project: http://dl.dropbox.com/u/9204589/testFlipAnimation.zip
That seems more natural to start to play with the interface when all the system stuff is done, didAppear must be used for that purpose i believe (yes, it works :))
FlipsideViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)viewDidAppear:(BOOL)animated
{
UIImage *myImg = [UIImage imageNamed : #"Img72.png"];
UIImageView *myImgView =[ [UIImageView alloc] initWithImage: myImg ];
myImgView.frame= CGRectMake(250,50,72,72);
[self.view addSubview:myImgView];
[UIView animateWithDuration:0.5
delay: 0.0
options: UIViewAnimationOptionCurveEaseInOut
animations:^{
[UIView setAnimationRepeatCount:100.0];
[UIView setAnimationRepeatAutoreverses:YES];
myImgView.frame= CGRectMake(50,250,72,72);
}
completion:NULL];
[myImgView release];
[super viewDidAppear:animated];
}

Show activity indicator during application launch

I am trying to add an activity indicator during startup. I did have a launch image, but I'd rather have just an indicator alone. I added the following to my app delegate, but the indicator doesn't appear.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// *******Create activity indicator****
UIActivityIndicatorView *activity = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(225, 115, 30, 30)];
[activity setBackgroundColor:[UIColor clearColor]];
[activity setActivityIndicatorViewStyle: UIActivityIndicatorViewStyleGray];
[window addSubview: activity];
[activity release];
[activity startAnimating];
activity.hidden = FALSE;
// *******End activity indicator****
MainViewController *viewController = [[MainViewController alloc] initWithNibName:#"MainView" bundle:nil];
self.mainViewController = viewController;
[window addSubview:[mainViewController view]];
mainViewController.view.frame = CGRectMake(0, 20, 320, 411);
[window addSubview:[rootController view]];
[window makeKeyAndVisible];
#if !TARGET_IPHONE_SIMULATOR
[application registerForRemoteNotificationTypes:
UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound];
#endif
application.applicationIconBadgeNumber = 0;
// Hide indicator
[viewController release];
activity.hidden = TRUE;
[activity stopAnimating];
return YES;
}
I visited this question from back in 2009, but the solution didn't work for me.
iPhone-SDK:Activity Indicator during Startup?
For all those who needed this, and i know there were many...
(Made on Xcode version 4.2.1)
So...
In the AppDelegate.h add this:
#property (nonatomic, strong) UIImageView *splashView;
In the AppDelegate.m add this:
On the top of the page of cours #synthesize splashView;
And then:
- (void) splashFade
{
splashView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0, 320, 480)];
splashView.image = [UIImage imageNamed:#"Default.png"];
[_window addSubview:splashView];
[_window bringSubviewToFront:splashView];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:2.0];
[UIView setAnimationDelay:2.5];
[UIView setAnimationTransition:UIViewAnimationTransitionNone forView:_window cache:YES];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(startupAnimationDone:finished:context:)];
splashView.alpha = 0.0;
[UIView commitAnimations];
//Create and add the Activity Indicator to splashView
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
activityIndicator.alpha = 1.0;
activityIndicator.center = CGPointMake(160, 360);
activityIndicator.hidesWhenStopped = NO;
[splashView addSubview:activityIndicator];
[activityIndicator startAnimating];
}
- (void)startupAnimationDone:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
{
[splashView removeFromSuperview];
}
The [UIView setAnimationDelay:2.5] is responsible for how long the splashView will be in front by the delay time you choose.
You can change the position of the indicator by changing the nubmers of x/y in:
activityIndicator.center = CGPointMake(160, 360);
At last, under the methode:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Just add this:
[self performSelector:#selector(splashFade) withObject:nil];
And there you go :)
Hope it helped.
Have a nice programming....
I don't think this is possible from looking at the docs for UIApplicationDelegate
The earliest your app is called is in
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Which as the name suggests is when your app hasFinishedLaunching
The reason nothing happens when you show and hide the indicator is to do with threading. The user interface will only update at the end of your method where the net result of your changes will be that the indicator is hidden.
Another solution is to let the launchimage load and when your ViewController loads at the viewDidLoad, use overlay + indicator on top of your view with alpha below 1:
UIView *baseView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.view addSubview:baseView];
[baseView setBackgroundColor:[UIColor blackColor]];
baseView.userInteractionEnabled = NO;
baseView.alpha = 0.4;
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
indicator.frame = CGRectMake(0.0, 0.0, 40.0, 40.0);
indicator.center = self.view.center;
[self.view addSubview:indicator];
[indicator bringSubviewToFront:self.view];
[indicator startAnimating];
Now comes the fun part, use delegate to remove the indicator + overlay when all your background threads finish to load up and simple call a method via your delegate:
- (void) onFinishLoading{
[indicator stopAnimating];
[baseView removeFromSuperview];
}
In order to stopAnimation and removeFromSuperView you might want to make baseView and indicator property + #synthesize
This isn't possible (as #Paul.S is saying). However, you can simulate this by adding a (static, so it's not animating) Default.png-splash-screen to your project.
In my opinion, though, you should rather invest in a better performance. For example: do you link your app with unused frameworks (eg. QuartzCore, MapKit) or something.
Starting an app should take 2 seconds max. At this time, you don't really need to show your user an activity-indicator. If it does take longer, you should take a look at what makes it so slow, rather than trying to hide it.