Drawing a Bar in iPhone / iPad - objective-c

How can I draw a simple BAR?
Like this:
Thank you.

You'll want to make a UIToolbar, put it at the bottom of your XIB, and put some buttons on it. Now, this will by default give you a regular black bar, with that standard black gloss. If you want to have a custom image, there are two solutions.
First is simply subclass UIToolbar and override its drawRect to draw a custom image. The code for overriding drawRect would look something like this:
//in some other code somewhere, preferably on init
self.image = [UIImage imageNamed: #"image"];
- (void)drawRect:(CGRect)rect {
[self.image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
Now, in iOS 5.0 there is something very useful called appearance but you have to be willing to only target 5.x+ iOS versions.
The second, which is simpler but less versatile, is to simply stick a UIImageView at the bottom of the XIB, and place some buttons on top of it. This is much easier than above, but is less extensible, is harder to modify, and is frowned upon in iOS for good reason - it breaks general iOS conventions (and you lose some very useful functionality).

Crimson has a nice idea but since his/her answer requires using UIToolbar, I'll offer an alternative:
Basically what you are showing there is some kind of progress bar, so ultimately whatever you want to display should be something subclassed from UIControl or even better, UIProgressView or maybe a UISlider.
Google around for custom progress view indicators or sliders. There are also good examples available here on Stackoverflow.

Related

Draw / lay out contents of a wide UIView inside UIScrollView, outside of a ViewController

I'm trying to make a large UIScrollView with various UI elements on it which is larger (wider) than the iPhone's screen.
I'd like to be able to lay those elements out in a UIView, and then load that UIView into the UIScrollView. This way, I can clearly see in Interface Builder what I'm doing with that large view.
How can I do this, with Storyboards active? I'm trying to do something similar to the #2 example here, but using Storyboards:
http://agilewarrior.wordpress.com/2012/05/18/uiscrollview-examples/
See if this tutorial from Ray Wenderlich helps, which goes into pretty good detail about UIScrollView :
http://www.raywenderlich.com/10518/how-to-use-uiscrollview-to-scroll-and-zoom-content
If you're doing layout programmatically, please take note of this important comment:
You might ask why we don’t do all of the above in viewDidLoad, and you’d be right to ask. The reason you can’t is that the view size isn’t definitely known until viewWillAppear:, and since you use the size of scrollView when calculating the minimum zoom, things might go wrong if we do it in viewDidLoad.
Good luck!

Clicking through NSWindow/CALayer

So I'm working on an issue I have when trying to do some simple animation using CAKeyframeAnimation, and I believe my problem is more related to not fully understanding how NSWindow, NSView, and CALayer work together. 
I have two main objects in question. MyContainerWindow (NSWindow subclass) and MyMovableView (NSView subclass). My goal is to be able to animate MyMovableView back and forth across the screen, while maintaining the ability to click on anything through MyContainerWindow unless you are clicking on wherever MyMovableView is. I am able to accomplish the first part fine, by calling -addAnimation:forKeyPath: on myMovableView.layer, and everything is great except I can't click through MyContainerWindow. I could make the window smaller, but then the animation would clip by the bounds of the window.
Important points: 
1) MyContainerWindow is initWithFrame to [[NSScreen mainScreen] frame], NSBorderlessWindowMask, defer no, buffered
2) I setWantsLayer:TRUE to MyMovableView
3) MyContainerWindow is clear, and I want it to be as if there wasnt a window at all, but need it so I have a larger canvas to animate on.
Is there something obvious I'm missing to be able to click through an NSWindow?
Thanks in advance!
My solution in this scenario was actually to use:
[self ignoresMouseEvents:YES];
I originally was hoping to be able to retain the mouse events on the specific CALayer that I'm animating, but upon some further research I understand this comes with the cost of custom drawing everything from scratch, which is not ideal for this particular project.

How does UIBarButtonItem know which UIBarStyle the UIToolBar uses?

In Xcode ui builder when one set the UIBarStyle of the UIToolBar (such as BlackTranslucent, for example), the UIToolBarItem matches the background images to it. How does the UIToolBarItem know which style it should use?
I'm trying to do a put a custom colored image on top of the regular background tile (programatically merge a given image on top of the background image). I want to the code to be generalizable enough so that it is able to handle all UIBarStyles. That means I want to know when UIToolBarItem decides which background to use and intercept it so I can compose the button image on the fly.
Without being able to see apple's implementation of UIBarbuttonItem, I posit that they do not, in fact, know what the style of their UIToolbar is. If you look closely, they have the same alpha as their toolbar, and the same overlay (indicative of a subview). Therefore, any image that is below this highlighted layer, added as a subview, should conform to the UIToolbar's style. If you want to use multiple images though (one for each barStyle), you can determine it with self.myToolbar.barStyle and plan appropriately at -viewDidLoad time. As for true image drawing, subclass UIToolbar and override -drawRect: and use [UIImage drawInRect:rect];

Building custom widgets like Safari's URL bar

I'm new to Cocoa, and trying to figure out how to build custom widgets (views?). I'm particularly interested in something like Safari's URL bar that acts and looks like a text field, but has buttons, or at least clickable components, at either end.
I've been doing some research – mostly looking at Hillegass's book and Cocoa and Objective-C: Up and Running from O'Reilly – on custom views and trying to build things with NSCells. It's still all pretty fuzzy to me... Am I on the right track with this line of research?
Can anyone give a quick break down of what widgets the URL bar is probably made up of?
Can anyone give me an idea of how this is done or, failing that, point me to some resources that would be particularly good at explaining this kind of thing?
You're on the right track. You want to subclass NSView. From there you can either implement the -(void)drawRect method to do your own custom drawing, or you can add subviews, or both.
//add some subviews
NSTextField * textField = [[[NSTextField alloc] initWithFrame:self.bounds] autorelease];
[self addSubview:textField];
NSButton * button = ...
[self addSubview:button];
You can also use the Interface Builder (now built in to XCode 4) to design the widget, and then hook up the parts with code.

Objective-C can someone explain how to programmatically display a view

I'm just not getting this, I want to display a view in my app when a user clicks a button.
I've gotten this far:
NSView* unitMarker = [[NSView alloc] initWithFrame: NSMakeRect( 20.0, 20.0, 80.0, 50.0 ) ];
How would I display this view with a red background?
Thanks
#Aaron: he says he wants to do this programmatically. Also he's using NSView, not UIView, so an iPhone tutorial would be almost irrelevant.
#Mike: Your description of what you want to do is a bit vague. We have a bit of code creating, a view, but no context to tell us exactly what you are trying to do. Do you want the view to come up in a new window or the same? Do you want to replace a view that's already there? We don't even really know your skill level.
I suggest you go check out the documentation for NSView: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSView_Class/Reference/NSView.html
I've gotten this far:
NSView* unitMarker = [[NSView alloc] initWithFrame: NSMakeRect( 20.0, 20.0, 80.0, 50.0 ) ];
How would I display this view with a red background?
You wouldn't, because a plain NSView doesn't draw anything.
First, you need to subclass NSView, implement drawRect: in that subclass to fill its bounds with red, and instantiate that subclass instead of NSView directly.
You should read the View Programming Guide.
How would I display this view …
You wouldn't. The view displays itself when it is appropriate to do so.
It won't ever be appropriate for it to draw itself until you add it to a view hierarchy. Every window has one, rooted at its content view. You need to add this view either to a content view or to some descendant view (subview, subview of a subview, etc.) of a content view.
You normally should not tell a view to display from your controller. That's the window's job. When you do change a property or properties of the view that affect what it draws, set the view as needing display, and let the window tell the view to display when it's appropriate to do that.
Say this out loud 10 times repeatedly:
Interface Builder is my friend.
I was able to put together a sample project doing exactly what you want to do in about 5 minutes by leveraging Interface Builder as part of the process. http://www.markdouma.com/developer/ShowWindowWithRedView.zip.
You can't show a view without placing it in a window first; by far the easiest way to do this kind of a thing is to drag out a second window in Interface Builder, set it to not be visible on launch, drag a generic NSView custom view onto the Window, set its class to be SRRedView (your red view subclass). As d11wtq posted, you override NSView's primitive drawing method like he shows (though personally I prefer NSBezierPath :-P).
In your controller class, you define IBOutlets, and then hook those up in Interface Builder. These provide you with a way to reference the important parts of your interface so that you can manipulate them programmatically.
I added one IBAction method, which the button in the main window is hooked up to call. That method simply tells the second window to show itself.
- (IBAction)showWindowWithRedView:(id)sender {
[windowWithRedView makeKeyAndOrderFront:nil];
}
In the 8 years or more that I've been doing Cocoa programming, I don't think I've ever needed to resort to manually creating windows and views. It has always been much faster to simply load another nib file that contains the windows or views I need to display. Using Interface Builder along with Xcode to create your app is quite a bit different than how other IDEs work. (Specifically, when you arrange stuff in Interface Builder you're not generating code as much as you are creating instances of UI objects and then "freeze-drying" them in their current arrangement into a .nib archive file. When you launch the app, they are brought back to life. Or at least that's the way I think about it).
You need to subclass NSView and implement drawRect:.
In this case you're just going to fill the entire rect with red.
#interface MyView : NSView {
}
#end
#implementation MyView
-(void)drawRect:(NSRect)dirtyRect {
[[NSColor redColor] set];
NSRectFill(dirtyRect);
}
#end
That's an extremely basic example that does what you want, but if you want to do more complex things (adding borders (strokes) or drawing curves (paths) etc), then you need to learn all the drawing classes available to you.
Scott Stevenson has written some easy to follow tutorials on this:
http://cocoadevcentral.com/d/intro_to_quartz/ and;
http://cocoadevcentral.com/d/intro_to_quartz_two/