I've got a subclass of UIControl which represents a slider switch, with a variable 'percent' which stores the current position of the slider, i.e. 0.0 means the slider is on the left, 1.0 means the slider is on the right. I have two images which look like speech bubbles, and when the user clicks the slider I want to display one of these images (they are the same size but look different, designed so one is displayed if percent <= 0.5 and the other one if percent > 0.5) and have the 'tail' of the speech bubble follow the slider (i.e. the frame is set as a function of the percentage).
I have created a custom UIView for the image which changes the image to display via a boolean parameter. I have tried creating a parameter in the UIControl subclass that draws the UIView along with all the other drawing, but I need to draw it outside the UIControl's rect, which can't be done from inside the UIControl's drawRect: method. What would be a good way of managing these two views and making sure the speech bubble always updates when the percentage value of the UIControl changes?
Sounds like your UIControl should simply be:
Tall enough to contain the bar and bubble view
Transparent (so that you can see behind the part of the view where the bubble "slides")
Or am I missing something?
First off, make sure the continuous property is set to TRUE in your UISlider.
Then, make sure you have an IBAction in place to receive update events from your UISlider. You can make the connection easily in Interface Builder (built into XCode 4) or you can do it programatically using UIControl's addTarget:action:forControlEvents: method.
And lastly, inside that IBAction you can now change the frame of your "speech bubble" UIView (make sure to link that up to your parent view controller as a member in your #interface .h file). Where it appears in relation to the slider is left to you as a homework assignment (cause it's really implementation specific -- or, to put it another way, how it appears is up to each individual app & programmer).
I hope this information helps you out!
Thanks for the answers - it turned out the best way to do it was to declare a delegate protocol for my custom UIControl, and assign the speech bubble view as the delegate. Then I made a method that tells the speech bubble to update location (passing in the location) and called that from the UIControl whenever the position of the control updated.
Probably the simplier way is to add to the UIControl a property pointing to the UIView and move it around in the method(s) where you change the control state. Of course to do that you need to create a class like MyCustomControl that extends UIControl.
Related
I'm building an iOS application and I try to determine the best way to implement this :
I have a main UIViewController (MainViewController) that displays a simple view. This view contains a button that let the user add an object (let's say a Circle) to the main view. The user can add multiple circles by pressing the button and move each of them by dragging them. The circle objects should have their own color (randomly chosen).
The question is: what is the best way to implement this?
Should I create an other UIViewController subclass (CircleViewController) for the Circle object, whose view actually draws the circle?
And then, when the user presses the button, should I create a new instance of this CircleViewController and add its view to the MainViewController?
When the user double-tap a circle, it should disappear... How can I send a message to the mainViewController to tell it to remove the concerned CircleViewController's view?
Thank you very much for your help.
If your object is really as simple as a circle you should look at Quartz in Apple's Documentation and the method drawRect: in UIView. If you are doing something more like an image you could subclass UIView and put your code in there. Either way, you do not need to create new viewControllers.
All I see is a list (which looks like a rolodex), how do I make this like the combo box option?
I haven't tried this, so I can't say that it will 100% work, but ths is what I would attempt to do:
Extend UIPickerView and initially give it only enough height for one row
In the new class, intercept touchesBegan: so that if the control is in the 1 row mode it will first expand to the full height (using an animation of course). I would probably NOT pass touches on to the super class in this mode
If the control is already in the full height mode, let the touch pass on through to the super class.
Add some other communication with other components on the screen so that when the user touches them, the extended UIPickerView shrinks back to it's 1 line height form, with more animation.
To make all of that work you probably need all your controls in a scroll view that does proper auto layout so that as you change the frame size of the UIPickerView thingie the other controls move around appropriately.
I agree with Henrik that this is very non-Apple however. It seems the prescribed Apple implementation would involve a tableview cell with a disclosure button that takes you to another screen containing the picker. I know the Apple HUI guidelines don't cover all cases, but it seems they probably cover this one.
I have an app with an image view. When the user clicks on this view I want to run some code which will change the colour of a label and then hide this view
I have everything setup in the interface, i.e. Outlets etc, but I dont see any events available to associate
Can anyone help or point me in the direction of a good tutorial asap please?
Cheers
Paul
You shouldn't use an image view for this, you should use a UIButton. ImageViews are designed primarily to display, not allow for interaction (which is why their userInteractionEnabled flag is OFF by default.)
Take a look at the documentation for UIResponder - all UIViews, including UIImageView, inherit from it. In turn, UIResponder defines a set of methods you can override to handle the kind of event you're looking at. Start by subclassing UIImageView (call it MyImageView), then override the touchesEnded:withEvent: method.
As Ben Gottlieb said, however, this may be kind of an abuse of the UIKit framework - just make sure the user interaction you're creating makes sense and conforms to good UI practices.
The last time I needed to do this I just used a button also. You can always set up the highlighted state so that it doesn't highlight when someone taps on it if that's what you're trying to avoid.
Note that the higher level UI "actions" are implemented in UIControl, so if all you need to do is track actions like "Touch Up Inside" then it's possible to avoid the event layer, create a UIView in Interface Builder, then change the class to UIControl. You should then be able to use the connections inspector and connect any of those control actions to whatever.
If you place views inside the UIControl and the subviews have "User Interaction Enabled" unchecked (that is, user interaction is disabled) then taps and such inside the UIControl just ignore those and fall through to the UIControl. So another way to do this if you needed to for some reason would be to create a UIView, change the class to UIControl, then place one or more UIImageViews, UILabels, or whatever you want in your generic UIControl view. You can then get actions from the generic UIControl as if all that stuff wasn't inside it.
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
I'm trying to figure out a best way to implement the picture-editing capability shown in the native address book app on iPhone.
On the built-in address book, this is how the picture looks like before editing:
qkpic.com/2f7d4 http://qkpic.com/2f7d4
And after clicking edit, notice how "Edit" overlay is added and the image becomes clickable:
qkpic.com/fb2f4 http://qkpic.com/fb2f4
What would be the best way to implement something like this? Should I make the image a button from the beginning and have tapping disabled at first? If so, what steps are required to add an overlay/label to the image (in above example, gray border + the text "Edit" is added)
The easiest way is to use Interface Builder, create a container view, then add a UIImageView and UILabel as subviews to it. You would position and style the text and the image but set the UILabel to hidden. Make the whole container view respond to touches. It's easy to do since UIView is derived from UIResponder so all you have to do is override touchesEnded. Whenever you want to change the text label, just set the UILabel to hidden=NO.
There's more to it, however. Notice how the image has rounded corners? You'll want to override the UIImageView's drawRect method to implement a custom drawing routine to do that. There's lots of sample code around and it wasn't part of your original question so I'll stop here.