Custom Navigation Transitions on iOS 7, how to manage the keyboard? - uiview

TabBarController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
PlaylistViewController *playlistViewController = [[PlaylistViewController alloc] init];
UIViewController *otherViewController = [[UIViewController alloc] init];
UINavigationController *playlistNavigationController = [[UINavigationController alloc] initWithRootViewController:playlistViewController];
playlistNavigationController.delegate = self;
self.viewControllers = #[playlistNavigationController, otherViewController];
playlistNavigationController.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemDownloads tag:kTabBarTagPlaylist];
playlistNavigationController.tabBarItem.title = #"Playlist";
otherViewController.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemMore tag:kTabBarTagOther];
playlistNavigationController.navigationBar.tintColor = [UIColor redColor];
}
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC {
if (operation == UINavigationControllerOperationPush) return [[FadeTransition alloc] init];
else if (operation == UINavigationControllerOperationPop) return [[SlideTransition alloc] init];
return nil;
}
PlaylistViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor redColor];
UIBarButtonItem *storeBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Store"
style:UIBarButtonItemStylePlain
target:self
action:#selector(test)];
self.navigationItem.leftBarButtonItem = storeBarButtonItem;
UIBarButtonItem *currentlyPlayingButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Now playing"
style:UIBarButtonItemStylePlain
target:self
action:#selector(test)];
self.navigationItem.rightBarButtonItem = currentlyPlayingButtonItem;
self.navigationItem.title = #"Playlist";
self.playlistTableViewController = [[PlaylistTableViewController alloc] initWithStyle:UITableViewStylePlain];
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 44)];
searchBar.placeholder = #"Search";
searchBar.delegate = self;
self.playlistTableViewController.tableView.tableHeaderView = searchBar;
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
[self addChildViewController:self.playlistTableViewController];
[self.view addSubview:self.playlistTableViewController.view];
self.playlistTableViewController.view.frame = self.view.bounds;
self.playlistTableViewController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
[self.playlistTableViewController didMoveToParentViewController:self];
}
FadeTransition.m
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return 0.5;
}
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
/* view controllers */
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
/* views */
UIView *containerView = [transitionContext containerView];
[containerView addSubview:fromVC.view];
[containerView addSubview:toVC.view];
/* settings */
toVC.view.alpha = 0.0f; /* not visible at start */
[UIView animateWithDuration:[self transitionDuration:transitionContext]
delay:0
options:UIViewAnimationOptionTransitionNone
animations:^{
toVC.view.alpha = 1.0f; /* 100% visible at the end */
}
completion:^(BOOL finished) {
[fromVC.view removeFromSuperview];
[transitionContext completeTransition:YES];
}];
}
This is how it looks like:
When I touch one of the results, a new UIView gets pushed and animated by FadeTransition.
The keyboard automatically gets slided down, but I need to leave the keyboard opened (it should stay behind), how can I do it?

Related

View shifted across to the right

I am trying to figure out why this tableView is shifted across to the right, it appears in every view the app uses, yet the app itself displays fine, it's only when the tableView appears is everything shifted out of the screen.
I believe the initializing is here;
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"Lets load the frame");
CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[self.view setFrame: frame];
self.contentSizeForViewInPopover = CGSizeMake(320, 480);
m_mywork = nil;
dataArray = [LoadSessionController loadTableData:YES];
}
Here is the initializing from another class;
on iPad display is perfect.
- (void) ShowInitialMenu
{
InitialMenuController *MewMgrController = [[InitialMenuController alloc] initWithStyle:UITableViewStyleGrouped];
MewMgrController.delegate = self;
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController: MewMgrController];
if(![ColorSplashAppDelegate isiPad]){
[self presentViewController:navController animated:YES completion:nil];
}
else{
UIPopoverController* popover = [[UIPopoverController alloc] initWithContentViewController:navController];
popover.delegate = self;
[popover presentPopoverFromRect:CGRectMake(30.0, 940.0, 30.0, 480.0)
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionDown
animated:YES];
ColorSplashAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
appDelegate.popoverController = popover;
}
[navController release];
[MewMgrController release];
[self enableUserAction:YES];
}
Try This.
-(void)viewDidLayoutSubviews
{
CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[self.view setFrame: frame];
self.contentSizeForViewInPopover = CGSizeMake(320, 480);
m_mywork = nil;
}

Dismissing MFMailComposeViewController causes upward shift

I've ran into an issue when dismissing the MFMailComposeViewController and returning to a shifted screen in iOS7. The method below has worked on iOS6 without shifting the screen upwards of about 25-30. Altering my[[UIScreen mainScreen] applicationFrame]] to using auto resize isn't fixing my issue as suggested in another question of downward shifting.
#import "RootViewController.h"
#implementation RootViewController
- (void)loadView {
self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease];
self.view.backgroundColor = [UIColor whiteColor];
navBar = [[UINavigationBar alloc] init];
navBar.frame = CGRectMake(0, 0, self.view.frame.size.width, 44);
UINavigationItem *navItem = [[[UINavigationItem alloc] initWithTitle:#"iShift"] autorelease];
UIBarButtonItem *mail = [[[UIBarButtonItem alloc] initWithTitle:#"Email" style:UIBarButtonItemStylePlain target:self action:#selector(sendMail)] autorelease];
navItem.rightBarButtonItem = mail;
navBar.barStyle = UIBarStyleDefault;
navBar.items = [NSArray arrayWithObject:navItem];
[self.view addSubview:navBar];
}
- (void)sendMail {
MFMailComposeViewController *compose = [[MFMailComposeViewController alloc] init];
compose.mailComposeDelegate = self;
if ([MFMailComposeViewController canSendMail]){
NSArray *toRecipients = [NSArray arrayWithObjects:#"sample#gmail.com", nil];
[compose setToRecipients:toRecipients];
[compose setSubject:#"Test Email"];
[compose setMessageBody:#"Device: \niOS Version: \nProblem: \n\nSuggestions: \n" isHTML:NO];
[self presentModalViewController:compose animated:YES];
}
[compose release];
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
[self dismissModalViewControllerAnimated:YES];
}
#end
I've managed to solve this issue in what seems to be pretty dirty by changing [[UIScreen mainScreen] applicationFrame]] to [[UIScreen mainScreen] bounds]] and padding the navbar position by 20pts resulting in the following code. If someone can point out a problem with this I'm open to suggestions. (With a tableview it's y position is also padded by 20pts)
#import "RootViewController.h"
#implementation RootViewController
- (void)loadView {
self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
self.view.backgroundColor = [UIColor whiteColor];
navBar = [[UINavigationBar alloc] init];
navBar.frame = CGRectMake(0, 20, self.view.frame.size.width, 44);
UINavigationItem *navItem = [[[UINavigationItem alloc] initWithTitle:#"iShift"] autorelease];
UIBarButtonItem *mail = [[[UIBarButtonItem alloc] initWithTitle:#"Email" style:UIBarButtonItemStylePlain target:self action:#selector(sendMail)] autorelease];
navItem.rightBarButtonItem = mail;
navBar.barStyle = UIBarStyleDefault;
navBar.items = [NSArray arrayWithObject:navItem];
[self.view addSubview:navBar];
}
- (void)sendMail {
MFMailComposeViewController *compose = [[MFMailComposeViewController alloc] init];
compose.mailComposeDelegate = self;
if ([MFMailComposeViewController canSendMail]){
NSArray *toRecipients = [NSArray arrayWithObjects:#"sample#gmail.com", nil];
[compose setToRecipients:toRecipients];
[compose setSubject:#"Test Email"];
[compose setMessageBody:#"Device: \niOS Version: \nProblem: \n\nSuggestions: \n" isHTML:NO];
[self presentModalViewController:compose animated:YES];
}
[compose release];
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
[self dismissModalViewControllerAnimated:YES];
}
#end

easier way to subview a UIImagePickerController? mines not working

When I run my code and launch the camera with the code below I get my custom overlayView along with the default camera buttons. The only problem is, now, I get a blank black box where my UIImagePicker once was. I am simply trying to create a camera using the default UIImagePicker controls and buttons and then add my own IBOutlet UILabel over top of the default imagePickerController so that my label is displayed along with all the default camera controls. I'm having a terrible time accomplishing this though. cheers!
- (void)viewDidLoad
{
[super viewDidLoad];
if (self.image == nil && [self.videoFilePath length] == 0) {
self.imagePicker = [[UIImagePickerController alloc] init];
self.imagePicker.delegate = self;
self.imagePicker.allowsEditing = NO;
self.imagePicker.videoMaximumDuration = 10;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
}
self.imagePicker.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:self.imagePicker.sourceType];
[[NSBundle mainBundle] loadNibNamed:#"OverlayView" owner:self options:nil];
self.overlayView.frame = self.imagePicker.cameraOverlayView.frame;
self.imagePicker.cameraOverlayView = self.overlayView;
self.overlayView = nil;
}
[self presentViewController:self.imagePicker animated:YES completion:nil];
}
Try to use my code. It worked fine. May be you achieve what you want. I created a controller, and used it's view to set cameraOverlayView property. I didn't use nib files, I created everything programmatically.
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.tabBarItem.image = [UIImage imageNamed:#"86-camera"];
self.cameraOverlayViewController = [[CameraOverlayViewController alloc] init];
self.cameraOverlayViewController.picker = picker;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.showsCameraControls = NO;
picker.toolbarHidden = YES;
picker.cameraOverlayView = self.cameraOverlayViewController.view;
picker.delegate = self.cameraOverlayViewController;
}
else if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]) {
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
}
This is a code for custom CameraOverlayViewController:
Interface file:
#import <UIKit/UIKit.h>
#interface CameraOverlayViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
#property (nonatomic, strong) UIImagePickerController *picker;
#end
Implementation file:
#import "CameraOverlayViewController.h"
#import "BButton.h"
#import "AnalyseViewController.h"
#import "Tree.h"
#interface CameraOverlayViewController ()
{
}
#end
#implementation CameraOverlayViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.view.backgroundColor = [UIColor clearColor];
self.view.opaque = NO;
}
return self;
}
- (void)loadView
{
[super loadView];
UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, self.view.bottom - 150, 320, 150)];
bottomView.backgroundColor = [UIColor blackColor];
BButton *button = [[BButton alloc] initWithFrame:CGRectMake(50, 25, 220, 50) type:BButtonTypePrimary];
[button setTitle:#"Сфотографировать" forState:UIControlStateNormal];
[button addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[bottomView addSubview:button];
[self.view addSubview:bottomView];
UIView *topView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 70)];
topView.backgroundColor = [UIColor clearColor];
UILabel *infoLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, 310, 60)];
infoLabel.backgroundColor = [UIColor clearColor];
infoLabel.font = [UIFont fontWithName:#"Georgia" size:18];
infoLabel.textColor = [UIColor whiteColor];
infoLabel.textAlignment = NSTextAlignmentCenter;
infoLabel.numberOfLines = 0;
infoLabel.text = #"Поместите лист дерева внутри рамки, чтобы\nсфотографировать его.";
[topView addSubview:infoLabel];
[self.view addSubview:topView];
UIView *bordersView = [[UIView alloc] initWithFrame:CGRectMake(10, topView.bottom + 10, 300, 300)];
bordersView.layer.cornerRadius = 10;
bordersView.layer.borderColor = [UIColor whiteColor].CGColor;
bordersView.layer.borderWidth = 2;
bordersView.backgroundColor = [UIColor clearColor];
[self.view addSubview:bordersView];
}
#pragma mark - UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
AnalyseViewController *analyseViewController = [[AnalyseViewController alloc] initWithNibName:nil bundle:nil];
analyseViewController.baseImage = image;
analyseViewController.treesArray = [Tree retrieveAllTrees];
UINavigationController *analyseNavController = [[UINavigationController alloc] initWithRootViewController:analyseViewController];
[AppDel.tabBarController presentViewController:analyseNavController animated:YES completion:nil];
}
#pragma mark - Other methods
- (void)buttonClicked:(id)sender
{
[self.picker takePicture];
}
#end
Delete unneeded classes like BButton yourself.
fixed it with this. I did some research on CGPoints & CGRect and come up with this solution. Not sure if it is the most elegant solution but it works and seems to make pretty good sense. - (void)viewDidLoad
{
[super viewDidLoad];
if (self.image == nil && [self.videoFilePath length] == 0) {
self.imagePicker = [[UIImagePickerController alloc] init];
self.imagePicker.delegate = self;
self.imagePicker.allowsEditing = YES;
self.imagePicker.videoMaximumDuration = 10;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
}
self.imagePicker.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:self.imagePicker.sourceType];
[self presentViewController:self.imagePicker animated:NO completion:nil];
}
[[NSBundle mainBundle] loadNibNamed:#"OverlayView" owner:self options:nil];
self.overlayView.frame = CGRectMake(160,0,0,0);
self.imagePicker.cameraOverlayView = self.overlayView;
}

"addChildViewController:" crashes on iPad but not iPhone

I have an iPhone app that works great when running on the phone however crashes at launch when running on compatibility mode on the iPad. I use iAd in my project, specifically i'm using
Bannerviewcontroller.h and .m
from the iAd suite to present the banner programmatically.
in my App Delegate I wrap some view controllers as follows.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIViewController *viewController1, *viewController2, *catVC3, *otherVC4;
UINavigationController *navController, *dognav, *catnav, *othernav;
viewController1 = [[FirstViewController alloc] initWithNibName:#"FirstViewController_iPhone" bundle:nil];
viewController2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController_iPhone" bundle:nil];
catVC3 = [[catViewController alloc]initWithNibName:#"catViewController_iPhone" bundle:nil];
otherVC4 = [[otherViewController alloc]initWithNibName:#"otherViewController_iPhone" bundle:nil];
navController = [[UINavigationController alloc]initWithRootViewController:viewController1];
dognav = [[UINavigationController alloc]initWithRootViewController:viewController2];
catnav = [[UINavigationController alloc]initWithRootViewController:catVC3];
othernav = [[UINavigationController alloc]initWithRootViewController:otherVC4];
_tabBarController = [[UITabBarController alloc] init];
NSArray *controllers = [NSArray arrayWithObjects:navController,dognav,catnav,othernav,nil];
_tabBarController.viewControllers = controllers;
//wrap tabbar controller in adbanner controller
_bannerViewController = [[BannerViewController alloc] initWithContentViewController:_tabBarController];
self.window.rootViewController = _bannerViewController;
[self.window makeKeyAndVisible];
return YES;
Then the crash happens here in my
Bannerviewcontroller.m
#import "BannerViewController.h"
#implementation BannerViewController
{
ADBannerView *_bannerView;
UIViewController *_contentController;
}
- (id)initWithContentViewController:(UIViewController *)contentController
{
self = [super init];
if (self != nil) {
_bannerView = [[ADBannerView alloc] init];
_bannerView.delegate = self;
_contentController = contentController;
}
return self;
}
- (void)loadView
{
UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[contentView addSubview:_bannerView];
[self addChildViewController:_contentController];
[contentView addSubview:_contentController.view];
[_contentController didMoveToParentViewController:self];
self.view = contentView;
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return [_contentController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}
- (void)viewDidLayoutSubviews
{
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
_bannerView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;
} else {
_bannerView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierLandscape;
}
CGRect contentFrame = self.view.bounds;
CGRect bannerFrame = _bannerView.frame;
if (_bannerView.bannerLoaded) {
contentFrame.size.height -= _bannerView.frame.size.height;
contentFrame.origin.y = _bannerView.frame.size.height;
bannerFrame.origin.y = contentFrame.size.height - contentFrame.size.height;
} else {
bannerFrame.origin.y = contentFrame.size.height;
}
_contentController.view.frame = contentFrame;
_bannerView.frame = bannerFrame;
}
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
[UIView animateWithDuration:0.35 animations:^{
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
}];
}
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
[UIView animateWithDuration:0.35 animations:^{
[self.view setNeedsLayout];
[self.view layoutIfNeeded];
}];
}
#end
and throws this exception:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
Whats going on here? Thanks in advance!
The error tells, that _contentController is not initialized. Where / how do you assign it? I can't see it in the AppDelegate code.

Greedy UITabBarController?

I'm making a custom UIViewController which holds to sub view controllers. They are put inside the main view controller this way:
- (void) setHeaderViewController:(UIViewController *)vc
{
[self setViewController:vc isHeader:YES];
_headerViewController = vc;
}
- (void) setDetailViewController:(UIViewController *)vc
{
[self setViewController:vc isHeader:NO];
_detailViewController = vc;
}
- (void) setViewController:(UIViewController*) viewController isHeader:(BOOL)isHeader
{
UIViewController* viewControllerRef = ((isHeader) ? _headerViewController : _detailViewController);
if(viewControllerRef == viewController)
return;
const CGSize selfSize = self.view.frame.size;
CGRect viewFrame;
if (isHeader)
{
viewFrame = CGRectMake(0, 0, selfSize.width, 150);
}
else
{
viewFrame = CGRectMake(0, 150, selfSize.width, selfSize.height-150);
}
UIView* viewControllerView = viewController.view;
[viewControllerView setFrame:viewFrame];
[viewControllerView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | ((isHeader) ? UIViewAutoresizingFlexibleBottomMargin : UIViewAutoresizingFlexibleTopMargin))];
[self.view addSubview:viewControllerView];
}
If I put two UIViewControllers inside of each sub view controller slot, the sizes defined in the method is respected. However, when putting a UITabBarController, it gets greedy and occupies the whole space:
UIViewController *vc = [[WIFCustomerDetailHeaderViewController alloc] initWithNibName:#"WIFCustomerDetailHeaderViewController" bundle:nil];
[self setHeaderViewController:vc];
UIViewController *vc1 = [[UIViewController alloc] init];
vc1.title = #"Personal Data";
vc1.tabBarItem = [[UITabBarItem alloc] initWithTitle:#"Personal Data" image:nil tag:0];
vc1.view.backgroundColor = [UIColor redColor];
vc1.view.frame = CGRectMake(0,400,100,100);
UIViewController *vc2 = [[UIViewController alloc] init];
vc2.title = #"Diagnosis";
vc2.tabBarItem = [[UITabBarItem alloc] initWithTitle:#"Diagnosis" image:nil tag:0];
vc2.view.backgroundColor = [UIColor purpleColor];
vc2.view.frame = CGRectMake(0,500,50,50);
NSArray *tabs = [[NSArray alloc] initWithObjects:vc1, vc2, nil];
WIFCustomerDetailTabViewController *tvc = [[WIFCustomerDetailTabViewController alloc] init];
[tvc setViewControllers:tabs];
[self setDetailViewController:tvc];
Does anyone knows what can be happening here? I can't find the cause...
Images below..
Documentation for the UITabBarController class says, "you must install this view as the root of your window. Unlike other view controllers, a tab bar interface should never be installed as a child of another view controller".
It seems that you're attempting a design that's specifically not supported.

Resources