iOS: Styling multiple textfields - objective-c

I have multiple UITextFields with the same/similar styling but I'm styling them individually. How would I style them all in on go?
example of what I'm doing now:
textfield1.layer.borderWith = 2;
textfield2.layer.borderWith = 2;
textfield3.layer.borderWith = 2;

Here's something I've used in the past:
UITextField * textField1;
UITextField * textField2;
UITextField * textField3;
for (UITextField * textField in #[textField1, textField2, textField3]) {
textField.layer.borderWidth = 2;
}
If you're doing extensive edits to create a highly customized textField, it might be better to use a subclass. If you've just got a few additions you want applied to each textfield, this should be fine.
As per your request, because I'm feeling generous. Here's an example of a UITextField subclass.
MyTextField.h
#import <UIKit/UIKit.h>
#interface MyTextField : UITextField
#end
MyTextField.m
#import "MyTextField.h"
#implementation MyTextField
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.layer.borderWidth = 2;
// Blue For Demonstration
self.layer.borderColor = [UIColor blueColor].CGColor;
// add whatever else you want to customize here ....
}
return self;
}
////////
////// ** Include Custom Methods You Might Need **
////////
#end
Then, in whatever ViewController or View you want to use it, add this:
#import "MyTextField.h"
Then, you can launch MyTextField class Textfields like this:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
MyTextField * textField1 = [MyTextField new];
textField1.frame = CGRectMake(10, 30, 100, 30);
[self.view addSubview:textField1];
MyTextField * textField2 = [MyTextField new];
textField2.frame = CGRectMake(10, 70, 100, 30);
[self.view addSubview:textField2];
MyTextField * textField3 = [MyTextField new];
textField3.frame = CGRectMake(10, 110, 100, 30);
[self.view addSubview:textField3];
}
And you'll get this:

How about --
for (UIView *view in [self.view subviews]) {
if ([view isKindOfClass:[UITextField class]]) {
UITextField *textField = (UITextField *)view;
textField.layer.borderWidth = 2.0;
}
}
That way you will not even have to have outlets of textFields in the view. But this is, of course, only applicable if you want to apply same styles to every textField in the view.

If the textfields have outlets, create an IBOutletCollection like so in your .h:
#property (strong, nonatomic) IBOutletCollection(UITextField) NSArray *textFields;
Then, in your .m:
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
for(UITextField *textField in self.textFields) {
textfield.layer.borderWith = 2;
// add more here as needed
}
}

Related

How to add swiple gesture with 3 buttons in a xib?

I have a table view where i m adding a cell for the content of the table view and i need to add swipeable gesture with 3 buttons in that that table cell.
u haven't provide enough info about how you are implementing the tableview cell but i assume that u are using the xib file and also i assume that u want to display the 3 button when table view cell is swiped ..
first of all u should subclass the table view cell in my example i named the cell class as CustomTableCell
in this cell's xib file i am adding the a view and 3 buttons, it is something look like below image
in the above image swipeView should be on top of content view and it holds your swipe gestures
for example in CustomTableCell.h file
#import <UIKit/UIKit.h>
#interface CustomTableCell : UITableViewCell
+ (id)createMenuCell;
#property (weak, nonatomic) IBOutlet UIView *swipeView;
#property (weak, nonatomic) IBOutlet UIButton *button3;
#property (weak, nonatomic) IBOutlet UIButton *button2;
#property (weak, nonatomic) IBOutlet UIButton *button1;
#property (assign, nonatomic) BOOL showButton;
- (IBAction)buttonOneAction:(id)sender;
- (IBAction)buttonTwoAction:(id)sender;
- (IBAction)buttonThreeAction:(id)sender;
#end
and in CustomTableCell.m file
#import "CustomTableCell.h"
#implementation CustomTableCell
#define MAX_LEFT 160 //set the how much view has to be move
#define ANIMATION_DUR 0.3
+ (id)createMenuCell
{
NSArray *xibElements = [[NSBundle mainBundle] loadNibNamed:#"CustomTableCell" owner:nil options:nil];
for(id item in xibElements)
{
if([item isKindOfClass:[CustomTableCell class]])
{
return (CustomTableCell *)item;
}
}
return nil;
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self)
{
[self setUpGestures];
}
return self;
}
- (void)awakeFromNib {
// Initialization code
_showButton = NO; //simple avoid unwanted swipes when showing the buttons
[self setUpGestures];
}
- (void)setUpGestures{
UISwipeGestureRecognizer *swipeLeftGesture = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swipeLeftGestureAction)]; //to open
swipeLeftGesture.direction = UISwipeGestureRecognizerDirectionLeft; //set the direction to swipe
[self.swipeView addGestureRecognizer:swipeLeftGesture];
UISwipeGestureRecognizer *swipeRightGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeRightGestureAction)]; //this is for closing
[self.swipeView addGestureRecognizer:swipeRightGesture];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
//button actions
- (IBAction)buttonOneAction:(id)sender {
NSLog(#"button one action");
}
- (IBAction)buttonTwoAction:(id)sender {
NSLog(#"button two action");
}
- (IBAction)buttonThreeAction:(id)sender {
NSLog(#"button three action");
}
//hear u are showing the buttons with left swipe
- (void)swipeLeftGestureAction
{
if(!_showButton)
{
CGRect destRect = self.swipeView.frame;
destRect.origin.x = -MAX_LEFT;
[UIView animateWithDuration:ANIMATION_DUR animations:^{
self.swipeView.frame = destRect;
} completion:^(BOOL finished) {
_showButton = YES;
}];
}
}
//hear u are hiding the buttons if it is shown
- (void)swipeRightGestureAction
{
if(_showButton)
{
CGRect destRect = self.swipeView.frame;
destRect.origin.x = 0;
[UIView animateWithDuration:ANIMATION_DUR animations:^{
self.swipeView.frame = destRect;
} completion:^(BOOL finished) {
_showButton = NO;
}];
}
}
Note: above is just i assumed so final result will be like below

can not show view on top of status bar, uiwindow, objective C

I am trying to put an overlay on top of status bar by doing the following :
ViewController implementation
- (IBAction)addViewOnTop:(id)sender {
StatusBarOverlayWindow *overlay = [[ACStatusBarOverlayWindow alloc] initWithFrame:CGRectMake(0, 0, 320, 20)];
overlay.hidden = NO;
[overlay makeKeyAndVisible];
}
StatusBarOverlayWindow header file
#import <UIKit/UIKit.h>
#interface StatusBarOverlayWindow : UIWindow {
}
#end
StatusBarOverLayWindow implementation
#implementation StatusBarOverlayWindow
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
// Place the window on the correct level and position
self.windowLevel = UIWindowLevelStatusBar + 1;
self.frame = frame;
self.backgroundColor = [UIColor orangeColor];
}
return self;
}
#end
When I click a button, nothing happens at all.
Does anyone have any thoughts about this issue. Please guide, thanks
Try keeping a strong reference to the StatusBarOverlayWindow, without that the variable will go out of scope after the addViewOnTop: method is complete. A property will work well here.
Example:
#interface ViewController : UIViewController
#property (nonatomic, strong) StatusBarOverlayWindow *overlayWindow;
#end
Then in your method:
- (IBAction)addViewOnTop:(id)sender {
self.overlayWindow = [[ACStatusBarOverlayWindow alloc] initWithFrame:CGRectMake(0, 0, 320, 20)];
overlay.hidden = NO;
[overlay makeKeyAndVisible];
}

How to add label inside ScrollView

I am a newbie to Xcode 5 and Objective C. I want to develop word processing app. Still, I can't figure how to do it with Xcode.
How do I add label inside ScrollView with swipe left to right direction: left to preview, right to next word?
How do I add 100 words to a UIlabel in Xcode?
For example, swiping right for next word, "Apple", then swiping right again for next word "Bananas"; Swiping left to preview: "Apple".
//scrollVC.h
#import <UIKit/UIKit.h>
#interface scrollVC : UIViewController
#property (weak, nonatomic) IBOutlet UIScrollView *mainScroll;
#end
//scrollVC.m
#import "scrollVC.h"
#interface scrollVC ()
#end
#implementation scrollVC
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.mainScroll setContentSize:CGSizeMake(960, 995)];
[self.mainScroll setPagingEnabled:YES];
UILabel *testLabel1 = [[UILabel alloc]initWithFrame:CGRectMake(350, 100, 100, 44)];
[testLabel1 setText:#"testLabel1"];
[testLabel1 setBackgroundColor:[UIColor redColor]];
[self.mainScroll addSubview:testLabel1];
UILabel *testLabel2 = [[UILabel alloc]initWithFrame:CGRectMake(660, 100, 100, 44)];
[testLabel2 setText:#"testLabel2"];
[testLabel2 setBackgroundColor:[UIColor redColor]];
[self.mainScroll addSubview:testLabel2];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
This is the behavior of UIScrollView paging. Here you can find documentation.
How can you add UILabel ( in general any instance on UIView ) to UIScrollView.
UIScrollView* scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
scrollView.pagingEnabled = YES; // replace default scroll with paging
for ( int i = 0; i < mWordsCount; i++ )
{
UILabel* textLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width * i, self.view.frame.size.height)];
textLabel.text = #"currnet word"; // wordsArray[i]; or [wordsArray objectAtIndex:i];
[scrollView addSubview:textLabel];
// Uncomment if you don't use ARC
//[textLabel release];
}

Trying to fix subview flipping and now subview buttons no longer work?

I have a view which includes two subviews. I had it working so that only one subview was shown at a time and each subview had a button and when the button was clicked the subview would flip over and the next subview would appear. The problem was that it appeared as though the entire view was flipping. After reading on this site about how to solve the problem I attempted to add the subviews to a container and flip that instead. However now, although my first subview is showing up when I press the button it no longer flip. It doesn't do anything. I put a log statement in the method which flips the subviews, as well as a breakpoint and as far as I can tell it no longer gets called. I'm very new to xcode and objective c and delegates and I have no idea how to proceed. Any help would be appreciated. Thanks.
I have included the relevant code here:
The header for the ViewController
#interface ExerciseViewController : UIViewController<ExerciseSubViewDelegate>
//stuff for subviews
#property (nonatomic, strong) ExerciseSubViewImage *subViewImage;
#property (nonatomic, strong) ExerciseSubViewText *subViewText;
#property UIView *panel;
#end
This is the code for the ViewController:
#interface ExerciseViewController ()
#end
#implementation ExerciseViewController
#synthesize subViewImage, subViewText;
- (void)viewDidLoad
{
self.subViewImage.delegate = self;
_panel = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.bounds.size.width, self.view.bounds.size.height/2)];
_panel.backgroundColor = [UIColor whiteColor];
[self.view addSubview:_panel];
[_panel addSubview:subViewImage];
}
-(ExerciseSubViewImage *)subViewImage
{
if (!subViewImage)
{
CGRect subViewImageFrame = CGRectMake(0,0, _panel.bounds.size.width, _panel.bounds.size.height);
self.subViewImage = [[ExerciseSubViewImage alloc] initWithFrame:subViewImageFrame];
[_panel addSubview:subViewImage];
}
return subViewImage;
}
-(ExerciseSubViewText *)subViewText
{
if (!subViewText)
{
CGRect subViewTextFrame = CGRectMake(0,0, _panel.bounds.size.width, _panel.bounds.size.height);
self.subViewText = [[ExerciseSubViewText alloc] initWithFrame:subViewTextFrame];
self.subViewText.backgroundColor = [UIColor blueColor];
[_panel addSubview:subViewText];
}
return subViewText;
}
-(void)exerciseSubViewImagePressed
{
[UIView transitionWithView:_panel
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
[subViewImage removeFromSuperview];
[_panel addSubview:subViewText];
}
completion: nil];
//This is how I did it before I added the container
/*[UIView transitionFromView:subViewImage
toView:subViewText
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromRight
completion:nil];
self.subViewText.delegate = self;*/
NSLog(#"Ipushedtheimage");
}
-(void)exerciseSubViewTextPressed
{//I haven't updated this yet
[UIView transitionFromView:subViewText
toView:subViewImage
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromRight
completion:nil];
self.subViewImage.delegate = self;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
subViewImage = nil;
subViewText = nil;
}
#end
This is the code for the delegate
#import
#protocol ExerciseSubViewDelegate <NSObject>
-(void) exerciseSubViewImagePressed;
-(void) exerciseSubViewTextPressed;
#end
I am also added the code for the first subview:
#import
#import "ExerciseSubViewDelegate.h"
#interface ExerciseSubViewImage : UIView
#property (nonatomic, strong) UIButton *button;
#property (nonatomic, assign) id<ExerciseSubViewDelegate>delegate;
#property (strong, nonatomic) UIImageView *exerciseImageView;
#end
#import "ExerciseSubViewImage.h"
#import "UIImage+animatedGIF.h"
#implementation ExerciseSubViewImage
#synthesize button;
#synthesize delegate;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
//Initialization code
self.button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
CGRect buttonFrame = CGRectMake(50,200,100,35);
self.button.frame = buttonFrame;
[self.button setTitle:#"Image"forState:UIControlStateNormal];
[self.button addTarget:self
action:#selector(buttonTouched)
forControlEvents:UIControlEventTouchUpInside];
[self addSubview:self.button];
_exerciseImageView = [[UIImageView alloc] initWithFrame:CGRectMake(50,20,160,158)];
NSURL *url = [[NSBundle mainBundle] URLForResource:#"AppleLogo" withExtension:#"gif"];
_exerciseImageView.image = [UIImage animatedImageWithAnimatedGIFURL:url];
[self addSubview:self.exerciseImageView];
}
return self;
}
-(void)buttonTouched
{
NSLog(#"imagebuttonpressed");
[self.delegate exerciseSubViewImagePressed];
}
Again, any help would be appreciate. I know I'm probably just not understanding something simple.
Ok. This took me all weekend but I finally figured it out on my own. I thought I would shere the answer here in case anyone else ever has a similar problem. After trying several other approaches I finally went back to the approach I used here and started inserting a whole bunch of NSLogs to determine the order that every thing was executing in. What I finally ended up doing was changing this: (all in the top ViewController)
self.subViewImage.delegate = self;
_panel = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.bounds.size.width, self.view.bounds.size.height/2)];
_panel.backgroundColor = [UIColor whiteColor];
[self.view addSubview:_panel];
[_panel addSubview:subViewImage];
to this:
//create panel
_panel = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.bounds.size.width, s self.view.bounds.size.height/2)];
_panel.backgroundColor = [UIColor whiteColor];
[self.view addSubview:_panel];
[_panel addSubview:subViewImage];
//Set the subview delegates
self.subViewImage.delegate = self;
self.subViewText.delegate = self;

UITextField shadow does not display when editing

I want to draw the text in an UITextField with a shadow. In order to do this, I have subclassed UITextField, and implemented the drawTextInRect: method as follows:
- (void)drawTextInRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
// Create shadow color
float colorValues[] = {0.21875, 0.21875, 0.21875, 1.0};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGColorRef shadowColor = CGColorCreate(colorSpace, colorValues);
CGColorSpaceRelease(colorSpace);
// Create shadow
CGSize shadowOffset = CGSizeMake(2, 2);
CGContextSetShadowWithColor(context, shadowOffset, 0, shadowColor);
CGColorRelease(shadowColor);
// Render text
[super drawTextInRect:rect];
}
This works great for when the text field is not editing, but as soon as editing begins, the shadow disappears. Is there anything I am missing?
Here is the code for following component
#interface AZTextField ()
- (void)privateInitialization;
#end
#implementation AZTextField
static CGFloat const kAZTextFieldCornerRadius = 3.0;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (!self) return nil;
[self privateInitialization];
return self;
}
// In case you decided to use it in a nib
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (!self) return nil;
[self privateInitialization];
return self;
}
- (void)privateInitialization
{
self.borderStyle = UITextBorderStyleNone;
self.layer.masksToBounds = NO;
self.layer.shadowColor = [UIColor blackColor].CGColor;
self.layer.shadowOffset = CGSizeMake(0.0f, 5.0f);
self.layer.shadowOpacity = 0.5f;
self.layer.backgroundColor = [UIColor whiteColor].CGColor;
self.layer.cornerRadius = 4;
// This code is better to be called whenever size of the textfield changed,
// so if you plan to do that you can add an observer for bounds property
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:kAZTextFieldCornerRadius];
self.layer.shadowPath = shadowPath.CGPath;
}
#end
Couple of things to consider:
You want to set borderStyle to none, otherwise you'll end up with
UIKit putting subviews into your textfield
Depending on the Xcode
version you might want to link QuartzCore and to #import
<QuartzCore/QuartzCore.h>
For more complex appearance you can still
use shadow properties of the layer and move the drawing code itself
into the drawRect: method, but jake_hetfield was right if you
override drawRect you don't want to call super, especially in the end
of the method
As for the text drawing (you can see that it sticks to
close to the component borders), you have a separate
drawTextInRect: and drawPlaceholderInRect: method that draws the
text and placeholder respectively
You can use UIColor method for
colors and call CGColor property, it makes code more readable and
easier to maintain
Hope that helps!
Inspired by #jake_hetfield answer I created a custom UITextField that uses an internal label to do the drawing, check it out:
ShadowTextField .h file
#import <UIKit/UIKit.h>
#interface ShadowTextField : UITextField
// properties to change the shadow color & offset
#property (nonatomic, retain) UIColor *textShadowColor;
#property (nonatomic) CGSize textShadowOffset;
- (id)initWithFrame:(CGRect)frame
font:(UIFont *)font
textColor:(UIColor *)textColor
shadowColor:(UIColor *)shadowColor
shadowOffset:(CGSize)shadowOffset;
#end
ShadowTextField .m file
#import "ShadowTextField.h"
#interface ShadowTextField ()
#property (nonatomic, retain) UILabel *internalLabel;
#end
#implementation ShadowTextField
#synthesize internalLabel = _internalLabel;
#synthesize textShadowColor = _textShadowColor;
#synthesize textShadowOffset = _textShadowOffset;
- (id)initWithFrame:(CGRect)frame
font:(UIFont *)font
textColor:(UIColor *)textColor
shadowColor:(UIColor *)shadowColor
shadowOffset:(CGSize)shadowOffset
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
// register to my own text changes notification, so I can update the internal label
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(handleUITextFieldTextDidChangeNotification)
name:UITextFieldTextDidChangeNotification
object:nil];
self.font = font;
self.textColor = textColor;
self.textShadowColor = shadowColor;
self.textShadowOffset = shadowOffset;
}
return self;
}
// when the user enter text we update the internal label
- (void)handleUITextFieldTextDidChangeNotification
{
self.internalLabel.text = self.text;
[self.internalLabel sizeToFit];
}
// init the internal label when first needed
- (UILabel *)internalLabel
{
if (!_internalLabel) {
_internalLabel = [[UILabel alloc] initWithFrame:self.bounds];
[self addSubview:_internalLabel];
_internalLabel.font = self.font;
_internalLabel.backgroundColor = [UIColor clearColor];
}
return _internalLabel;
}
// override this method to update the internal label color
// and to set the original label to clear so we wont get two labels
- (void)setTextColor:(UIColor *)textColor
{
[super setTextColor:[UIColor clearColor]];
self.internalLabel.textColor = textColor;
}
// override this method to update the internal label text
- (void)setText:(NSString *)text
{
[super setText:text];
self.internalLabel.text = self.text;
[self.internalLabel sizeToFit];
}
- (void)setTextShadowColor:(UIColor *)textShadowColor
{
self.internalLabel.shadowColor = textShadowColor;
}
- (void)setTextShadowOffset:(CGSize)textShadowOffset
{
self.internalLabel.shadowOffset = textShadowOffset;
}
- (void)drawTextInRect:(CGRect)rect {
// don't draw anything
// we have the internal label for that...
}
- (void)dealloc {
[_internalLabel release];
[_textShadowColor release];
[super dealloc];
}
#end
Here is how you use it in your view controller
- (void)viewDidLoad
{
[super viewDidLoad];
ShadowTextField *textField = [[ShadowTextField alloc] initWithFrame:CGRectMake(0, 0, 320, 30)
font:[UIFont systemFontOfSize:22.0]
textColor:[UIColor whiteColor]
shadowColor:[UIColor redColor]
shadowOffset:CGSizeMake(0, 1) ] ;
textField.text = #"This is some text";
textField.backgroundColor = [UIColor blackColor];
[self.view addSubview:textField];
}
You could try to do the drawing of the label yourself. Remove
[super drawTextInRect:rect]
And instead draw your own label. I haven't tried this but it could look something like this:
// Declare a label as a member in your class in the .h file and a property for it:
UILabel *textFieldLabel;
#property (nonatomic, retain) UILabel *textFieldLabel;
// Draw the label
- (void)drawTextInRect:(CGRect)rect {
if (self.textFieldLabel == nil) {
self.textFieldLabel = [[[UILabel alloc] initWithFrame:rect] autorelease];
[self.view addSubview:myLabel];
}
self.textFieldLabel.frame = rect;
self.textFieldLabel.text = self.text;
/** Set the style you wish for your label here **/
self.textFieldLabel.shadowColor = [UIColor grayColor];
self.textFieldLabel.shadowOffset = CGSizeMake(2,2);
self.textFieldLabel.textColor = [UIColor blueColor];
// Do not call [super drawTextInRect:myLabel] method if drawing your own text
}
Stop calling super and render the text yourself.
Have your tried with the standard shadow properties of the CALayer? it usually is enough and it is lot simpler. Try something like this with a regular UITextField:
self.inputContainer.layer.shadowColor=[UIColor blackColor].CGColor;
self.inputContainer.layer.shadowRadius=8.0f;
self.inputContainer.layer.cornerRadius=8.0f;
self.inputContainer.layer.shadowOffset=CGSizeMake(0, 4);
You need to import QuartzCore first of course!
#import <QuartzCore/QuartzCore.h>