- Home /
Does anyone have iPad popover examples?
I'm about to start implementing some obj-c UI elements on top of Unity, and was wondering whether anyone had yet created a plugin to show a popover. I've got Unity pro, so I plan to implement this code as a plugin with methods to be called from within scripts in Unity. I'd greatly appreciate any code snippets.
Answer by Tetrad · Jun 10, 2010 at 09:33 PM
Well without going into full detail, UIPopoverView is pretty straight forward.
Here's a simple example.
Header:
@interface MyCustomPicker : NSObject <UIPopoverControllerDelegate, UINavigationControllerDelegate> { UIView* view; // the base view passed in from the custom init function below UIPopoverController* popOver; }
// this is passed in the view created inside AppController.mm,
// I'll leave it as an exercise to the reader as to where to create this class in order to get that variable. - (id)initWithView:(UIView*)appView;
@end
I'm assuming you understand the basics of the language so I won't bore you with the entire implementation:
// this converts a Unity GUI Rect to a CGRect for the purposes of pointing at the button you clicked on assuming iPad resolution - (CGRect)GetMuxedRect:(CGRect)portraitRect { switch( [[UIApplication sharedApplication] statusBarOrientation] ) { case UIInterfaceOrientationPortrait: return portraitRect; case UIInterfaceOrientationPortraitUpsideDown: return CGRectMake( 768 - portraitRect.origin.x - portraitRect.size.width, 1024 - portraitRect.origin.y - portraitRect.size.height, portraitRect.size.width, portraitRect.size.height ); case UIInterfaceOrientationLandscapeLeft: return CGRectMake( portraitRect.origin.y, 1024 - portraitRect.origin.x - portraitRect.size.width, portraitRect.size.height, portraitRect.size.width ); case UIInterfaceOrientationLandscapeRight: return CGRectMake( portraitRect.origin.y - portraitRect.size.height, portraitRect.origin.x, portraitRect.size.height, portraitRect.size.width ); default: return portraitRect; } }
// call this somehow from your C# to Obj-C code bridge. There are several ways to do this - (void)OpenViewInPopover { // You can replace this with something else, like maybe UIImagePickerController MyCustomViewController* vc = [[[MyCustomViewController alloc] initWithNibName:@"MyCustomViewController" bundle:nil] autorelease];
vc.delegate = self; // setup code for your embedded view controller
self.popOver = [[[UIPopoverController alloc] initWithContentViewController:vc] autorelease];
popOver.delegate = self;
[popOver setPopoverContentSize:vc.view.frame.size]; // for your own custom views you'll want this line.
// in this example, I have a GUI.Button with rect( 5, 384, 100, 40 ) somewhere on screen. If you have a 3D GUI or something that doesn't use Unity GUI, you'll have to find your own solution for figuring out how to put the arrow pointing the right place.
[popOver presentPopoverFromRect:[self GetMuxedRect:CGRectMake( 5, 384, 100, 40 )] inView:view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
// UIPopOverView delegate methods - (void)popoverControllerDidDismissPopover:(UIPopoverController*)popoverController { // you might want to do something else here, like sending a unity message to change something from what was in the view self.popOver = nil; }
The real work is going to be figuring out how to send information back and forth between your game and the view controller you put in the UIPopOverView. For example, for a simple toggle switch, you'll probably want to call a native code function that sets a bool on your view whenever it changes in game. Likewise, when the bool changes in native code you'll want to send a message back downwards to notify the game.
For sending messages from Unity into the view controller, the pattern I use is to create the MyCustomPicker object on startup, and do a simple singleton style pattern. So outside the @implementation block do something like this:
// static instance that gets set in init MyCustomPicker* selfCustomPicker;
// this is a native function you'd bind to and call from Unity script void OpenCustomPicker() { [selfCustomPicker OpenViewInPopover]; }
Also, if you have a view controller with something like a "done" button (i.e. UIImagePickerController), that done button callback should call the -(void)dismissPopoverAnimated:(BOOL)animated function on your stored UIPopOverView.
Forgive me, I don't really understand how initWithView is called, nor do I understand why it needs to be called since you are presenting the popover at a coordinate. Can you give any further details?
I now understand why you need a view to display the popover, but dont understand how to modify AppController to initialize it.
It's been a long time since I originally posted this question, and now that I've done this a bunch, I should give a tip on what I think the best way to do this is. To avoid mucking around in the AppController create a category on the AppController and put all of your code in there. To get the view controller which you'll put your popover in to you can call [[UIApplication sharedApplication].keyWindow rootViewController]. With older versions of unity, the EAGL view wasn't inside a view controller, so you needed to make a temp view controller to put your popover in. But now they've wrapped up everything inside a view controller, so you can get at it much more easily.
This answer is helpful. I would be really grateful if the implementation category class file for the AppController.m could be shared. I understand why making a category is good organization, and I understand that Unity content is now inside a view. I do not understand where to put the reference to [[UIApplication sharedApplication].keyWindow rootViewController]. I like a challenge as much as anyone, but after several days trying to put together the parts from above, I’m really hoping for the details to get a complete example. $$anonymous$$any thanks!
Your answer
