Step 1:-
Create a class with sub Class UITextView and put the name of class KDPlaceHolderTextView
copy and paste the code in KDPlaceHolderTextView.h file
#import <UIKit/UIKit.h>
IB_DESIGNABLE
#interface KDPlaceHolderTextView : UITextView
#property (nonatomic, retain) IBInspectable NSString *placeholder;
#property (nonatomic, retain) IBInspectable UIColor *placeholderColor;
/*!
This method is used to set the UITextView Notification and UitextField begin nitification to set the placeholder text
#param NSNotification to be a notification
#return void
*/
-(void)textChanged:(NSNotification*)notification;
#end
Step 2:-
Add the this code in KDPlaceHolderTextView.m file
#import "KDPlaceHolderTextView.h"
#interface KDPlaceHolderTextView ()
#property (nonatomic, retain) UILabel *placeHolderLabel;
#end
#implementation KDPlaceHolderTextView
CGFloat const UI_PLACEHOLDER_TEXT_CHANGED_ANIMATION_DURATION = 0.25;
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)awakeFromNib
{
[super awakeFromNib];
// Use Interface Builder User Defined Runtime Attributes to set
// placeholder and placeholderColor in Interface Builder.
if (!self.placeholder) {
[self setPlaceholder:#""];
}
if (!self.placeholderColor) {
[self setPlaceholderColor:[UIColor lightGrayColor]];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
}
/*!
This method is used to set the frame Placeholder lable
#param CGrect frame to be a frame
#return id
*/
- (id)initWithFrame:(CGRect)frame
{
if( (self = [super initWithFrame:frame]) )
{
[self setPlaceholder:#""];
[self setPlaceholderColor:[UI Color lightGrayColor]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil];
}
return self;
}
- (void)textChanged:(NSNotification *)notification
{
if([[self placeholder] length] == 0)
{
return;
}
[UIView animateWithDuration:UI_PLACEHOLDER_TEXT_CHANGED_ANIMATION_DURATION animations:^{
if([[self text] length] == 0)
{
[[self viewWithTag:999] setAlpha:1];
}
else
{
[[self viewWithTag:999] setAlpha:0];
}
}];
}
- (void)setText:(NSString *)text {
[super setText:text];
[self textChanged:nil];
}
/*!
This method is used to draw the rect in placeholder lable acording to amount of text
#param CGrect to be a rect
#return void
*/
- (void)drawRect:(CGRect)rect
{
if( [[self placeholder] length] > 0 )
{
if (_placeHolderLabel == nil )
{
_placeHolderLabel = [[UILabel alloc] initWithFrame:CGRectMake(8,8,self.bounds.size.width - 16,0)];
_placeHolderLabel.lineBreakMode = NSLineBreakByWordWrapping;
_placeHolderLabel.numberOfLines = 0;
_placeHolderLabel.font = self.font;
_placeHolderLabel.backgroundColor = [UIColor clearColor];
_placeHolderLabel.textColor = self.placeholderColor;
_placeHolderLabel.alpha = 0;
_placeHolderLabel.tag = 999;
[self addSubview:_placeHolderLabel];
}
_placeHolderLabel.text = self.placeholder;
[_placeHolderLabel sizeToFit];
[self sendSubviewToBack:_placeHolderLabel];
}
if( [[self text] length] == 0 && [[self placeholder] length] > 0 )
{
[[self viewWithTag:999] setAlpha:1];
}
[super drawRect:rect];
}
#end
Step 3:-
Go to storyboard file and drag the UITexview in viewcotroller and assign the class KDPlaceHolderTextView
and see the attribute inspector set the PlaceHolder text or color
finally build and run the project
Check this in GitHub
You just have to change class name to (GCPlaceholderTextView) in UITextView interface.
It is not directly possible to add a Placeholder in textView But we can make use of UILabel to do the same.
Take a property of UILabel
#property (weak, nonatomic) UILabel *placeholederLabel;
Then in YourViewDidLoad.
placeholederLabel = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 5.0,textView.frame.size.width - 30.0, 40.0)];
[placeholederLabel setText:#"Enter Your text here."];
[placeholederLabel setBackgroundColor:[UIColor clearColor]];
[placeholederLabel setTextColor:[UIColor yellowColor]];
[textView addSubview:placeholederLabel];
And then write textView delegate Methods
- (void)textViewDidEndEditing:(UITextView *)theTextView
{
if (![textView hasText]) {
placeholederLabel.hidden = NO;
}
}
- (void) textViewDidChange:(UITextView *)textView
{
if(![textView hasText]) {
placeholederLabel.hidden = NO;
}
else{
placeholederLabel.hidden = YES;
}
}
Related
I just finished a tutorial on making my own keypad. So I took that knowledge and made a real simple App that adds two numbers with my own keypad. It is just two numbers. But when I tap on one textfield, the other textfield gets edited! I have enclosed my code, any help will be much appreciated. And thanks to #spacious for all previous help.
#import "KeyPad2ViewController.h"
#interface KeyPad2ViewController ()
#property (nonatomic) BOOL userIsEnteringANumber;
#end
#implementation KeyPad2ViewController
#synthesize numberOne;
#synthesize numberTwo;
#synthesize result;
#synthesize keyPad;
#synthesize userIsEnteringANumber;
#synthesize currentTextField;
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if ([numberOne isFirstResponder])
{
self.currentTextField = self.numberOne;
self.userIsEnteringANumber = NO;
}
else if ([numberTwo isFirstResponder])
{
self.currentTextField = self.numberTwo;
self.userIsEnteringANumber = NO;
}
return YES;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[numberOne setInputView:keyPad];
[numberTwo setInputView:keyPad];
numberOne.delegate = self;
numberTwo.delegate = self;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setNumberOne:nil];
[self setNumberTwo:nil];
[self setResult:nil];
[self setKeyPad:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
} else {
return YES;
}
}
- (IBAction)buttonPressed:(UIButton *)sender
{
NSString *button = [sender currentTitle];
NSRange decimalpoint = [self.currentTextField.text rangeOfString:#"."];
if (self.userIsEnteringANumber)
{
if ([button isEqualToString:#"."] && decimalpoint.location != NSNotFound)
{
self.currentTextField.text = self.currentTextField.text;
}else
self.currentTextField.text = [self.currentTextField.text stringByAppendingString:button];
}else
{
self.currentTextField.text = button;
self.userIsEnteringANumber = YES;
}
}
- (IBAction)backspacePressed:(UIButton *)sender
{
if (self.userIsEnteringANumber)
{
int positionOfDigitBeforeLastOne = self.currentTextField.text.length -1;
if (self.currentTextField.text.length > 0)
{
self.currentTextField.text = [self.currentTextField.text substringToIndex:positionOfDigitBeforeLastOne];
}
if (self.currentTextField.text.length == 0)
self.currentTextField.text = #"";
}
}
- (IBAction)clearPressed:(id)sender
{
currentTextField.text = [NSString stringWithFormat:#""];
}
- (IBAction)enterPressed:(UIButton *)sender
{
[self hideKeyPad];
}
- (IBAction)signPressed:(UIButton *)sender
{
NSString *negativeNumber = #"-";
NSString *firstCharInDisplay = #"";
if (self.userIsEnteringANumber)
{
firstCharInDisplay = [self.currentTextField.text substringToIndex:1];
if ([firstCharInDisplay isEqualToString:#"-"])
{
self.currentTextField.text = [self.currentTextField.text substringFromIndex:1];
}else {
negativeNumber = [negativeNumber stringByAppendingString:self.currentTextField.text];
self.currentTextField.text = negativeNumber;
}
}
}
- (IBAction)add:(UIButton *)sender
{
float a = [[numberOne text] floatValue];
float b = [[numberTwo text] floatValue];
float c = a + b;
[result setText:[NSString stringWithFormat:#"%.2f", c]];
}
- (void)showKeyPad
{
[UIView beginAnimations:#"animateView" context:nil];
[UIView setAnimationDuration:0.3];
CGRect keypadview = CGRectMake(0, 270, 320, 190); // puts keyboard on screen
keyPad.frame = keypadview;
keyPad.alpha = 1.0;
[UIView commitAnimations];
}
- (void)hideKeyPad
{
[UIView beginAnimations:#"animateView" context:nil];
[UIView setAnimationDuration:0.3];
CGRect keypadview = CGRectMake(0, 640, 320, 190); // puts keyboard off screen
keyPad.frame = keypadview;
keyPad.alpha = 1.0;
[UIView commitAnimations];
}
#end
and my .h file is
#import <UIKit/UIKit.h>
#interface KeyPad2ViewController : UIViewController <UITextFieldDelegate>
#property (weak, nonatomic) IBOutlet UITextField *numberOne;
#property (weak, nonatomic) IBOutlet UITextField *numberTwo;
#property (weak, nonatomic) IBOutlet UILabel *result;
#property (strong, nonatomic) IBOutlet UIView *keyPad;
#property (weak, nonatomic) UITextField *currentTextField;
- (IBAction)buttonPressed:(UIButton *)sender;
- (IBAction)backspacePressed:(UIButton *)sender;
- (IBAction)clearPressed:(UIButton *)sender;
- (IBAction)enterPressed:(UIButton *)sender;
- (IBAction)octopusPressed:(UIButton *)sender;
- (IBAction)signPressed:(UIButton *)sender;
- (IBAction)add:(UIButton *)sender;
#end
Thanks to any and all help. This site is really the best!!
When your textFieldShouldBeginEditing: method is called, the first responder has not been set to the correct field yet. Replace the textFieldShouldBeginEditing: with textFieldDidBeginEditing: to fix this problem.
I want to implement iAd in my viewController so that i created the singleton class for iAd here the code that i used but it doesnt display iAd in my viewController.
adWhirlSingleton.h
#import <Foundation/Foundation.h>
#import "iAd/ADBannerView.h"
#interface adWhirlSingleton : NSObject <ADBannerViewDelegate> {
ADBannerView *adView;
UIViewController *displayVC;
}
#property (strong, nonatomic) ADBannerView *adView;
#property (strong, nonatomic) UIViewController *displayVC;
+(id)sharedAdSingleton;
-(void)adjustAdSize:(CGFloat)x:(CGFloat)y;
#end
adWhirlSingleton.m
#import "adWhirlSingleton.h"
#implementation adWhirlSingleton
static adWhirlSingleton* _sharedAdSingleton = nil;
#synthesize adView, displayVC;
+(id)sharedAdSingleton
{
#synchronized(self)
{
if(!_sharedAdSingleton)
_sharedAdSingleton = [[self alloc] init];
return _sharedAdSingleton;
}
return nil;
}
+(id)alloc
{
#synchronized([adWhirlSingleton class])
{
NSAssert(_sharedAdSingleton == nil, #"Attempted to allocate a second instance of a singleton.");
_sharedAdSingleton = [super alloc];
return _sharedAdSingleton;
}
return nil;
}
-(id)init
{
self = [super init];
if (self != nil) {
// initialize stuff here
self.adView.delegate=self;
}
return self;
}
-(void)dealloc
{
displayVC = nil;
if (adView) {
[adView removeFromSuperview]; //Remove ad view from superview
[adView setDelegate:nil];
adView = nil;
}
[super dealloc];
}
-(void)adjustAdSize:(CGFloat)x :(CGFloat)y
{
[UIView beginAnimations:#"AdResize" context:nil];
[UIView setAnimationDuration:0.7];
adView.frame = CGRectMake(x, y, 320, 50);
[UIView commitAnimations];
}
-(BOOL)adWhirlTestMode
{
return YES;
}
-(NSString *)adWhirlApplicationKey
{
return #"xxxxxxxxxxxxx";
}
-(UIViewController *)viewControllerForPresentingModalView
{
return displayVC;
}
-(void)bannerViewDidLoadAd:(ADBannerView *)banner {
[self adjustAdSize:0 :410];
}
#end
myViewController.m
#import "adWhirlSingleton.h"
-(void)viewWillAppear:(BOOL)animated {
adWhirlSingleton *adWhirlSingle = [adWhirlSingleton sharedAdSingleton];
adWhirlSingle.displayVC = self;
[adWhirlSingle adjustAdSize:0 :self.view.frame.size.height -50];
[self.view addSubview:adWhirlSingle.adView];
[self.view bringSubviewToFront:adWhirlSingle.adView];
NSLog(#"Ad Banner View");
}
This is how i implemented the singleton class for iAd when i excute this i didnt get iAd displayed over my ViewController.
If anyone know how to implement this please help me to get out of this issue. Thanks in Advance.
I'm working on a soundboard app, that has several pages of buttons to play sound effects with a stop button on every page should the user wish to manually interrupt the clip. I'm using avaudioplayer in each view to play the sound upon pressing the button for that clip. It works fine until the view is changed. If a user jumps to a new page the sound keeps playing and the stop button stops working even if they return to the original view. Pressing a sound button no longer interrupts the running sound resulting in two sounds over each other.
From googling and searching this site, I know the issue is that each view change creates a new instance of the player and the remedy is to create a singleton class. Unfortunately I have yet to find any further examples of how to actually do this. If someone could provide or point the way to a beginners guide for creating an avaudioplayer singleton I would really appreciate it. All I need to be able to do is pass the file name to the shared player and start play with a sound clip button and have the stop button stop sounds no matter what view the user is on. I am using the ios 5.1 sdk with storyboards and ARC enabled.
My solution, as used in one of my own projects, is posted beneath. Feel free to copy-and-paste, I intend to open-source this project once it's finished :)
A preview of the player can be seen on YouTube: http://www.youtube.com/watch?v=Q98DQ6iNTYM
AudioPlayer.h
#protocol AudioPlayerDelegate;
#interface AudioPlayer : NSObject
#property (nonatomic, assign, readonly) BOOL isPlaying;
#property (nonatomic, assign) id <AudioPlayerDelegate> delegate;
+ (AudioPlayer *)sharedAudioPlayer;
- (void)playAudioAtURL:(NSURL *)URL;
- (void)play;
- (void)pause;
#end
#protocol AudioPlayerDelegate <NSObject>
#optional
- (void)audioPlayerDidStartPlaying;
- (void)audioPlayerDidStartBuffering;
- (void)audioPlayerDidPause;
- (void)audioPlayerDidFinishPlaying;
#end
AudioPlayer.m
// import AVPlayer.h & AVPlayerItem.h
#interface AudioPlayer ()
- (void)playerItemDidFinishPlaying:(id)sender;
#end
#implementation AudioPlayer
{
AVPlayer *player;
}
#synthesize isPlaying, delegate;
+ (AudioPlayer *)sharedAudioPlayer
{
static dispatch_once_t pred;
static AudioPlayer *sharedAudioPlayer = nil;
dispatch_once(&pred, ^
{
sharedAudioPlayer = [[self alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:sharedAudioPlayer selector:#selector(playerItemDidFinishPlaying:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
});
return sharedAudioPlayer;
}
- (void)playAudioAtURL:(NSURL *)URL
{
if (player)
{
[player removeObserver:self forKeyPath:#"status"];
[player pause];
}
player = [AVPlayer playerWithURL:URL];
[player addObserver:self forKeyPath:#"status" options:0 context:nil];
if (delegate && [delegate respondsToSelector:#selector(audioPlayerDidStartBuffering)])
[delegate audioPlayerDidStartBuffering];
}
- (void)play
{
if (player)
{
[player play];
if (delegate && [delegate respondsToSelector:#selector(audioPlayerDidStartPlaying)])
[delegate audioPlayerDidStartPlaying];
}
}
- (void)pause
{
if (player)
{
[player pause];
if (delegate && [delegate respondsToSelector:#selector(audioPlayerDidPause)])
[delegate audioPlayerDidPause];
}
}
- (BOOL)isPlaying
{
DLog(#"%f", player.rate);
return (player.rate > 0);
}
#pragma mark - AV player
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (object == player && [keyPath isEqualToString:#"status"])
{
if (player.status == AVPlayerStatusReadyToPlay)
{
[self play];
}
}
}
#pragma mark - Private methods
- (void)playerItemDidFinishPlaying:(id)sender
{
DLog(#"%#", sender);
if (delegate && [delegate respondsToSelector:#selector(audioPlayerDidFinishPlaying)])
[delegate audioPlayerDidFinishPlaying];
}
#end
AudioPlayerViewController.h
extern NSString *const kAudioPlayerWillShowNotification;
extern NSString *const kAudioPlayerWillHideNotification;
#interface AudioPlayerViewController : UIViewController
#property (nonatomic, assign, readonly) BOOL isPlaying;
#property (nonatomic, assign, readonly) BOOL isPlayerVisible;
- (void)playAudioAtURL:(NSURL *)URL withTitle:(NSString *)title;
- (void)pause;
#end
AudioPlayerViewController.m
NSString *const kAudioPlayerWillShowNotification = #"kAudioPlayerWillShowNotification";
NSString *const kAudioPlayerWillHideNotification = #"kAudioPlayerWillHideNotification";
#interface AudioPlayerViewController () <AudioPlayerDelegate>
#property (nonatomic, strong) AudioPlayerView *playerView;
- (void)playButtonTouched:(id)sender;
- (void)closeButtonTouched:(id)sender;
- (void)hidePlayer;
#end
#implementation AudioPlayerViewController
#synthesize playerView, isPlaying, isPlayerVisible;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
playerView = [[AudioPlayerView alloc] initWithFrame:CGRectZero];
[AudioPlayer sharedAudioPlayer].delegate = self;
}
return self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
{
self.view = playerView;
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
[playerView.playButton addTarget:self action:#selector(playButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
[playerView.closeButton addTarget:self action:#selector(closeButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Private methods
- (AudioPlayerView *)playerView
{
return (AudioPlayerView *)self.view;
}
- (void)hidePlayer
{
[[NSNotificationCenter defaultCenter] postNotificationName:kAudioPlayerWillHideNotification object:nil];
[self.playerView hidePlayer];
}
- (void)playButtonTouched:(id)sender
{
DLog(#"play / pause");
if ([AudioPlayer sharedAudioPlayer].isPlaying)
{
[[AudioPlayer sharedAudioPlayer] pause];
}
else
{
[[AudioPlayer sharedAudioPlayer] play];
}
[self.playerView showPlayer];
}
- (void)closeButtonTouched:(id)sender
{
DLog(#"close");
if ([AudioPlayer sharedAudioPlayer].isPlaying)
[[AudioPlayer sharedAudioPlayer] pause];
[self hidePlayer];
}
#pragma mark - Instance methods
- (void)playAudioAtURL:(NSURL *)URL withTitle:(NSString *)title
{
playerView.titleLabel.text = title;
[[AudioPlayer sharedAudioPlayer] playAudioAtURL:URL];
[[NSNotificationCenter defaultCenter] postNotificationName:kAudioPlayerWillShowNotification object:nil];
[playerView showPlayer];
}
- (void)pause
{
[[AudioPlayer sharedAudioPlayer] pause];
[[NSNotificationCenter defaultCenter] postNotificationName:kAudioPlayerWillHideNotification object:nil];
[playerView hidePlayer];
}
#pragma mark - Audio player delegate
- (void)audioPlayerDidStartPlaying
{
DLog(#"did start playing");
playerView.playButtonStyle = PlayButtonStylePause;
}
- (void)audioPlayerDidStartBuffering
{
DLog(#"did start buffering");
playerView.playButtonStyle = PlayButtonStyleActivity;
}
- (void)audioPlayerDidPause
{
DLog(#"did pause");
playerView.playButtonStyle = PlayButtonStylePlay;
}
- (void)audioPlayerDidFinishPlaying
{
[self hidePlayer];
}
#pragma mark - Properties
- (BOOL)isPlaying
{
return [AudioPlayer sharedAudioPlayer].isPlaying;
}
- (BOOL)isPlayerVisible
{
return !playerView.isPlayerHidden;
}
#end
AudioPlayerView.h
typedef enum
{
PlayButtonStylePlay = 0,
PlayButtonStylePause,
PlayButtonStyleActivity,
} PlayButtonStyle;
#interface AudioPlayerView : UIView
#property (nonatomic, strong) UIButton *playButton;
#property (nonatomic, strong) UIButton *closeButton;
#property (nonatomic, strong) UILabel *titleLabel;
#property (nonatomic, strong) UIActivityIndicatorView *activityView;
#property (nonatomic, assign) PlayButtonStyle playButtonStyle;
#property (nonatomic, assign, readonly) BOOL isPlayerHidden;
- (void)showPlayer;
- (void)hidePlayer;
#end
AudioPlayerView.m
#implementation AudioPlayerView
{
BOOL _isAnimating;
}
#synthesize playButton, closeButton, titleLabel, playButtonStyle, activityView, isPlayerHidden = _playerHidden;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"musicplayer_background.png"]];
_playerHidden = YES;
activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
activityView.frame = CGRectMake(0.0f, 0.0f, 30.0f, 30.0f);
[self addSubview:activityView];
playButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 30.0f, 30.0f)];
[playButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[playButton setBackgroundImage:[UIImage imageNamed:#"button_pause.png"] forState:UIControlStateNormal];
playButton.titleLabel.textAlignment = UITextAlignmentCenter;
[self addSubview:playButton];
closeButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 30.0f, 30.0f)];
[closeButton setBackgroundImage:[UIImage imageNamed:#"button_close.png"] forState:UIControlStateNormal];
[closeButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
closeButton.titleLabel.textAlignment = UITextAlignmentCenter;
[self addSubview:closeButton];
titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 240.0f, 30.0f)];
titleLabel.text = nil;
titleLabel.textAlignment = UITextAlignmentCenter;
titleLabel.font = [UIFont boldSystemFontOfSize:13.0f];
titleLabel.numberOfLines = 2;
titleLabel.textColor = [UIColor whiteColor];
titleLabel.backgroundColor = [UIColor clearColor];
[self addSubview:titleLabel];
}
return self;
}
- (void)layoutSubviews
{
#define PADDING 5.0f
DLog(#"%#", NSStringFromCGRect(self.bounds));
CGRect frame = self.bounds;
CGFloat y = frame.size.height / 2;
titleLabel.center = CGPointMake(frame.size.width / 2, y);
CGFloat x = titleLabel.frame.origin.x - (playButton.frame.size.width / 2) - PADDING;
playButton.center = CGPointMake(x, y);
activityView.center = CGPointMake(x, y);
x = titleLabel.frame.origin.x + titleLabel.frame.size.width + (closeButton.frame.size.width / 2) + PADDING;
closeButton.center = CGPointMake(x, y);
}
#pragma mark - Instance methods
- (void)showPlayer
{
if (_isAnimating || _playerHidden == NO)
return;
_isAnimating = YES;
[UIView
animateWithDuration:0.5f
animations:^
{
CGRect frame = self.frame;
frame.origin.y -= 40.0f;
self.frame = frame;
}
completion:^ (BOOL finished)
{
_isAnimating = NO;
_playerHidden = NO;
}];
}
- (void)hidePlayer
{
if (_isAnimating || _playerHidden)
return;
_isAnimating = YES;
[UIView
animateWithDuration:0.5f
animations:^
{
CGRect frame = self.frame;
frame.origin.y += 40.0f;
self.frame = frame;
}
completion:^ (BOOL finished)
{
_isAnimating = NO;
_playerHidden = YES;
}];
}
- (void)setPlayButtonStyle:(PlayButtonStyle)style
{
playButton.hidden = (style == PlayButtonStyleActivity);
activityView.hidden = (style != PlayButtonStyleActivity);
switch (style)
{
case PlayButtonStyleActivity:
{
[activityView startAnimating];
}
break;
case PlayButtonStylePause:
{
[activityView stopAnimating];
[playButton setBackgroundImage:[UIImage imageNamed:#"button_pause.png"] forState:UIControlStateNormal];
}
break;
case PlayButtonStylePlay:
default:
{
[activityView stopAnimating];
[playButton setBackgroundImage:[UIImage imageNamed:#"button_play.png"] forState:UIControlStateNormal];
}
break;
}
[self setNeedsLayout];
}
#end
AppDelegate - didFinishLaunching
// setup audio player
audioPlayer = [[AudioPlayerViewController alloc] init]; // public property ...
CGRect frame = self.window.rootViewController.view.frame;
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
CGFloat tabBarHeight = tabBarController.tabBar.frame.size.height;
audioPlayer.view.frame = CGRectMake(0.0f, frame.size.height - tabBarHeight, 320.0f, 40.0f);
[self.window.rootViewController.view insertSubview:audioPlayer.view belowSubview:tabBarController.tabBar];
From any view controller inside the app I start audio with the following code:
- (void)playAudioWithURL:(NSURL *)URL title:(NSString *)title
{
OnsNieuwsAppDelegate *appDelegate = (OnsNieuwsAppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate.audioPlayer playAudioAtURL:URL withTitle:title];
}
Assets
For the above example, the following assets can be used (button images are white, so hard to see against background):
Buttons:
Background:
There's a lot of discussion (and links to blogs, etc.) about singletons over at What should my Objective-C singleton look like?, and I see a fair number of tutorials as a result of this Google search: http://www.google.com/search?q=+cocoa+touch+singleton+tutorial, but the real answer to your question, I believe, is that you should do one of two things:
If you do want the sound for a particular view to continue playing when the user switches, create the player as you're doing now, but when the view (re)appears, check that a player exists, and don't make a new one.
If you want the sound to stop, then stop the sound when the view changes (i.e., in viewWillDisappear:).
I have a custom view that I'm using in a xib file. I load the view and add it to a window. It adds the view just fine as I can see the default text of the labels in the view, but when I try to change the label with a method call, it doesn't change the text.
The custom view isn't anything to fancy, just draws a rounded, transparent background.
NotificationView.h
#import <Cocoa/Cocoa.h>
#interface NotificationView : NSView
#property (weak) IBOutlet NSTextField *primaryLabel;
#property (weak) IBOutlet NSTextField *secondaryLabel;
#property (weak) IBOutlet NSTextField *identifierLabel;
#end
NotificationView.m
#implementation NotificationView
#synthesize primaryLabel;
#synthesize secondaryLabel;
#synthesize identifierLabel;
- (id) initWithFrame:(NSRect)frameRect
{
self = [super initWithFrame:frameRect];
if (self)
{
return self;
}
return nil;
}
- (void)drawRect:(NSRect)dirtyRect
{
NSColor *bgColor = [NSColor colorWithCalibratedWhite:0.0 alpha:0.6];
NSRect rect = NSMakeRect([self bounds].origin.x + 3, [self bounds].origin.y + 3, [self bounds].size.width - 6, [self bounds].size.height - 6);
NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:5.0 yRadius:5.0];
[path addClip];
NSShadow *shadow = [[NSShadow alloc] init];
[shadow setShadowColor:[NSColor redColor]];
[shadow setShadowBlurRadius:2.0f];
[shadow setShadowOffset:NSMakeSize(0.f, -1.f)];
[shadow set];
[bgColor set];
NSRectFill(rect);
[super drawRect:dirtyRect];
}
#end
In the xib I have a custom view set to the type NotificationView. I've added 3 labels to the view and connected them to the above IBOutlets. (I ctrl-click & drag from the label to the .h file to make the connection.)
I'm loading the view and adding it to a window with the following method. It looks through an array of windows, if an existing match is found it used that window, if not it creates a new window.
- (void) popupNotificationWithTag:(NSString *)tag fade:(double)msFade lineOne:(NSString *)lineOneText lineTwo:(NSString *)lineTwoText
{
NotificationWindow *notificationWindow;
NotificationWindow *tmpWindow;
NSEnumerator *enumerator;
// Walk the notification windows in the array
enumerator = [self.notificationWindows objectEnumerator];
if(enumerator)
{
while((tmpWindow = [enumerator nextObject]))
{
if([tmpWindow.tag isEqualToString:tag])
{
notificationWindow = tmpWindow;
}
}
}
// Make a new notification window
if (!notificationWindow)
{
int width = [[NSScreen mainScreen] frame].size.width;
int height = [[NSScreen mainScreen] frame].size.height;
notificationWindow = [[NotificationWindow alloc] initWithRect:NSMakeRect(width - 420, height - 130, 400, 100)];
NSNib *nib = [[NSNib alloc] initWithNibNamed:#"Notification" bundle: nil];
NSArray *objects;
[nib instantiateNibWithOwner:self topLevelObjects:&objects];
for (id obj in objects) {
if ([[obj class] isSubclassOfClass:[NSView class]])
[notificationWindow setContentView:obj];
}
[notificationWindow setTag:tag];
[self.notificationWindows addObject:notificationWindow];
}
// Display window
[notificationWindow makeKeyAndOrderFront:nil];
[notificationWindow display];
notificationWindow.fadeOut = msFade;
[notificationWindow setPrimaryText:lineOneText];
[notificationWindow setSecondaryText:lineTwoText];
[notificationWindow setIdentifierText:tag];
}
The window class is NotificationWindow.h
#import <Foundation/Foundation.h>
#interface NotificationWindow : NSWindow
#property (nonatomic, strong) NSString *tag;
#property (nonatomic) double fadeOut;
- (id)initWithRect:(NSRect)contentRect;
- (void) setPrimaryText:(NSString *)text;
- (void) setSecondaryText:(NSString *)text;
- (void) setIdentifierText:(NSString *)text;
#end
NotificationWindow.m
#import "NotificationWindow.h"
#import "NotificationView.h"
//===========================================================================================================================
// Private call properties and methods
//===========================================================================================================================
#interface NotificationWindow()
#property (nonatomic,strong) NSTimer *timerFade;
- (void) timerFadeFired;
#end
//===========================================================================================================================
//===========================================================================================================================
#implementation NotificationWindow
//===========================================================================================================================
// Property Getters and Setters
//===========================================================================================================================
#synthesize tag = _tag;
#synthesize fadeOut = _fadeOut;
#synthesize timerFade = _timerFade;
//===========================================================================================================================
// Public methods
//===========================================================================================================================
- (id)initWithRect:(NSRect)contentRect
{
if (self = [super initWithContentRect:contentRect
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO]) {
[self setLevel: NSScreenSaverWindowLevel];
[self setBackgroundColor: [NSColor clearColor]];
[self setAlphaValue: 1.0];
[self setOpaque: NO];
[self setHasShadow: NO];
[self setIgnoresMouseEvents: YES];
[self setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces];
[self orderFront: NSApp];
self.fadeOut = -1;
// Start our timer to deal with fadeing the window
self.timerFade = [NSTimer scheduledTimerWithTimeInterval:0.001
target:self
selector:#selector(timerFadeFired)
userInfo:nil
repeats:YES];
return self;
}
return nil;
}
- (BOOL) canBecomeKeyWindow
{
return YES;
}
- (void) display
{
[super display];
[self setAlphaValue:1.0];
}
- (void) setPrimaryText:(NSString *)text
{
NotificationView *view = self.contentView;
view.primaryLabel.stringValue = text;
}
- (void) setSecondaryText:(NSString *)text
{
NotificationView *view = self.contentView;
view.secondaryLabel.stringValue = text;
}
- (void) setIdentifierText:(NSString *)text
{
NotificationView *view = self.contentView;
view.identifierLabel.stringValue = text;
}
//===========================================================================================================================
// Private methods
//===========================================================================================================================
- (void) timerFadeFired
{
[self orderFront:NSApp];
if (self.fadeOut > 0)
{
self.fadeOut--;
}
else if (self.fadeOut == 0)
{
if (self.alphaValue > 0)
self.alphaValue -= 0.002;
else
self.fadeOut = -1;
}
}
#end
So I assume I'm doing something wrong connecting the labels to the IBOutlets, but I can't figure out what. I suppose I could create the view in code, but I was trying to be good and use the interface builder.
I'm in XCode 4.2.1.
Can anyone please suggest some links for using UITextField in cocos2d.
I want to press on label, then the UITextField should get selected and I need to edit on that UITextField.
I'm doing this in a current project to allow for entering the number of the level to start playing at, so that's why my variables and methods are named the way they are; you should probably adjust these to make sense for you.
In your app controller, define this as an instance variable:
UITextField *levelEntryTextField;
Create it inside applicationDidFinishLaunching:
levelEntryTextField = [[UITextField alloc] initWithFrame:
CGRectMake(60, 165, 200, 90)];
[levelEntryTextField setDelegate:self];
Define a method to activate the text field. You should also declare it in the header file for your app controller.
- (void)specifyStartLevel
{
[levelEntryTextField setText:#""];
[window addSubview:levelEntryTextField];
[levelEntryTextField becomeFirstResponder];
}
This will make pressing "return" on the keypad end editing
- (BOOL)textFieldShouldReturn:(UITextField*)textField {
//Terminate editing
[textField resignFirstResponder];
return YES;
}
This is triggered when the editing is actually done.
- (void)textFieldDidEndEditing:(UITextField*)textField {
if (textField==levelEntryTextField) {
[levelEntryTextField endEditing:YES];
[levelEntryTextField removeFromSuperview];
// here is where you should do something with the data they entered
NSString *result = levelEntryTextField.text;
}
}
Now to actually set things in motion, you put this somewhere. I call this from within one of my Scene classes, in response to a user action:
[[[UIApplication sharedApplication] delegate] specifyStartLevel];
I took the example that Jack provided and actually created a working project, this was done using the Cocos2D 0.7.1 XCode Template, and then just editting the *AppDelegate.m/.h files, which are provided below in there entirety. I also modified some of what Jack said, because I feel that creating the UITextField in the appDidFinishLoading would utilize a bit too much memory, especially if the text field is not used all the time ... this solution creates the text field only when it is needed, the sample draws an empty Cocos2D Layer scene, and on screen touch, it displays the text field for you to start entering text into. It will spit out the result of what you entered to the Console - you can pass this to whatever is necessary in your own code.
the .h
#import <UIKit/UIKit.h>
#import "cocos2d.h"
#interface MYSCENE : Layer <UITextFieldDelegate>
{
UITextField *myText;
}
-(void)specificStartLevel;
#end
#interface textFieldTestAppDelegate : NSObject <UIAccelerometerDelegate, UIAlertViewDelegate, UITextFieldDelegate, UIApplicationDelegate>
{
UIWindow *window;
}
#end
and then the .m
#import "textFieldTestAppDelegate.h"
#implementation MYSCENE
-(id) init
{
self = [super init];
isTouchEnabled = YES;
return self;
}
-(BOOL)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self specifyStartLevel];
return kEventHandled;
}
-(void)specifyStartLevel {
myText = [[UITextField alloc] initWithFrame:CGRectMake(60, 165, 200, 90)];
[myText setDelegate:self];
[myText setText:#""];
[myText setTextColor: [UIColor colorWithRed:255 green:255 blue:255 alpha:1.0]];
[[[[Director sharedDirector] openGLView] window] addSubview:myText];
[myText becomeFirstResponder];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField {
[myText resignFirstResponder];
return YES;
}
-(void)textFieldDidEndEditing: (UITextField *)textField {
if(textField == myText) {
[myText endEditing:YES];
[myText removeFromSuperview];
NSString *result = myText.text;
NSLog([NSString stringWithFormat:#"entered: %#", result]);
} else {
NSLog(#"textField did not match myText");
}
}
-(void) dealloc
{
[super dealloc];
}
#end
#implementation textFieldTestAppDelegate
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[window setUserInteractionEnabled:YES];
[[Director sharedDirector] setDisplayFPS:YES];
[[Director sharedDirector] attachInWindow:window];
Scene *scene = [Scene node];
[scene addChild: [MYSCENE node]];
[window makeKeyAndVisible];
[[Director sharedDirector] runWithScene: scene];
}
-(void)dealloc
{
[super dealloc];
}
-(void) applicationWillResignActive:(UIApplication *)application
{
[[Director sharedDirector] pause];
}
-(void) applicationDidBecomeActive:(UIApplication *)application
{
[[Director sharedDirector] resume];
}
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
[[TextureMgr sharedTextureMgr] removeAllTextures];
}
#end
To add Text field in cocos2d as below code
first of all you add view in Scene and afetr add textfield add in view thats very easy.
-(id) init
{
if( (self=[super init]) )
{
// add view in scene
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 568)];
view.backgroundColor = [UIColor redColor];
// add textfield in view
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 140, 300, 30)];
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.font = [UIFont systemFontOfSize:15];
textField.placeholder = #"enter text";
textField.autocorrectionType = UITextAutocorrectionTypeNo;
textField.keyboardType = UIKeyboardTypeDefault;
textField.returnKeyType = UIReturnKeyDone;
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.delegate = self;
[view addSubview:textField];
// add view in scene
[[[CCDirector sharedDirector] view] addSubview:view];
}
return self;
}
you can also use CCTextfield in cocos2d best example is https://github.com/iNinja/CCTextField
Try the following CCNode subclass, CCMenuItemTextField, to use text fields in cocos2d.
The class is directly subclassed from CCMenuItemSprite. When tapped, the "selected" method is called and a UITextField is added to the main window. After editing is done, "unselected" method is called and the UITextField is removed from screen. User's input is saved to a CCLabelTTF node, which position itself exactly as the original UITextField.
CCMenuItemTextField.h
#interface CCMenuItemTextField : CCMenuItemSprite<UITextFieldDelegate> {
UITextField *textField_;
CCLabelTTF *label_;
CGFloat paddingLeft_;
}
#property (readonly, nonatomic) UITextField *textField;
#property (readonly, nonatomic) CCLabelTTF *label;
#property (assign, nonatomic) CGFloat paddingLeft;
- (void)selected;
- (void)unselected;
- (void)setFontSize:(CGFloat)size;
- (NSString*)text;
- (void)setText:(NSString*)text;
#end
CCMenuItemTextField.m
#import "CCMenuItemTextField.h"
#implementation CCMenuItemTextField
#synthesize
textField = textField_,
label = label_,
paddingLeft = paddingLeft_;
- (id)init
{
CCSprite *normalSprite = [CCSprite spriteWithFile:#"text_field_background.png"];
CCSprite *selectedSprite = [CCSprite spriteWithFile:#"text_field_background.png"];
CCSprite *disabledSprite = [CCSprite spriteWithFile:#"text_field_background.png"];
return [self initWithNormalSprite:normalSprite selectedSprite:selectedSprite disabledSprite:disabledSprite];
}
- (id)initWithNormalSprite:(CCNode<CCRGBAProtocol> *)normalSprite
selectedSprite:(CCNode<CCRGBAProtocol> *)selectedSprite
disabledSprite:(CCNode<CCRGBAProtocol> *)disabledSprite
{
self = [super initWithNormalSprite:normalSprite
selectedSprite:selectedSprite
disabledSprite:disabledSprite
target:self
selector:#selector(selected)];
if (self) {
paddingLeft_ = 3.0;
textField_ = [[UITextField alloc] init];
[textField_ setTextColor:[UIColor blackColor]];
[textField_ setFont:[UIFont systemFontOfSize:18]];
label_ = [[CCLabelTTF node] retain];
[label_ setAnchorPoint:ccp(0,0.5)];
[label_ setFontSize:18];
[label_ setVisible:NO];
[label_ setColor:ccBLACK];
[self addChild:label_];
}
return self;
}
- (void)dealloc
{
[label_ release];
[textField_ release];
[super dealloc];
}
// --------------------------------
// Public
// --------------------------------
- (void)selected
{
[super selected];
[label_ setVisible:NO];
CGAffineTransform transform = [self nodeToWorldTransform];
float textFieldHeight = textField_.font.lineHeight;
float width = self.contentSize.width;
float height = self.contentSize.height;
float left = transform.tx + paddingLeft_;
float top = 480 - transform.ty - height + (height - textFieldHeight) / 2;
[textField_ setFrame:CGRectMake(left, top, width, height)];
[[[[CCDirector sharedDirector] view] window] addSubview:textField_];
[textField_ becomeFirstResponder];
[textField_ setDelegate:self];
}
- (void)unselected
{
[super unselected];
[label_ setVisible:YES];
[label_ setPosition:ccp(paddingLeft_, self.contentSize.height/2)];
NSString *text = textField_.text ? textField_.text : #"";
[label_ setString:text];
[textField_ resignFirstResponder];
[textField_ removeFromSuperview];
}
- (NSString*)text
{
return [label_ string];
}
- (void)setText:(NSString*)text
{
[label_ setString:text];
[textField_ setText:text];
}
// --------------------------------
// UITextFieldDelegate
// --------------------------------
- (BOOL)textFieldShouldReturn:(UITextField*)textField {
[self unselected];
return YES;
}
- (void)textFieldDidEndEditing:(UITextField*)textField {
[self unselected];
}
- (void)setFontSize:(CGFloat)size
{
[label_ setFontSize:size];
[textField_ setFont:[UIFont systemFontOfSize:size]];
}
// --------------------------------
// CCNode
// --------------------------------
- (void)onExitTransitionDidStart
{
[super onExitTransitionDidStart];
[self unselected];
}
#end