I would like to use an MPMediaPickerController in a navigation controller.
This does work:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MusicImport" bundle:[NSBundle mainBundle]];
UINavigationController *nav = [storyboard instantiateInitialViewController];
self.picker = [[MPMediaPickerController alloc] initWithMediaTypes:MPMediaTypeAnyAudio];
self.picker.delegate = self;
self.picker.allowsPickingMultipleItems = NO;
self.picker.showsCloudItems = NO;
self.picker.view.frame = CGRectMake(0, 0, 1024, 768);
// add to dummy VC's view
[[nav.viewControllers[0] view] addSubview:self.picker.view];
nav.navigationBarHidden = YES;
nav.delegate = self;
self.mainNav = nav;
I then push my custom view controller when the user selects an item in the picker:
self.selectedItem = mediaItemCollection.items[0];
self.playbackViewController = [[PlaybackViewController alloc] initWithNibName:#"PlaybackViewController" bundle:[NSBundle mainBundle]];
self.playbackViewController.mediaItem = self.selectedItem;
self.playbackViewController.delegate = self;
self.mainNav.navigationBar.tintColor = self.picker.navigationController.navigationBar.tintColor;
self.mainNav.navigationBarHidden = NO;
[self.mainNav pushViewController:self.playbackViewController animated:YES];
so far, so good. only problem here is that the tintColor thing does not work.
the real problem is that when navigating back from my custom playback VC, the media picker does not become visible.
Even when I'm trying to add it back in the navigation controller's delegate method:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if(viewController == navigationController.viewControllers[0])
{
[viewController.view addSubview:self.picker.view];
navigationController.navigationBarHidden = YES;
}
}
alas, no dice.
Related
I have read many other threads on this and the Apple docs, but haven't found a solution yet for my particular problem.
My app uses a UITabBarController as the rootViewController, and in one of the tabs I have a UISegmentedControl in the navigationBar to switch between three child UITableViewControllers.
(In the real app two of the childVCs are a custom UIViewController, I'm just using three UITableViewControllers for the sample app).
The segmentedControl setup and the switching all works fine. The thing that goes wrong is that only the first UITableViewController is shown correctly. For the second and third one, part of the first cell is hidden under the navigationBar. When I click through all three, the first one is still ok.
I have made a little sample app to show what's going on, using very bright colors for demonstration purposes: https://www.dropbox.com/s/7pfutvn5jba6rva/SegmentedControlVC.zip?dl=0
Here is also some code (I'm not using storyboards):
// AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
FirstViewController *fvc = [[FirstViewController alloc] init];
UINavigationController *firstNavigationController = [[UINavigationController alloc] initWithRootViewController: fvc];
SecondViewController *svc = [[SecondViewController alloc] init];
UINavigationController *secondNavigationController = [[UINavigationController alloc] initWithRootViewController: svc];
// Initialize tab bar controller, add tabs controllers
UITabBarController *tabBarController = [[UITabBarController alloc] init];
tabBarController.viewControllers = #[firstNavigationController, secondNavigationController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
// FirstViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.title = #"One";
self.view.backgroundColor = [UIColor orangeColor];
UITableViewController *vc1 = [[UITableViewController alloc] init];
UITableViewController *vc2 = [[UITableViewController alloc] init];
UITableViewController *vc3 = [[UITableViewController alloc] init];
vc1.view.backgroundColor = [UIColor redColor];
vc2.view.backgroundColor = [UIColor blueColor];
vc3.view.backgroundColor = [UIColor greenColor];
self.viewControllers = #[vc1, vc2, vc3];
self.segmentTitles = #[#"Red", #"Blue", #"Green"];
self.segmentedControl = [[UISegmentedControl alloc] initWithItems: self.segmentTitles];
[self.segmentedControl addTarget: self
action: #selector(segmentClicked:)
forControlEvents: UIControlEventValueChanged];
self.navigationItem.titleView = self.segmentedControl;
self.segmentedControl.selectedSegmentIndex = 0;
// set the first child vc:
UIViewController *vc = self.viewControllers[0];
[self addChildViewController: vc];
vc.view.frame = self.view.bounds;
[self.view addSubview: vc.view];
self.currentVC = vc;
}
- (void)segmentClicked:(id)sender
{
if (sender == self.segmentedControl)
{
NSUInteger index = self.segmentedControl.selectedSegmentIndex;
[self loadViewController: self.viewControllers[index]];
}
}
- (void)loadViewController:(UIViewController *)vc
{
[self addChildViewController: vc];
[self transitionFromViewController: self.currentVC
toViewController: vc
duration: 1.0
options: UIViewAnimationOptionTransitionFlipFromBottom
animations: ^{
[self.currentVC.view removeFromSuperview];
vc.view.frame = self.view.bounds;
[self.view addSubview: vc.view];
} completion: ^(BOOL finished) {
[vc didMoveToParentViewController: self];
[self.currentVC removeFromParentViewController];
self.currentVC = vc;
}
];
}
So obviously my question is, why does this happen, and what can I do to fix it?
Edit: adding screenshots.
EDIT: Based on the answer below I changed the code in the animation block to:
[self.currentVC.view removeFromSuperview];
if ([vc.view isKindOfClass: [UIScrollView class]])
{
UIEdgeInsets edgeInsets = UIEdgeInsetsMake(self.topLayoutGuide.length, 0, self.bottomLayoutGuide.length, 0);
[UIView performWithoutAnimation: ^{
vc.view.frame = self.view.bounds;
((UIScrollView *)vc.view).contentInset = edgeInsets;
((UIScrollView *)vc.view).scrollIndicatorInsets = edgeInsets;
}];
}
else
{
vc.view.frame = self.view.bounds;
}
[self.view addSubview: vc.view];
Now it works. I'm going to try this with a custom UIViewController as well.
The issue is that you do not set the correct content inset to each table view. The system attempts to do it for you, but I guess your setup is too complex for it, and it only does it for the first tableview that is loaded in viewDidLoad. In your loadViewController: method, when replacing the currently displayed view, make sure to set both the contentInset and scrollIndicatorInsets to the values of the previous view. I think the system will manage to set the correct insets later, in case you rotate to landscape. Try it. If it doesn't, you will need to do it on your own in viewDidLayoutSubviews.
I've created tab bar items in the first controller
UITabBarController *tabBarController = [[UITabBarController alloc] init];
tabBarController.delegate = self;
tabBarController.view.frame = CGRectMake(0, 0, 320, 460);
StageViewController *stageViewRegular = [[StageViewController alloc] init];
[stageViewRegular setTitle:#"Regular"];
stageViewRegular.tabBarItem.tag = 1;
StageViewController *stageViewAdvanced = [[StageViewController alloc] init];
[stageViewAdvanced setTitle:#"Advanced"];
stageViewAdvanced.tabBarItem.tag = 2;
NSArray* controllersArray = [NSArray arrayWithObjects:stageViewRegular, stageViewAdvanced, nil];
tabBarController.viewControllers = controllersArray;
tabBarController.selectedIndex = 0;
[self.view addSubview:tabBarController.view];
and I want to pass tabBarItem.tag to the controllers as mentioned above
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
chooseLevel = viewController.tabBarItem.tag;
}
but in the second controller
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(#"%d", chooseLevel);
}
the chooseLevel always record old value. If I press the first tab and then press the second tab, the value in chooseLevel is 1 rather than 2.
Does anyone know how to solve it?
Do the following steps :
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
UIViewController *viewController1 = [[[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil] autorelease];
viewController1.tabBarItem.tag = 0;
UIViewController *viewController2 = [[[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil] autorelease];
viewController2.tabBarItem.tag = 1;
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = #[viewController1, viewController2];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
FirstViewController.m
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(#"%d",self.tabBarItem.tag);
}
SecondViewController.m
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(#"%d",self.tabBarItem.tag);
}
OutPut :
2013-06-27 18:13:03.913 sampletabs[3981:c07] 0
2013-06-27 18:13:05.282 sampletabs[3981:c07] 1
Thanks, Do let me know it works for you ?
Why don't you use selectedIndex property of the UITabBarController. I think it has the value you are trying to use.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UITabBarController_Class/Reference/Reference.html
You can use selected index property like this:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
chooseLevel = tabBarController.selected index;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
int selectedtag=self.tabBarController.selectedIndex;
NSLog(#"%d", selectedtag);
}
Do this :
RootViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UITabBarController *tabBarController = [[UITabBarController alloc] init];
tabBarController.delegate = self;
tabBarController.view.frame = CGRectMake(0, 0, 320, 460);
FirstViewController *stageViewRegular = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
[stageViewRegular setTitle:#"First"];
stageViewRegular.tabBarItem.tag = 1;
SecondViewController *stageViewAdvanced = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[stageViewAdvanced setTitle:#"Second"];
stageViewAdvanced.tabBarItem.tag = 2;
NSArray* controllersArray = [NSArray arrayWithObjects:stageViewRegular, stageViewAdvanced, nil];
tabBarController.viewControllers = controllersArray;
tabBarController.selectedIndex = 0;
[self.view addSubview:tabBarController.view];
}
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
NSLog(#"%d",viewController.tabBarItem.tag);
}
FirstViewController
-(void)viewWillAppear:(BOOL)animated
{
NSLog(#"viewWillAppear %d",self.tabBarItem.tag);
}
SecondViewController
-(void)viewWillAppear:(BOOL)animated
{
NSLog(#"viewWillAppear %d",self.tabBarItem.tag);
}
If you need Global value of selected tab Index, then create readWrite property in AppDelegate and set the value in either RootViewController or First/SecondViewController.you will get global value of ChooseLevel.
Thanks,
I am facing this issue from last two days, but could find any solution on it. Can some one help. This is the code snippet am using for TabBar viewControllers.
// Set Up Tab Bar
NSMutableArray *tabBarViewControllers = [[NSMutableArray alloc] initWithCapacity:5];
self.tabBarController = [[UITabBarController alloc] init];
[tabBarController
setDelegate:self];
UINavigationController *navController = nil;
NSArray *vcArray = [self papulateViewControllers];
// SetViewController for tab Bar
-(NSArray *) papulateViewControllers{
BrowseViewController *browseVC = [[BrowseViewController alloc] initWithNibName:#"BrowseViewController" bundle:nil];
AlbumViewController *albumVC = [[AlbumViewController alloc] initWithNibName:#"AlbumViewController" bundle:nil];
SubmitStep1VC *submitVC = [[SubmitStep1VC alloc] initWithNibName:#"SubmitStep1VC" bundle:nil];
// SubmitStep1VC *submitVC = [[SubmitStep1VC alloc] initWithNibName:#"SubmitStep1_iPhone5.xib" bundle:[NSBundle mainBundle]];
WallViewController *wallVC = [[WallViewController alloc] initWithNibName:#"WallViewController" bundle:nil];
OptionVC *optionVC = [[OptionVC alloc] initWithNibName:#"OptionVC" bundle:nil];
sliderVCRef = [[SliderVC alloc] initWithNibName:#"SliderVC" bundle:nil];
//Navigation Controllers
UINavigationController *browseNavController = [[UINavigationController alloc] initWithRootViewController: browseVC];
[browseNavController setNavigationBarHidden:YES];
UINavigationController *albumNavController = [[UINavigationController alloc] initWithRootViewController: albumVC];
[albumNavController setNavigationBarHidden:YES];
UINavigationController *submitNavController = [[UINavigationController alloc] initWithRootViewController: submitVC];
[submitNavController setNavigationBarHidden:YES];
UINavigationController *wallNavController = [[UINavigationController alloc] initWithRootViewController: wallVC];
[wallNavController setNavigationBarHidden:YES];
UINavigationController *optionNavController = [[UINavigationController alloc] initWithRootViewController: optionVC];
[optionNavController setNavigationBarHidden:YES];
DDMenuController *browseMenuController = [[DDMenuController alloc] initWithRootViewController:browseNavController];
self.menuController = browseMenuController;
self.menuController.leftViewController = sliderVCRef;
DDMenuController *albumMenuController = [[DDMenuController alloc] initWithRootViewController:albumNavController];
albumMenuController.leftViewController = sliderVCRef;
DDMenuController *submitMenuController = [[DDMenuController alloc] initWithRootViewController:submitNavController];
submitMenuController.leftViewController = sliderVCRef;
DDMenuController *wallMenuController = [[DDMenuController alloc] initWithRootViewController:wallNavController];
wallMenuController.leftViewController = sliderVCRef;
DDMenuController *optionMenuController = [[DDMenuController alloc] initWithRootViewController:optionNavController];
optionMenuController.leftViewController = sliderVCRef;
/// Works fine if i uncomment this line and comment next line of code (Passing Viewcontrollers is fine )
// return [NSArray arrayWithObjects:self.menuController, albumVC, submitVC, wallVC, optionVC, nil];
////******* issue in case i use this line (Passing menuController creates issue of Tabbar )
return [NSArray arrayWithObjects:self.menuController, albumMenuController, submitMenuController, wallMenuController, optionMenuController, nil];
////////////
}
When i try to push to push to any viewcontroler from any above TabBarController Tab bar is not hiding . example
grandPrizeVC.hidesBottomBarWhenPushed = YES;
Its keep showing me tab bar.
If i try
appDelegate.tabbarcontroller.tabbar.hidden = YES; It shows on a black bottom bar on new VC.
Your app doing just what you have implemented. You are adding your sliding menu view controller as subview controller to tabbar controller, of course, it won't hide. Some suggestions to hide tabbar:
1. Add tabbar controller as modal to your DDMenuController
2. write some methods to hide/show tabbar (searching hide tabbar will give you the answers, or you could just traverse subviews of tabbar controller's view find tabbar and hide it).
Good luck!
Following worked for me :
Show TabBar :
+ (void) showTabBar{
MyAppDelegate* appDelegate = (MyAppDelegate *) [[UIApplication sharedApplication]delegate];
UITabBar *tabBar = appDelegate.tabBarController.tabBar;
UIView *parent = tabBar.superview; // UILayoutContainerView
UIView *content = [parent.subviews objectAtIndex:0]; // UITransitionView
UIView *window = parent.superview;
CGRect tabFrame = tabBar.frame;
tabFrame.origin.y = CGRectGetMaxY(window.bounds) - CGRectGetHeight(tabBar.frame);
tabBar.frame = tabFrame;
CGRect contentFrame = content.frame;
contentFrame.size.height -= tabFrame.size.height;
}
Hide TabBar:
+(void) hideTabBar{
MyAppDelegate* appDelegate = (MyAppDelegate *) [[UIApplication sharedApplication]delegate];
UITabBar *tabBar = appDelegate.tabBarController.tabBar;
UIView *parent = tabBar.superview; // UILayoutContainerView
UIView *content = [parent.subviews objectAtIndex:0]; // UITransitionView
UIView *window = parent.superview;
[UIView animateWithDuration:0.01
animations:^{
CGRect tabFrame = tabBar.frame;
tabFrame.origin.y = CGRectGetMaxY(window.bounds);
tabFrame.origin.y +=20;
tabBar.frame = tabFrame;
content.frame = window.bounds;
}];
}
I have implemented the KKLockscreen view controller and is working well within the in-app settings controller. Able to set passcode and change them as well.
I am having problem to call he lock screen view from appdelegate. I have added delegate .h file and imported the view controller in .m file. still it's not calling the lockscreen. any help?
below is my code.
- (void)applicationDidBecomeActive:(UIApplication *)application
{
if ([[KKPasscodeLock sharedLock] isPasscodeRequired]) {
KKPasscodeViewController *vc = [[KKPasscodeViewController alloc] initWithNibName:nil bundle:nil];
vc.mode = KKPasscodeModeEnter;
vc.delegate = self;
dispatch_async(dispatch_get_main_queue(),^ {
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
nav.modalPresentationStyle = UIModalPresentationFormSheet;
nav.navigationBar.barStyle = UIBarStyleBlack;
nav.navigationBar.opaque = NO;
} else {
nav.navigationBar.tintColor = _navigationController.navigationBar.tintColor;
nav.navigationBar.translucent = _navigationController.navigationBar.translucent;
nav.navigationBar.opaque = _navigationController.navigationBar.opaque;
nav.navigationBar.barStyle = _navigationController.navigationBar.barStyle;
}
[_navigationController presentModalViewController:nav animated:NO];
});
}
}
i have checked it with my code and it is working ,ya but you have not give nib name here in this line and i have given may be that why it is not displaying your view.
KKPasscodeViewController *vc = [[KKPasscodeViewController alloc] initWithNibName:nil bundle:nil]
-(void)applicationDidBecomeActive:(UIApplication *)application {
RootViewController *vc = [[RootViewController alloc] initWithNibName:#"RootViewController" bundle:nil];
dispatch_async(dispatch_get_main_queue(),^ {
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
nav.modalPresentationStyle = UIModalPresentationFormSheet;
nav.navigationBar.barStyle = UIBarStyleBlack;
nav.navigationBar.opaque = NO;
} else {
nav.navigationBar.tintColor = navigationController.navigationBar.tintColor;
nav.navigationBar.translucent = navigationController.navigationBar.translucent;
nav.navigationBar.opaque = navigationController.navigationBar.opaque;
nav.navigationBar.barStyle = navigationController.navigationBar.barStyle;
}
[navigationController presentModalViewController:nav animated:NO];
});
}
I get an orientation problem while using the following to code to display a view on top of a split view.
[window addSubview:aSplitViewController.view];
[window insertSubview:aViewController.view aboveSubview:aSplitViewController.view];
the plain view has a couple of buttons and labels.
So the problem I am facing is that the first view opens in landscape mode but the labels and buttons on the view are in portrait mode.
UPDATE: Here is some code so if anyone wants to see more details...
In my App Delegate
- (void) makeSplitViewController {
NSMutableArray *controllers = [NSMutableArray arrayWithArray:tabBarController.viewControllers];
// First tabbbar item
// detail view
detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
UINavigationController *navDetailView = [[[UINavigationController alloc] initWithRootViewController:detailViewController] autorelease];
navDetailView.hidesBottomBarWhenPushed = YES;
// root view
rootViewController = [[RootViewController alloc] initWithStyle:UITableViewStylePlain];
rootViewController.detailViewController = detailViewController;
rootViewController.navigationItem.title = #"List";
UINavigationController *navRootView = [[[UINavigationController alloc] initWithRootViewController:rootViewController] autorelease];
navRootView.hidesBottomBarWhenPushed = YES;
navRootView.navigationBar.barStyle = UIBarStyleBlackTranslucent;
splitViewController = [[UISplitViewController alloc] init];
splitViewController.tabBarItem.title = #"Face Sheet";
splitViewController.tabBarItem.image = [UIImage imageNamed:#"gear1.png"];
splitViewController.navigationItem.title = #"Face Sheet";
splitViewController.viewControllers = [NSArray arrayWithObjects:navRootView, navDetailView, nil];
splitViewController.delegate = detailViewController;
splitViewController.hidesBottomBarWhenPushed = YES;
[controllers addObject:splitViewController];
// Second tabbbar item
scoreViewController = [[ScoreCardViewController alloc] initWithNibName:#"TableViewController" bundle:nil];
scoreViewController.tabBarItem.title = #"Score Card";
scoreViewController.tabBarItem.image = [UIImage imageNamed:#"gear1.png"];
scoreViewController.navigationItem.title = #"Score Card";
[controllers addObject:scoreViewController];
tabBarController.viewControllers = controllers;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// Create tabbar
tabBarController = [[UITabBarController alloc] init];
//tabBarController.delegate = self;
// Set window
[window addSubview:splashController.view];
[window insertSubview:tabBarController.view belowSubview:splashController.view];
[self.window makeKeyAndVisible];
application.statusBarOrientation = UIInterfaceOrientationLandscapeRight;
return YES;
}
and here is the code in my SplashScreenView
- (IBAction) proceedButtonClick:(id)sender
{
// Initialize loginpopview
PhysicianLoginViewController *loginViewController = [[PhysicianLoginViewController alloc] init];
popOverController = [[UIPopoverController alloc] initWithContentViewController:loginViewController];
popOverController.popoverContentSize = CGSizeMake(350, 200);
popOverController.delegate = self;
// Set a notification to dismiss it later
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(loginViewControllerDone:) name:#"loginViewControllerDone" object:popOverController.contentViewController];
// Present popover
if ([popOverController isPopoverVisible])
{
[popOverController dismissPopoverAnimated:YES];
}
else
{
[popOverController presentPopoverFromRect:CGRectMake(485, 600, 100, 100) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
}
}
// Dismiss popview controller and setup the tabbar
- (void)loginViewControllerDone:(NSNotification *)notification{
[[NSNotificationCenter defaultCenter] removeObserver:self];
// Button in content view controller was tapped, dismiss popover...
[self.popOverController dismissPopoverAnimated:YES];
// remove subview
[self.view removeFromSuperview];
// set tabbar
i3EAppDelegate *appDelegate = (i3EAppDelegate *) [[UIApplication sharedApplication]delegate];
[appDelegate makeSplitViewController];
}
It would be great if someone could point out where I am going wrong. I have been stuck with this problem for quite a few days and I have tried everything that comes to my mind...
UIWindow has a subview that it uses for rotations and puts other views inside of that. You need to insert yourself into the root view (or something lower), not the window. Look at -[UIWindow rootViewController].
UIView *rootView = [[[self window] rootViewController] view];
[rootView addSubview:view];
This will work as long as you're using something with a root view controller. This will work as long as rootViewController isn't nil. If you're doing a raw "View Based" application, then it's usually best to pick another view and add your view as its sibling rather than digging through the undocumented hierarchy:
UIView *sibling = ... (some other view)
[[sibling superview] addSubview:view];