How to use NSTitlebarAccessoryViewController? - objective-c

Can anyone tell me how to use NSTitlebarAccessoryViewController, to add subview to a view with an example? As I am new to mac programming you may have to explain from basics. Please.

NSTitlebarAccessoryViewController is for adding subviews to the windows title bar.
Here is a example:
Set up a view in interface builder. Go to the `applicationDidFinishLaunching: method to add the view to the title bar.
The code would be the following:
NSTitlebarAccessoryViewController* vc = [[NSTitlebarAccessoryViewController alloc] init];
vc.view = self.view;
vc.layoutAttribute = NSLayoutAttributeRight;
[self.window addTitlebarAccessoryViewController:vc];
You can play with the size of the view to make it fit into the title bar.
Update
OS X 10.11 introduced the new layoutAttribute left.
There are now three layoutAttributes in total. bottom adds a bar beneath the titleBar (like the tabBar) and left/right places your subview within the titleBar.

Related

Preventing user to access a view in a NSView hierarchy

Maybe this is my strange understanding of the NSView hierarchy, but the question is:
I have a window with a SplitViewController which has the classic two child views.
When the user clic a button on the toolbar I add a 'work in progress' view as follows:
NSView* workingView;
// creating the view
...
[self.view addSubView:workingView];
where self is the SplitViewController object. My understanding (also from iOS programming) is that the split view controller has three views: left and right views and the workingView onto them(?)
The problem is that, even if workingView is covering the entire window, the two views are still accessible. In iOS developing we can set the userInteraction to NO so only the desired view is active. What about OSX?
Can I disable interaction with the split view controller views and let only the workingView be active?
Thanks
EDIT:
I followed #Wain hint and I created a new ViewController that contains my work in progress view.
I presented it using the presentViewController:animator technique. In this way I can hav more control about the positioning of the view.
In the custom animator I simply colored the view to see what is happening. Really the way the animator adds the new view controller seems nearly the same as adding a classic view onto the split view (like did before). In fact the result is the same: even if my working view covers two buttons belonging to the left side of the split view, they are clickable!
-(void)animatePresentationOfViewController:(NSViewController *)viewController fromViewController:(NSViewController *)fromViewController {
NSViewController* bottomVC = fromViewController;
NSViewController* topVC = viewController;
topVC.view.wantsLayer = YES;
topVC.view.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;
topVC.view.alphaValue = 0.0f;
[bottomVC.view addSubview:topVC.view];
topVC.view.layer.backgroundColor = [[NSColor blueColor] CGColor];
topVC.view.frame = CGRectMake(10, 10, 100, 100);
[NSAnimationContext runAnimationGroup:^(NSAnimationContext* context){
context.duration = 1.0f;
topVC.view.animator.alphaValue = 1.0f;
} completionHandler:nil];
}
I know something is missing or wrong... May you help me in understanding what is going on here?
You should create a new view controller to manage your new view and then present it as a form sheet. The display style is slightly different on each platform but this is the correct approach.
An alternative is the screenshot the split view and pass the image to the new controller which is presented full size. It then applies an overlay and adds its own content view in front of the background image.

iOS 8 - Modal in Popover

I have a popover with TabBarController in it. In one tab there is a TableViewController with a list of names. And there is a plus button, that has a modal segue to AddCharacterVC for adding new names.
In iOS 7 I do it like this:
AddCharacterViewController *acvc = (AddCharacterViewController *)segue.destinationViewController;
acvc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
acvc.modalPresentationStyle = UIModalPresentationCurrentContext;// so it does not take full screen in popover
And in AddCharacterVC I set content size like this:
- (void)viewWillAppear:(BOOL)animated {
CGSize size = CGSizeMake(320, 480); // size of view in popover
if (IDIOM == IPAD && [self respondsToSelector:#selector(preferredContentSize)]){
self.preferredContentSize = size;
}
And it works perfectly.
However, in iOS 8 modal view does not cover the whole popover, leaving TabBar visible. The user can tap on it or not, anyway modal view won't unwind properly.
I've tried:
setting acvc.modalPresentationStyle to UIModalPresentationOverCurrentContext
tried to set TabBar hidden
checked in storyboard that edges of TableVC extend under Bottom Bar and Bottom Bar in Modal View (AddCharacterVC) is set to none
All with no results.
Now the only thing I can think of is to try making modalPresentationStyleCustom and use UIPresentationController (I'm trying to do it now, but I haven't done it before). Am I missing something? Could there be other way to do it? Sorry, I cannot post images here yet. Many thanks in advance!
Ok, so I've set the modalPresentationStile to UIModalPresentationCustom, and used UIPresentationController - I've just copied code from WWDC-14's LookInside project and modified it a bit.
I'm not sure if it was the best solution, but it worked in my case.

How does a UIAlertView determine the vertical and horizontal center of the view it's within?

I'd like to use this same solution with my UIView to get the same result.
I have a UIView with a UIScrollView. These are embedded in a UINavigationController.
A customer adds an item to their basket and I would like to give them a confirmation message. Right now a little basket UIBarButtonItem updates a title within to show the number of items. This is fine but not every user/customer will notice this.
I don't really like the style of a UIAlertView for this situation. So I'm going to add my own UIView and style it how I want to.
I'm trying to figure out how to get the UIView to show up in the center of the window. Whether the customer is using an iPhone4 or iPhone5.
UIView code:
UIView *confirmationPopup = [[UIView alloc] initWithFrame:CGRectMake(10, 200, 300, 100)];
[confirmationPopup setBackgroundColor:[UIColor redColor]];
// confirmationPopup.center = [confirmationPopup.superview convertPoint:confirmationPopup.superview.center fromView:confirmationPopup.superview.superview];
[[[self navigationController] view] addSubview:confirmationPopup];
The popup view is centered horizontally automatically but not vertically. I've tried to play around with the line you can see I've commented out but it doesn't center the UIView in the center of the window. It appears to be centering it inside the NavBar
Would appreciate some solutions.
Don't hard-code; use auto layout. You might be helped by my custom class for this purpose, an imitation alert view substitute that you can configure however you like. It takes advantage of iOS 7 custom presentation view transitions. (Of course in iOS 8 there will be even more support for this kind of thing, i.e. UIPresentationController.)

Could not set tab bar image in Xcode 4.2 Programmatically

I created new tab bar project in xcode 4.2 and there is no app delegate xib file. Project has two navigation controller. I can set name of tab bar but couldn't set image. I am completely fed up with many tries. FirstViewController *firstView = [[FirstViewController alloc] initWithNibName:#"FirstViewController_iPhone" bundle:nil]
firstView.title=#"Birthdays";
firstView.tabBarItem.image=[UIImage imageNamed:#"bottomleft.png"];
SecondViewController *secondView = [[SecondViewController alloc] initWithNibName:#"SecondViewController_iPhone" bundle:nil];
secondView.title=#"Settings";
secondView.tabBarItem.image=[UIImage imageNamed:#"bottomright.png"];
UINavigationController *navController2 = [[UINavigationController alloc] initWithRootViewController:secondView];
navController2.navigationBarHidden=YES;
[viewControllers addObject:navController2];
Here you can see what sort of output I am getting.
Hard to tell from the code you posted, but you probably want to set the image on the tabBarItem of the UINavigationController (navController2), since it looks like that is what you directly add to you UITabBarController:
navController2.tabBarItem.image = [UIImage imageNamed:#"bottomright.png"];
The reason you can set the title is that navigation controllers by default automatically have the title of their current child view controller.
It looks like you successfully replaced the left image, however it has no transparent areas. Did you follow the guidelines for designing the tab icon?
http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/mobilehig/IconsImages/IconsImages.html
You need to use a white image on transparent background. If your background is not transparent, the whole image will just be a blue box, like the one on your left tab.
Example: To make a tab with a star on it, draw a completely white star on a transparent background. Do not use any other colors than completely white and transparent black.
You never need to do this:
[UIImage imageNamed:#"bottomleft2x.png"];
UIImage will automatically determine whether the #2x is needed or not based on the screen scale, so make it simply:
[UIImage imageNamed:#"bottomleft.png"];
Unless, of course, your resource name is actually bottomleft2x#2x.png
dude tab bar only allows white color and transparent background so if u want the picture to be like a birthday cake then draw a white birthday cake on a transparent background then add some transparent pixel in side the cake to create the looks of a cake instead of just the outline of the cake then u can set yr image to tab bar

Rotating UITabBarController Icon

I have an UITabBar in my application. One of the tab bar icons looks like a loading symbol. When the user presses the loading button I want the icon to spin/rotate until the loading is done. Should I use UIImageView to animate or something else? How should I make this happen?
Jacos, unfortunately you cannot do that with the UITabBarController and manipulate the tabBarController's tabBar properties. My best bet would be that you use a UIToolBar and assign a black color and make it appear like a tabBar and have buttons added in them as a subView so that they look like tabBarItems.
Its much more customizable, and you can even provide a scrolling experience and add more buttons to it.
I know this question is 4 years old but I had the same problem and managed to fix it by reading the tutorial in here:
https://medium.com/#werry_paxman/bring-your-uitabbar-to-life-animating-uitabbaritem-images-with-swift-and-coregraphics-d3be75eb8d4d#.bjfpbdnut
The main point is to get the view for desired UITabBarItem and the get the UIImageView from it in viewDidLoad:
UIView *plusView = self.tabBar.subviews[1];
self.plusImageView = plusView.subviews.firstObject;
self.plusImageView.contentMode = UIViewContentModeCenter;
Then in didSelectItem method you can do this:
[UIView animateWithDuration:0.4 animations:^{
[self.plusImageView setTransform:CGAffineTransformMakeRotation(M_PI/4)];
}];
My code only rotate the image view for 45 degrees but you can change as you wish.
I guess you could change the UITabBarItem's icon on a timer, but that seems pretty kludgey. You would have to pre-render each frame of your "loading" icon rather than rotate an ImageView.
Another hackey solution would be to add your ImageView to the UIWindow and move it on top of the TabBarController's TabBar (adding it to the TabBar itself is asking for trouble).
You shouldn't try to animate the actual UIImageView within the UITabBarController. I would take this approach:
Set the image for the relevant tab to nil or a blank image.
Create a UIActivityIndicatorView and add it over the tab bar. Position it over the correct tab.
[self.tabBarController.tabBar addSubview:activityIndicatorView];
When your loading task has completed, restore the normal image to the tab and remove the activityIndicator from the tab bar.