I want to show a logo UIView always on top when the app running,
I know there is a way to do that,add same UIView to every UIViewController,
but I think this is not the best way to do that.
when i have lot of pages,and modify the logo UIView,must modify it every page.
Did someone have better way to do this?
thanks.
look like this:
Since you only every have one window per app, and view's don't have levels, you have to make sure that view stays on top of the hierarchy, no matter what. One relatively easy way is to add it directly to the window above the rest of the interface (the navigation controller):
In applicationDidLaunch:
// After the main navigation controller or tab controller has been added
// either programmatically or in the xib:
UIImage *logo = [UIImage imageNamed:#"logo.png"];
UIImageView *logoView = [[UIImageView alloc] initWithImage:logo];
[self.window addSubview:logoView];
Actually, I think that (a) creating a subclass of UIView that shows your logo and has all the necessary setup in it and then (b) adding this subclass to each view controller is the cleanest and most manageable way to do this.
The reason I prefer this method over adding the view to the window is because if you ever have a view that you don't want to show the logo, you won't need to show and hide something you added to the window. Also, adding directly to the window may cause rotation challenges on certain iOS devices in my experience, depending on what you're doing.
Also, to make sure your logo view is always on top of the view hierarchy, you can do two things:
If the view already exists, you can bring it to front using [UIView bringSubviewToFront:]
[myParentView bringSubviewToFront:myLogoSubview];
If you are creating the view, it will be on top when you add it with [UIView addSubview:]
// Set up myLogoSubview first here with alloc+init, etc.
[myParentView addSubview:myLogoSubview];`
It looks like in your image you would replace myParentView with self.view and myLogoSubview with the view you're looking to keep on top, but this is just my assumption based on your image.
Related
I'm trying to write my first iPhone app, and I'm running into a sort of design struggle. What I want to do is have a grid of icons and when you touch one, all the icons above and to the left will "activate" and all the ones below and to the right will "deactivate." If an icon is activated it shows one picture, and if it's not activated it shows another.
The problem I have is that I want to assign a gesture recognizer to each one of these individual icons, and when that icon is tapped, it needs to call a function that updates my grid of icons. But in order to properly update, the function needs to pass as arguments the location of the image in the grid and there's no way to call a function with arguments as part of a gesture recognizer.
So really all I need to do is extend UIImageView to hold two extra integers and the grid it's contained in, and then I could have the following code:
imageView.userInteractionEnabled = YES;
UITapGestureRecognizer *tapgr = [[UITapGestureRecognizer alloc] initWithTarget:
self action:#selector(handleTap)];
[imageView addGestureRecognizer:tapgr];
:
:
- (void)handleTap
{
[self.grid updateTableFromRow:self.row andCol:self.col
}
So I suppose this is one way of doing it, but I'm told that I'm not supposed to extend classes in Objective-C, that I should build them from the ground up. In this case, I would just make a custom view with all the properties and/or instance variables I need and I would just fill this custom view with the UIImageView.
This is mostly fine, except when it comes to building my Storyboard. I put all the code that manages and creates this table of icons (programmatically) in another custom view, GridOfIconsView. So on the Storyboard I drag out a custom view and set to be a GridOfIconsView, but then I just see a big white rectangle, and I really want to be able to visualize my app in Storyboard. I know that I can drag out actual image files that I use for the icons onto Storyboard and set them to be a custom view, but then how does that work? Is that image just a background to the custom view? Would I be able to change it programmatically? So if the activated image was a green square, but the deactivated was a red one and I initially dragged out red squares to the Storyboard, would I have access to that red square image?
And a more concerning issue is that I want to manage all these icons in a data structure, either as a 2d array (id icons[][]) or a NS(Mutable?)Array of NS(Mutable?)Arrays. Either way, how could I initialize the data structure to contain links to all these? The grid will be probably 8x8 or 10x10, and there's no way I'm going to have 64-100 #propertys connecting these icons. I'm thinking the only way to sensible organize this is programmatically, but then still, how can I visualize it in Storyboard?
First, it's completely fine to extend classes in Objective-C, and it's done all the time. UIView, UIViewController, UIComponent, etc., were all designed specifically to be subclassed and extended.
However, there are two ways you can do this that are much simpler than extending the class. First, you can have your grid as you already do, where each view has a gesture recognizer attached that calls back to a method on the view controller. Then, you can set a tag on each view (or even just use the view's frame for identification), and read that from the callback method (the gesture recognizer is passed back to the callback method). For example, let's say you had a grid of 4x4 views and you simply numbered them starting in the top-left, advancing each column to the right and then each row, from 0 to 11, you could easily identify the view as such:
// The system automatically passes the gesture recognizer as the only parameter
- (void)handleTap:(UIGestureRecognizer)gestureRecognizer
{
NSInteger viewNumber = [[gestureRecognizer view] tag];
// do something with this view
}
The other way you can do it is to have a single gesture recognizer on the parent view, and then in your -handleTap: callback, you'd query the position of the tap in the view. If the position is within the frame of any of your views, you'd know which one and what to do with it. If not, you could ignore it. This solution requires slightly more math, but also requires far less maintenance and far fewer gesture recognizer that need to be wired up. I would recommend this solution over tagging your views.
Is there a way to use custom segues to individually animate several different subviews.
For example, I want my modal view to appear by the UINavigationBar fading in (as the source destination's UINavigationBar fades out) and then a UITableView to slide down the screen 'over' the source destination's view controller.
When I try to implement this in the - (void)perform method. My properties don't animate using [UIView animateWithDuration: animations: completion:].
Can anyone provide me with a solution?
Thanks in advance!
You can certainly use custom segues to achieve this - however, I don't think you'll get much help without more details about the setup of your view controllers.
Everything you describe is correct: to create a custom segue you animate the views inside your sourceViewController and destinationViewController inside the segue's perform: method. If they're not animating you might want to check that your segue is actually getting called (you can use breakpoints in the debugger to check this), or that the views you're trying to access inside your view controllers actually exist at that point in time (again, something you can check using the debugger).
For a solution specific to your app you're almost certainly going to have to provide more details about the two view controllers you're trying to transition between. Perhaps you could post your perform: method.
I wanna create an app that will have three view controllers. To navigate between them I wanna use swipes and page control (UIPageControl). Also i wanna do this using Stroryboards as much as possible.
What's the best way to implement this?
Thanks
This could also be achieved using the storyboard and segues.
The basic idea is you would create the segues between the 3 UIViewControllers, then capture the swipe gestures, and then call the perform segue to move between views.
On each view, you will have one or two segues:
[ View 1 ] -> gotoView2
gotoView1 <- [ View 2 ] -> gotoView3
gotoView2 <- [ View 3 ]
Here is a video of how to do it.
http://www.youtube.com/watch?v=5u1-DGiUhXU
This is actually quite simple to implement if you know what you need to do. UIPageControl does not help you to achieve paging, it merely displays the dots like on springboard to show what page you are on.
As far as I am aware storyboards let you switch between views or controllers, which if a paging effect is what you are after is not going one much use to you. Your best bet would be to use one view controller and a scrollview on its view.
If you set
scrollView.pagingEnabled = YES;
scrollView.contentSize = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f);
Or something to that effect (you can change the content size to whatever size you want your pages to be. Your scroll view will then snap to those boundaries when scrolling.
If you want to display the current page with a UIPageControl you will need to also add one to your view controller's view. Then implement the UIScollViewDelegate protocol and the method:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
pageControl.currentPage = (calculate current page here);
}
In order to make you pages, simply add subviews to the scroll view and it will page between them depending on your set content size.
Hope this help, if it seems unclear or you need any more help, let me know :)
I have a simple app that has a NSStatusItem, which only displays an icon.
I would now like to add functionality that would make a MAAttachedWindow appear under the NSStatusItem.
I saw the demo code Matt Gemmel provided; the code he uses to make the MAAttachedWindow appear under the NSStatusItem is:
NSRect frame = [[self window] frame];
NSPoint pt = NSMakePoint(NSMidX(frame), NSMinY(frame));
[controller toggleAttachedWindowAtPoint:pt];
The above is done in the custom view of the NSStatusItem. However, my NSStatusItem has no custom view. How can I add the MAAttachedWindow in my case?
You can't afaik. You have to have a way to get coordinates to attach the window to, and the only way i've been able to get that to work is to use a custom view so you can get the coordinates on mouse down and the only way i've seen is to use your own view. Anything else would probably be a little hacky unless there is some way to get the view for a status item without a custom view and it wouldn't be good to display the MSAttachedWindow and a menu.
I just settled on doing a NSStatusitem with a custom view and faking selection by drawing a background gradient when its selected.
Have you considered using NSPopover ?
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/