I stumbled across a lovely ui concept. I am wondering how could we create a "pop up" window like this in iOS(iPhone).
I have 3 questions:
How do we achieve that pop up style window?
What is the best approach to do that?
Thank you
EDIT: I would like to create a custom control like this.
It seems that the better way is to:
1- Create a class that inherits UIView and has a delegate class too.
your .h file should be something like this:
#import <UIKit/UIKit.h>
#class MYPopUpView;
//Your delegate class
#protocol PopUpViewDelegate <NSObject>
- (void) popUpView:(MYPopUpView *)popUpView clickedButtonAtIndex:(NSInteger) index;
#end
//Your view interface
#interface LIPopUpView : UIView{
NSObject<LIPopUpViewDelegate> *_delegate;
}
//Your methods and properties
#end
2- In the initializer of your .m file implement the UI of your PopUpView
3- For the circle you can use UILayer or even a custom button and when user clicks it fire your delegate methods.
4- Define a show methods with following code for showing the popUp:
- (void) show
{
UIWindow *window = [UIApplication sharedApplication].windows.lastObject;
[window addSubview:self];
[window bringSubviewToFront:self];
}
5- Fire the show method of you popUp object to show the popUp
6- For hiding it, define the close methods like below and fire it from the caller class.
- (void) close
{
[self removeFromSuperview];
}
Sounds to me the following will do:
Create a view controller whose view has sub-views look like the register window in the screenshot. For the non-rectangle shape, mask of the view layer may needs to be properly set.
Add the view of the view controller to the key window.
Related
I have implemented a custom alertview and the delegate methods are as follows:
#import <UIKit/UIKit.h>
#class MyAlertViewController;
#protocol MyAlertViewControllerDelegate <NSObject>
#required
-(void) alertViewControllerClickedPrimaryButton:(MyAlertViewController *)alertViewController;
#optional
-(void) alertViewControllerClickedSecondaryButton:(MyAlertViewController *)alertViewController;
#end
I have these delegate methods called in many view controllers.And Also I made one SharedViewController which I use it for all my ViewControllers
Lets say, one of these delegate method is called from MasterViewController which inherits SharedViewController,I will have this method in the SharedViewController:
#pragma mark My Alert Delegate
-(void) alertViewControllerClickedPrimaryButton:(MyAlertViewController *)alertViewController{
//here how would I know that this alert is presented from MasterViewController ?
}
If I do [self class] , I would get the name as SharedViewController.
How can I get the name for my MasterViewController in my SharedViewController,when the delegate method is called from MAsterVIewController?
Edit: I added one parameter called UIViewController to the delegate method,and now it looks like this:
-(void) alertViewControllerClickedSecondaryButton:(MyAlertViewController *)alertViewController :(UIViewController *)controllerName;
and what needs to send to delegate as controllerName?
I have this line to call the delegate method:
[_delegate alertViewControllerClickedSecondaryButton:self ]; //previous call
and I changed this to:
[_delegate alertViewControllerClickedSecondaryButton:self :<#(UIViewController *)#>]; // I have no idea which parameter to pass in here
any ideas?
~ EDIT ~
Select your storyboard file
Choose MasterViewController
In Utilities select Identity Inspector
Make sure the Class selected is MasterViewController
Just below the Custom Class area in the Storyboard ID textbox give it a custom name
Lastly, Tick the 'Use Storyboard ID' box √
Do the same for SharedViewController
(and for any other VC's you have potentially presenting your alertviewcontroller)
Now, in your Alert Delegate Method after your custom AlertVC has been presented onto the Navigation Stack:
-(void) alertViewControllerClickedPrimaryButton:(MyAlertController *)alertViewController
{
/* ... all other code
...
...
*/
// Print the name of the Presenting View Controller
NSLog(#"Presenting ViewController = %#", self.presentingViewController.restorationIdentifier);
}
I have a single UIView I'm going to be adding to a few different views (like a navigation bar). Where should I put the selectors that I'm using for each button to keep the MVC structure?
My first guess would be to create a NavButtonsViewController but that seems funky since I'd have to instantiate the view controller somewhere in the UIView to add the target and selectors to the buttons. Or is that how it's supposed to work?
I would probably model this on something like UITableView and have the view itself deal with the immediate gesture but provide a protocol so that a delegate could decide what should really be done.
The view's selectors would probably do nothing but forward to the delegate.
It's fairly common to use a delegate for this kind of a problem. The view with the buttons would provide a delegate protocol that anyone can use to define behaviors that occur on an event.
The UINavigationBar and UINavigationBarDelegate are a good place to look for the delegation pattern similar to what you described.
https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UINavigationBar_Class/index.html
https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UINavigationBarDelegate_Protocol/index.html
I can think in two solutions if the view is reusable
1- Add the selectors in the UIView subclass and define a protocol where the delegate should take care of the actions in the View.
Header file
#protocol SubviewActionDelegate
#optional
- (void)button1Selected;
#end
#interface Subview: UIView
#property (nonatomic, weak) id<SubviewActionDelegate> delegate
#end
Implementation file
[self.button1 addTarget:self action:#selector(buttonSelected:) forControlEvents:UIControlEventTouchUpInside];
...
- (IBAction)buttonSelected:(UIButton *)sender {
if(self.delegate respondsToSelector:#selector(button1Selected)) {
[self.delegate button1Selected];
}
}
The class that adds this reusable view as subview should implement this delegate and define itself as delegate.
2- Add the selectors in the same UIView or UIViewcontroller that add your view as subview.
Subview *view = [Subview alloc]initWithFrame:CGRectZero];
view.button1 addTarget:self action:#selector(buttonSelected:) forControlEvents:UIControlEventTouchUpInside];
...
- (void)buttonSelected:(id)sender{
NSLog(#"Button selected");
}
Now if you have more than one of this reusable views in the same UIViewController or UIView container (like a UITableViewCell), you can identify which view is the one you are looking for by setting the view or button tag value.
[subview.button1 setTag:someValue];
...
- (void)buttonSelected:(UIButton *)sender{
if(sender.tag == someValue) {
//do something
} else {
//do something else
}
Hope it helps
I'm trying to get a custom tab bar for iPhone (iOS 6) and I've got to manage a central button that raises over the bar (based on code, https://github.com/tciuro/CustomTabBar) but now I have to face another feature: buttons must blink when clicked and glossy effect has to be removed. Any suggestion about the best way to get that? I'm still relatively new programming with iOS and its animations.
Thank you very much
What I already have so far:
In MBCenteredButtonVC (main entry in storyboard)
#import <UIKit/UIKit.h>
#interface MBCenteredButtonViewController : UITabBarController <UITabBarDelegate>
#property(nonatomic, weak) IBOutlet UIButton *centerButton;
#end
And its implementation:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tabBar setSelectedImageTintColor:[UIColor colorWithRed:171/225.0 green:233/255.0 blue:8/255.0 alpha:1]];
[self.tabBar setBackgroundImage:[UIImage imageNamed:#"bar-back.png"]];
// Do any additional setup after loading the view.
[self addCenterButtonWithImage:[UIImage imageNamed:#"button-rocketBg.png"] highlightImage:[UIImage imageNamed:#"button-rocketBg-active.png"] target:self action:#selector(buttonPressed:)];
}
Images for each item is defined within views properties using XCode. So, this way, I get a central button raised over the rest and I have changed the color for selected items but I need that they blink while content is being loading (it supposed that could take some time).
I feel that I have to implement this functionality when buttons are pressed:
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
NSLog(#"Selected tab bar item: %i", item.tag);
}
}
but not sure if it the right way and how to do it exactly.
The easiest way to get started with animations on iOS is probably to use the UIView animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations method.
Documentation here: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/UIView/UIView.html#//apple_ref/doc/uid/TP40006816-CH3-SW111
Any values that are animatable that you change in that block will be animated.
Core Animation is extensive, and this barely scratches the surface of what can be done, but it might be enough to get you started.
I am currently designing the structure for my first iPhone game and ran into a problem. Currently, I have a 'MenuViewController' that allows you to pick the level to play and a 'LevelViewController' where the level is played.
A UIButton on the 'MenuViewController' triggers a modal segue to the 'LevelViewController'.
A UIButton on the 'LevelViewController' triggers the following method to return to the 'MenuViewController':
-(IBAction)back:(id)sender //complete
{
[self dismissModalViewControllerAnimated:YES];
}
The problem is, I have a UILabel on the menu page that prints the number of total points a player has. Whenever I go back to the menu from the level, I want this label to automatically update. Currently, the label is defined programmatically in the 'MenuViewController':
-(void)viewDidLoad {
[super viewDidLoad];
CGRect pointsFrame = CGRectMake(100,45,120,20);
UILabel *pointsLabel = [[UILabel alloc] initWithFrame:pointsFrame];
[pointsLabel setText:[NSString stringWithFormat:#"Points: %i", self.playerPoints]];
[self.pointsLabel setTag:-100]; //pointsLabel tag is -100 for id purposes
}
self.playerPoints is an integer property of MenuViewController
Is there a way I could update the label? Thanks ahead of time!
This is a perfect case for delegation. When the LevelViewController is done, it needs to fire off a delegate method which is handled in the MenuViewController. This delegate method should dismiss the modal VC and then do whatever else you need it to do. The presenting VC should normally handled the dismissal of modal views it presents.
Here is a basic example of how to implement this:
LevelViewController.h (Above the Interface declaration):
#protocol LevelViewControllerDelegate
-(void)finishedDoingMyThing:(NSString *)labelString;
#end
Same file inside ivar section:
__unsafe_unretained id <LevelViewControllerDelegate> _delegate;
Same File below ivar section:
#property (nonatomic, assign) id <LevelViewControllerDelegate> delegate;
In LevelViewController.m file:
#synthesize delegate = _delegate;
Now in the MenuViewController.h, #import "LevelViewController.h" and declare yourself as a delegate for the LevelViewControllerDelegate:
#interface MenuViewController : UIViewController <LevelViewControllerDelegate>
Now inside MenuViewController.m implement the delegate method:
-(void)finishedDoingMyThing:(NSString *)labelString {
[self dismissModalViewControllerAnimated:YES];
self.pointsLabel.text = labelString;
}
And then make sure to set yourself as the delegate for the LevelViewController before presenting the modal VC:
lvc.delegate = self; // Or whatever you have called your instance of LevelViewController
Lastly, when you are done with what you need to do inside the LevelViewController just call this:
[_delegate finishedDoingMyThing:#"MyStringToPassBack"];
If this doesn't make sense, holler and I can try to help you understand.
Make a property self.pointsLabel that points to the UILabel, then you can just call something like [self.pointsLabel setText:[NSString stringWithFormat:#"Points: %i", self.playerPoints]]; to update the label with the new score
In your modal view header file, add the property:
#property (nonatomic,assign) BOOL updated;
Then in your main view controller, use didViewAppear with something like:
-(void)viewDidAppear:(BOOL)animated{
if (modalView.updated == YES) {
// Do stuff
modalView.updated = NO;
}
}
Where "modalView" is the name of that UIViewController that you probably alloc/init there.
Add more properties if you want to pass more info, like what level the user picked.
I've just started with xcode and objective-c and did some very basic apps, but what i'm having problem with is very basic this. the keyboard return button not hiding the keyboard.
I've searched the internet for the solution and all they say is to connect delegate to the file's owner and add the function and it should work, i did that and nothing is working.
I have an ok button and it is working and also clicking on any free space on the screen is working, just the return button....
I am using the simulator, not testing on iphone yet. (xcode 3.2.5 64 bit with the 4.2 simulator).
This is the line of code that should connect the delegate to every textFiled.
1. i've tried already to return both YES and NO, didn't work.
2. i've tried both a specific object name for the textField and this general way, didn't work.
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return NO;
}
In the: basic view controller connection -> connections -> outlets, i have the: delegate -- File's Owner. and in the file's owner in referencing outlets there is: delegate - Round style text.....
EDIT - i forgot to mention before, i've check and the method isn't being called!!!
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
NSLog(#"Working!!!");
[textField resignFirstResponder];
return YES;
}
what should i do to make it happen? that is why people say to connect the delegate, but in my case it is connected and not triggering the function...i know it is kind of dumb question but for a nobie like me the solution is not obvious...
OK, another Edit - with all my code: just can't understand what to do....
This is: basicViewController.h:
#import <UIKit/UIKit.h>
#interface basicViewController : <#superclass#> <UITextFieldDelegate>
#interface basicViewController : UIViewController <UITextFieldDelegate> {
//every object that we want to interact with (like text field or lable) is call an outlet!!!!
//here we define the outlets for our program
IBOutlet UITextField *txtName;
IBOutlet UILabel *lblMessage;
}
//here are the getters and setter for our outlets
#property (nonatomic, retain) IBOutlet UITextField *txtName;
#property (nonatomic, retain) IBOutlet UILabel *lblMessage;
//method decleration for the OK button action
- (IBAction) doSomething;
//method for hiding the keyboard when clicking on empty area in the app
//we will put an invisible button on all area and clicking on it will make keyboard disapear
- (IBAction) makeKeyboardGoAway;
#end
This is basicViewController.m:
#import "basicViewController.h"
#implementation basicViewController
//synthesizeing the objects that we made' this will create the getter and setters automaticly
#synthesize txtName;
#synthesize lblMessage;
- (IBAction) doSomething{
// makeing keyboard disapear when pressing ok button (doing that form the text field)
//when pressing the OK button, the keyboard will disapear and when clicking in the text field it will show again
[txtName resignFirstResponder];
NSString *msg = [[NSString alloc] initWithFormat:#"Hello, %#",txtName.text];
//the objective-c way for setting the test in the text field
[lblMessage setText:msg];
//the regular object oriented way
//lblMessage.text = msg;
[msg release];
}
- (IBAction) makeKeyboardGoAway{
[txtName resignFirstResponder];
}
//when clicking the return button in the keybaord
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
NSLog(#"Working!!!");
[textField resignFirstResponder];
return YES;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
Maybe now i am more clear, sorry i didn't do it before.
Any one has an idea what am i doing wrong? it should be pretty strait forward.....
EDIT - Adding an image of all the elements, i hope that will help to help me :-)
10x a lot for every one that is trying to help....i really like this framework, it is so great after c++ and java, python and many other...and i am working with a book, but it is for ios 3.1, maybe that is the problem.....
Firstly you should check if textFieldShouldReturn: is actually being called by adding an NSLog statement or breakpoint at the beginning of the method.
Once that's out of the way, try an manually declare that your view controller conforms to <UITextFieldDelegate> protocol in your interface file:
#interface YourClass : ... <UITextFieldDelegate>
Also declare a property & outlet for your UITextField, make the appropriate connections in IB and manually declare self as the UITextField delegate with:
self.yourUITextFieldObject.delegate = self;
Once that's done see if your method above is now being called and make sure you return YES.
Just write one line in the
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
}
before return YES;
the final version will be as given below:
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
-(void)textFieldDidEndEditing:(UITextField *)textField{
NSLog(#"%#",textField.text);
}
You need to assign the delegate of the textfields to your file owner. The textfields are sending the message, but doesn't have a delegate to respond to it.
Use the interface builder to do that.
You have to implement this method..
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
Like Rog said, don't forget to register the textfield to the delegate, you can do this manually as he said but in Storyboard you can just control drag from all of your textfields to the view controller and register the delegate (choose delegate). Only the textfields that are registered can make use of all those methods.
So this line is important:
self.yourUITextFieldObject.delegate = self;
Or even more easy these days is to just use the storyboard:
textfield is in a subview? in this case, make sure textfield have as delegate the FileOwner.
put a log at the
- (IBAction) makeKeyboardGoAway
function. I think its this method everytime anything is tapped on the screen. In that case, you will need to send the touch event to the text field. Not sure how this is done but that should do it.
Else try removing the which takes care of tap(click) all over the view and try to do what you are doing.
Most likely the problem is that your actual view controller in the running application is not a "basicViewController" but a UIViewController that does not implement the UITextFieldDelegate-protocol.
What you've done in the interface builder by selecting your class "basicViewController" as the FilesOwner is just declaring the FilesOwner-object in your running application to be of type basicViewController; the actual object is not instantiated by this declaration and in your case it is not in the xib / nib.
Some other part of your code actually instantiates a view controller object and loads the xib / nib file. At that place, I guess your code is instantiating a UIViewController (typically by auto-generated code) and not an instance of your basicViewController; you simply have to change the class there.
Furthermore, this error often happens when using a UINavigationController or UITabBarController in the Interface Builder that is (should be) configured to instantiate and load other custom views. If you use such a higher-level controller, double-check that it is actually configured to use your basicViewController, not UIViewController when loading your view from the xib / nib.
Hope, that solves the issue!
Can you try this..
#interface ClassName : SuperClass < UITextFieldDelegate >
Use like this...
textfield.delegate=self;
and use the UITextFieldDelegate in .h class
You can always dismiss the keyboard when you don’t even know which view the text field is in by using:
Objective-C:
[[UIApplication sharedApplication] sendAction:#selector(resignFirstResponder)
to:nil
from:nil
forEvent:nil];
Swift:
UIApplication.sharedApplication().sendAction("resignFirstResponder",
to:nil,
from:nil,
forEvent:nil)