I wanted a control like the UISlider, but with two thumbs instead of one so you could specify a range instead of just one value. I read up on other people looking for the same thing and suggestions about making new controls were over my head.
So I decided to setup what I wanted in a nib and then created a view controller to handle its behavior. It actually works really well this way accept for 2 things.
1) To load my 'custom control' into another nib I need to do it through code like this...
MaxMinSliderViewController *feeMaxMinSlider =
[[MaxMinSliderViewController alloc] init];
[self.view addSubview:feeMaxMinSlider.view];
feeMaxMinSlider.view.frame = CGRectMake(20, 20, 280, 54);
...instead of dragging and dropping into other nibs like normal IB controls. Is there an easy way to be able to do this?
2) In all my reading about doing this, its seems as though I was supposed to (to do it the right way) subclass UIView instead of UIViewController. I couldn't setup the UIView correctly and get it working though.
Thoughts?
instead of dragging and dropping into
other nibs like normal IB controls. Is
there an easy way to be able to do
this?
Nope! There's only an incredibly hard way!
Assuming you manage to convert your class into a custom UIView instead of a UIViewController you can do part of this quite easily within Interface Builder (depending upon what kind of init method your custom control has).
Within Interface Builder drag and drop a plain old UIView from the Library Window onto your view and position/size it as required.
Then with the UIView selected, switch to the Identity tab of the Inspector Window (the tab with a little (i) icon on it) and change it from UIView to the name of your custom class. This causes an instance of your custom class to be instantiated when the NIB is loaded, instead of an empty UIView.
You can then hook up the view to an IBOutlet etc as normal.
The advantage of this approach is the ability to position and size your control visually etc. It does however only appear as a rectangle, and you don't get the ability to graphically configure the additional properties of your control as you would with a UIButton or similiar control which Interface Builder has additional support for.
I find this technique great, as I'm not that much of a visual thinker and find it hard to picture in my mind how things will look when I read a section of code containing lots of frame = CGRectMake(20, 20, 280, 54) etc. Being able to do it visually with a mouse is much better for me.
There is an Interface Builder Plug-in Programming guide, but it only mentions Mac OS X, not the iPhone.
Also, as of XCode 3.2.1, there is only a new project template for creating a Mac OS X IB Plug-in; there is no such project template for iPhone (Cocoa Touch). So my guess is this is not applicable for the iPhone.
Related
I am using xib-s for my UITableViewCells on iPhone. Now I need to convert my app to universal app. Do I have to create new xib-s (looking exactly the same way) for the iPad version? My current problem is that I am using grouped UITableViews. As the left and right margins on both devices differ, some of the controls on iPad are partly "out of the cells".
In case I need new xib-s (looking exactly the same way), do I need separate properties for the controls in the ViewController? For example, for a label named myLabel, do I need a second property myLabelIpad or is there a better way to handle that?
Cheers
My suggestion is to create new xib. But if there are small changes , then you can maintain one xib. However it depends on how different your iPhone / iPad versions are. For example, if the iPad version is just a bigger version of the iPhone one with a few extra buttons, etc, it's easier to use one UIView and just set the frames of the subviews appropriately.
First understand what you are up to. How do you want your iPad app to look like? How does it navigate. Ceratinly you want to leverage from the lager screen of the ipad. When ever you do that and the auto-resizing mechanism is not sufficient (which it rarely is) then go for a separated xib file.
Second - for each XIB which hosts the same number and types of UIView and UIConrol subclasses, you should be able to use the same view controller for two separate XIBs. Just link all conrols within both XIB to the related IBOutlet properties and IBAction methods alike.
However, when you take leveraging from iPad capabilites seriously then you are like to end up with a different set of view controllers. That is when you can combine the controls of several iPad views wihin one single iPad view and similar cases.
Nevertheless, think of using popups. The content of a popup could nicely correlate to what is a full screen on the iPhone. In that case you can use the same view controller again within that popup container.
Does this sort of answer your question? If not, then please be more specific.
Actually you can retain the same Table cell xib files. You just have to get the Auto resizing masks of the cell and its subviews right.
I have defined a UIView in the header file named rectangle0
I got a question in regards to IB vs coding a view. Please see the following code example:
rectangle0.frame = CGRectMake(0.0, 70.0, 320.0, 190.0);
Now I can re-create the look of the view easy enough in IB except for the coordinates which are greyed out.
So by calling this code in an IBAction after designing the UIView in IB I can display in the app.
[self.view addSubview:rectangle0];
Now the last line of code will call this view to appear at the set coordinates if I code it - but if I build in interface builder I can make it look exactly the same, but it appears from Y coordinate 20 (just under the status bar) and I can't set the coordinate upon calling it - is there a way to do this??
The UIView is being build outside of the ViewController and then linked to it in the connections inspector.
cheers Jeff
I have added an image to show what screen I am using - as you can see the x and y coordinates are greyed out, it would be great if I can set those to something else.
A view inside the NIB is just an object like any other. It is made to be reusable and I believe that is the key point that resulted in the coordinates being greyed out.
Greying out the position makes the developer worry about where is the view going to be placed. I say that because the position is pretty dependent on the container that your view object is going to be added to.
Although it is just my personal opinion and I am looking forward to hearing if there is indeed a way to do that.
You (effectively) said the view is managed by a view controller. Before you can resize the view, you need to change the Size setting in the view controller's Simulated Metrics to "Freeform". (It is probably set to "None" by default.)
It seems like more and more OS X apps these days are doing all kinds of fancy drawing stuff for custom controls. Apps like Twitterific, Things, EventBox, Versions just to name a few....
So basically I'm looking for any information on how to get started doing this kind of thing. Not sure if it is just done by subclassing controls and using custom drawing or if it is something entirely different.
Any help is greatly appreciated. THanks!
It depends entirely on what you want to do.
The "Show Raw Properties" button in Versions for instance is an NSButton subclass, because basically what we needed is standard button behavior with our own look. One way to subclass a button is to simply implement your own -drawRect:(NSRect)rect method in the NSButton subclass, but we decided to stick with the way NSButton is implemented in Cocoa, meaning most drawing is done by the button's cell, so the implementation looks like this:
In the NSButton subclass:
+ (Class) cellClass
{
return [OurButtonCell class];
}
- (void)drawRect:(NSRect)rect
{
// first get the cell to draw inside our bounds
// then draw a focus ring if that's appropriate
}
In the NSButtonCell subclass (OurButtonCell):
- (void)drawInteriorWithFrame: (NSRect) rect inView: (NSView *) controlView
{
// a bunch of drawing code
}
The Timeline view in Versions is actually a WebView, the page that you see in it uses javascript to collapse headers you click on.
The rule of thumb I use for where to start out with a custom control is:
To customize the look of a standard Cocoa control:
subclass the appropriate control (like e.g. NSButton and NSButtonCell)
stick as close as makes sense to the way the default control is implemented (e.g. in a buttoncell, start from the existing attributedTitle instance method to draw the button title, unless you always want to draw with the same attributes regardless of what's set up in IB or if you need to draw with different attributes based on state, such as with the trial expiration button in Versions' main window)
Creating an entirely new UI element:
subclass NSView and implement pretty much all mouse and key event handling (within the view, no need to redo "hitTest:") and drawing code yourself.
To present something that's complex, of arbitrary height, but isn't a table:
See if you can do it in HTML, CSS and JS and present it in a WebView. The web is great at laying out text, so if you can offload that responsibility to your WebView, that can be a huge savings in pain in the neck.
Recommended reading on learning how to draw stuff in your own custom view's drawing methods: Cocoa Drawing Guide
Customizing the look of for instance an NSTableView is an entirely other cup of tea, thanks to the complexity of a tableview, that can happen all over the place. You'll be implementing your own custom cells for some things you want to do in a table, but will have to change the way rows are highlighted in a subclass of the actual NSTableView object itself. See for instance the source code for iTableView on Matt Gemmell's site for a clear example of where to draw what.
Finally, I think Abizer's suggestion to go check out the code of BWToolkit is a great idea. It might be a bit overwhelming at first, but if you can read and understand that code you'll have no trouble implementing your own custom views and controls.
Have a look at some excellent example code: BWToolkit
I am quite new to the whole IPhone development thing and was playing around with the Three20 library. The samples for this library showed me an easy way to create a nice looking button with styles etc and this to my view:
TTButton* button = [TTButton buttonWithStyle:#"forwardActionButton:" title:#"Login"];
[button setFrame:CGRectMake(245, 160, 65, 33)];
[self.view addSubview:button];
Works great. Now I have created a nib file in interface builder with my whole view layed out including all sorts of textfields etc.
What I would like to do is, is to create a placeholder for a button in Interface Builder and in my viewDidLoad method replace this placeholder with the actual TTButton instance. This would prevent my from having to call setFrame with an hardcoded location and instead make the whole interface design process much more free.
I have already tried creating a UIView object in interface builder, changing the type to TTButton and then assigning a new instance but seems to put the new button at coordinates location 0,0.
Can anybody point me in the right direction on how to achieve this?
waseem,
Unfortunately three20 does not use interface builder at all. The best thing you can do is layout a mock-up view and grab button x-y locations from that, then use those to update your TTButton locations in code.
I am trying to create a toolbar programatically (rather than via IB) very similar to the toolbar featured in the iPhone app:
Currently I've been experimenting with the UIToolbar class, but I'm not sure how (and if?) you can make the toolbar buttons centrally aligned and large like that in the iPod app.
Additionally, regardless of size, the gradient/reflection artwork never correctly respects the size and is stuck as if the object is the default smaller size.
If this cannot be done with a standard UIToolbar, I guess I need to create my own view. In this case, can the reflection/gradient be created programmatically or will it require some clever alpha tranparency Photoshopped artwork?
The best thing you can do is:
create MyToolbar.h and MyToolbar.m : MyToolbar can be inherited from UIToobar
create an empty xib named MyToolbar.xib
In Interface Builder, add a new UIToolBar with "IB->Tools->Library"
With "IB->Tools->Inspector", change the class identity to "MyToolbar"
Now, you can customize your toolbar with IB or with xCode as you want.