custom View IOS [duplicate] - iphone

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

Related

Iphone - Drawing into a view : philosophy and interactions

I've understood that I need to subclass a UIView t be able to draw inside it.
The thing I don't understand yet, is the philosophy of the way i must be done...
Let's say I have a view controller, and depending on context, I may want to draw a line into one of the subviews it manages, or a circle, or a rect, or a processed graphic. Or lets say two points that are moving inside a view into a defined rect and that display a bigger point when they are close.
How may I subclass and define the subview to make it able to do this only into its drawRect method ?
How does the controller, that manages more than this simple UIView (let's imagine you have a view controller that manages a view inside which there are many other view, and you want to make some drawings in two of them), and that knows what is needed to be drawn into the correct view (it's a controller, isn't it ?), may interact with the views ? And when the drawing is done, how may the views interact with the controller ?
I've read many doc about drawings (apple, web, forums, tutorials, ...), but I still can't touch the philosophy of the way this must be done.
it's very simple. Make a new class, OliverView, which is a UIView. (ie, it is a subclass of UIView.) In that view, make it draw stuff in a fancy way, inside drawRect.
Now make a UIViewController, called OliverVC. In storyboard put an OliverView inside OliverVC. (beginner explanation of how to do that).
In the OliverView, have properties "hours", "minutes", "seconds".
Now, in OliverView - in the drawRect - have a fancy way to display those values. (Pie chart, glowing letters, animation - whatever you want.)
Now, up in OliverVC, do some calculations to determine the time in Zimbabwe, for example.
Once you want a time displayed, simply set those properties in OliverView - - and you are done.
Your colleague could be programming the OliverView. You need know nothing about how she is going to display the time. Conversely, your colleague need know nothing about your calculations in OliverVC..
So, it's simpleL One part has the job of displaying the data. One part has the job of coming up with the data (doing whatever sort of calculation is relevant in the app).
It's the only architecture possible in a "real time" screen device where the views can and do change at any time.
In answer to your question below: you've forgotten that quite simply, if you have a button that would be a whole separate element. (Perhaps sitting "on top of" the OliverView.) So, it's easy!
The -drawRect method in your UIView subclass defines the onscreen appearance of the view. All drawing is done in -drawRect. Your UIViewController calls methods on its UIView to tell it to draw something differently or to perform some other action.
The UIViewController manages everything to do with the view that is not inherently associated with the drawing of the content. Data associated with the view is often stored in the controller.

Grasping the concept of UIviews and UIViewcontrollers

A couple of weeks ago i have started my research in Iphone app development and after alot of hello world applications in different settings i am now ready for my very first application based on the MVC design pattern used in Cocoa.
This opens up alot of questions for me though and after reading the different class references about UIViews and controllers i am stuck in trying to figure out which one i should be using.
In my application i am trying to create a grid of small rectangle's with each rectangle having a different text value on them, to be more specific, i am trying to create a simple calender that will display all the days of a month in a grid.
Every rectangle is a instance of a class i named Tile, in this class i want to implement the drawRect method to draw the rectangle for me and set the text value to the day it should represent.
In order to implement this i have done some research on how this should be done.
From what i have learned so far is that UIViewcontrollers do not really display anything, they are basically sitting there waiting to respond to any events from their children.
In my application i would translate this to the Controller that will respond to each touchevent on a tile.
A UIView however is also a container but one for objects that will need drawing methodes like drawRect. This would translate to the grid that will hold all of the tiles if i'm correct.
Except, i have no clue what subclass i should use for each tile, i have the feeling i am really missing some basic knowledge here but i just can't figure it out. Would really appreciate it if anyone could point me in the right direction with this.
If there were any two apple document you should read, it is the one about UIViewControllers which can be found here and the one about UIViews which can be found here. The UIViewController, as you mentioned, is more about integrating with the iOS system than being a visible component. It has a reference to a UIView, and that UIView is the root node in the visible tree of elements which starts at that View Controller.
In iOS programming you don't really need to worry about drawing rectangles, because for the most part you will be extending elements which know how to draw themselves and then just telling them where to go. The basic visible element in this case, is the UIView. There are many different kinds of UIViews (see the graphic in the UIView programming guide link), so for your case you could use a simple UIView with a background image set to your calendar box graphic, and add a subview of type UILabel. UILabel is a subclass of UIView, so you know it will be something visible as well.
Once you grasp these concepts (which can take a long time) Interface Builder will start to make more sense and you can start doing some of these things with it - and understand how its working. In essence it will create the hierarchy of a UIViewController referencing a hierarchy of UIViews automatically, then you.
Tile should be subclass of UIView since you want to drawRect your "days". Then you can add as many Tiles as you want to your UIViewController.view and manipulate them from UIViewController code (.m file).
But you can add UILabels to your Tile view and manipulate them by setting their text property. In this case you won't need to override drawRect: at all, UILabel will do the rest for you, but you will have to programmatically add this labels to your Tile (e.g. in Tile's init method) or in Interface Builder. In the last case you will have to load them from XIB using [[NSBundle mainBundle] loadNib:owner:options:] method.

Cocoa touch view with multiple identical subviews

I'm having my first foray into Cocoa Touch programming (and one of my first into Cocoa in general) and writing a simple game for the iPhone, though this question is about cocoa touch in general.
The main UI consists of a strip of identical acting buttons (only varying in colour) arranged horizontally across the screen. Although they act like buttons they need to have a custom drawn appearance. Each responds to touch events in the same way, triggering other events in the application.
I want to define a custom view, partly to have more control over the behaviour than just having a bunch of standard buttons, and partly to learn more about cocoa programming.
Should I define a main view with an array of subviews each of which draws itself and forwards touch events? Each button should do standard things like show a pressed state when touched and so on. Are there any pre-existing container views for this kind of scenario?
Or should I just define one main view which draws the whole strip and detects where a touch occurs? I feel this is a badly engineered approach - I shouldn't be programming hit test code.
Edited to clarify the question
The more lightweight approach is to add sublayers to your UIView's layer. Use hitTest: to dispatch touches you receive on you UIView to the CALayer instance that needs to receive it.
If you need more of the UIResponder behavior (touchesBegan etc.), you might want to go with subviews instead of sublayers as that would allow you to handle the events directly in the objects rather than having to dispatch them from a central responder (your main UIView).
Consequently, the essential bit may be just how much of the behavior associated with your individual buttons should be known (handled) by the your main UIView. If it makes sense to have everything controlled from a central place, you can put all the logic in the UIView and just use sublayers for lightweight display purposes. If it makes more sense to put the behavior into the buttons themselves, they shoudl be UIResponders and as such subclass UIView and be added as subviews of your main view.
You should use an array of subviews - that way each "button" class knows how to draw itself and its superview (your stated "main view") places the buttons where they need to go.
And second on the NDA: just talk about the iPhone.
If you have a lot of buttons and want to do fancy things with them, I recommend using layers. Your UIView will handle interpreting which layer had the touch (hit testing) and
respond appropriately. If all you're doing is managing a whole bunch of buttons with various effects and animations, this might be an easier route.
As for bad engineering, not at all. If you take a look at the associated guides, you'll see core animation and layers does require hit testing (though that's relatively easy), but it's far cleaner than the UIView doing all the drawing and more efficient than many subviews. It slips right between those two approaches nicely.
Full disclosure: I'm just wrapping my head around how to best leverage this stuff myself, but for more complicated interactive controls.
You can layout your view in Interface Builder. Simply drag a bunch of UIButtons in your view controller's view.
To respond to events, you define an IBAction in your view controller and connect the buttons to it.
This is all very basic. I really suggest that you at least walk through the iPhone programming introduction that Apple has online. It will teach you iPhone and Interface Builder basics.

iphone interface overlay pass-through events

alt text http://www.davidhomes.net/question.gif
I'm farily new to iphone dev (<3 months on my free time) and I'm starting development of my second app.
From the image, I'm adding a number of UIViews as subviews to my main UIViewController.view, the number of Views to add varies based on user selectable data.
Each view contains several controls, a label, a UITextField and a Horizontal UIViewPicker.
For simplicity I put a (VERY ROUGH) mock-up here with only two buttons.
Because I want to improve the GUI, I want to overlay an UIViewImage as the top sub-views of the added UIView, something like in the image.
The question is on passing through the events to the objects below it. I've read somewhere that one way was to use clipping, but the actual shape is more complex than just an oval frame.
Somewhere else I read that one could add four UIImages, one at each border, which would let the events pass through this hole. Seems like a dirty solution to me (Although I'm sure it would work)
Any ideas about the best way to do this? Any links to a tutorial or recipe online?
Your help is appreciated
thanks
david
Have you looked at protocols? You can define protocols for your views or objects, and the users of that object (the subviews underneath for example) can implement the protocol, set itself as the objects delegate and when actions happen they will notified through the protocols. So for example
An AboveView will declare a protocol that declares methods when a certain gesture was senced by that view so something like
-(void)didMakeCircleGesture...
as a property the underneathview will have a delegate, so in your method that actually sence the gesture youll have at the end something like
[delegate didMakeCircleGesture];
in turn the delegate is the view underneath or something, and it will conform to the protocol defined by the AboveView, and as part of it it will have to declare the method didMakeCircleGesture, so as a result when one makes a circle gesture in the AboveView the underneath view that conformed to the protocol will be told of the event and it can take appropriate action

Architecting a visual grid of 'buttons'

I'm trying to design how to implement a relatively simple application.
I want to create a grid of 'squares' that cover an entire screen. Each square should have the ability to respond to touch events, and then have an on/off state. For example, if I touch an 'off' square, and then drag my finger across 10 other squares, I want them all to turn on. And vice versa.
I'm not sure of the memory overhead of just creating a grid of 150 buttons. Also buttons don't have a settable state, from what I can see. I was also thinking of subclassing UIView and implementing UIResponder methods. It feels like I should be creating an array of array of buttons (or subclass of UIViews), but I'm not sure if that's possible.
I'm assuming that I can tell what square I'm on by getting the location of the touchevent from the UIResponder methods. Do I need to create my own version of a myButton by subclassing UIView, and have a on/off state property, along with UIResponder methods, and then create an array of myButtons?
UISwitch is the only thing that does this at the moment, though some have had good experiences using the UISegmentedControl for this as well.
Beyond that, you'll have to change the style/color of a regular button or image in code, which is what a lot of application developers do so it looks and reacts exactly the way they want it to.
Unless you need more of UIView's event handling stuff, you'll get the best performance if you use a single view and give it a -touchesBegan:withEvent, -touchesMoved, and -touchesEnded methods. Then use a custom drawRect method to draw your individual squares in either on or off states. You could also use layers, but trying to lay out 150 views is asking for trouble.