I'm new to Objective-c and i've reached an issue.
I'm trying to make a small scoreboard app, for learning more of the language.
Here is a small part of the app.
What i want it it to do is to add a new UItext field when you press the add button. So on button click it looks like this.
How can i add multiple UItextfields on button click in objective-c?
This is a very simple requirement. All you have to do is to create and add the new "Player Number" text field and "Fouls" label each time you tap the "Add" button. After this, move the "Add" button downwards and that's it. Here is some example code.
First of all, to keep things simple I created a UIViewController subclass to hold the "Player Number" text box and the "Fouls" label to make it easy to create them multiple times. Here is the class:
// The .h file
#import <UIKit/UIKit.h>
#interface LLPlayerViewController : UIViewController
// This is a very simple class with no public properties or methods
#end
// The .m file
#implementation LLPlayerViewController
-(void)loadView {
// Create the initial view
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 190, 25)];
self.view = view;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// PlayerNumber Text Field
UITextField *playerNumberField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 120, 20)];
playerNumberField.placeholder = #"PlayerNumber";
playerNumberField.borderStyle = UITextBorderStyleLine;
[self.view addSubview:playerNumberField];
// Fouls Label
UILabel *foulsLabel = [[UILabel alloc] initWithFrame:CGRectMake(135, 0, 50, 20)];
foulsLabel.text = #"0";
[self.view addSubview:foulsLabel];
}
#end
Then, in the main View Controller I create instances of that class and add them to the view each time I press the "Add" button. Here is some sample code:
// Don't forget to import the previous class
#import "LLPlayerViewController.h"
- (void)viewDidLoad
{
[super viewDidLoad];
// Inside viewDidLoad add the following code:
self.playersArray = [[NSMutableArray alloc] init];
// PLAYER Header
UILabel *playerLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 25, 80, 20)];
playerLabel.text = #"PLAYER";
[self.view addSubview:playerLabel];
// FOULS Header
UILabel *foulsLabel = [[UILabel alloc] initWithFrame:CGRectMake(145, 25, 80, 20)];
foulsLabel.text = #"FOULS";
[self.view addSubview:foulsLabel];
// Add player button
self.addPlayerButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.addPlayerButton.frame = CGRectMake(30, 60, 80, 30);
[self.addPlayerButton setTitle:#"Add" forState:UIControlStateNormal];
[self.addPlayerButton addTarget:self action:#selector(addPlayerTapped:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.addPlayerButton];
}
// This method will get called each time the user taps the "Add" button
-(void)addPlayerTapped:(id)sender {
NSLog(#"Adding Player");
self.yOffset = 60.0;
LLPlayerViewController *llVC = [[LLPlayerViewController alloc] init];
llVC.view.alpha = 0.0;
[self.playersArray addObject:llVC];
[self.view addSubview:llVC.view];
[self repositionFields];
}
// This method is responsible for repositioning the views
-(void)repositionFields {
// Reposition each view in the array
for (LLViewController *llVC in self.playersArray) {
CGRect frame = llVC.view.frame;
frame.origin.x = 15;
frame.origin.y = self.yOffset;
llVC.view.frame = frame;
self.yOffset += frame.size.height;
}
// Add some animations to make it look nice
[UIView animateWithDuration:0.3 animations:^{
CGRect frame = self.addPlayerButton.frame;
frame.origin.y = self.yOffset;
self.addPlayerButton.frame = frame;
} completion:^(BOOL finished) {
LLViewController *llVC = [self.playersArray lastObject];
llVC.view.alpha = 1.0;
}];
}
This code was tested on an iPad simulator but I believe it would also work on an iPhone. The code is straight-forward and self explanatory but let me know if you have any more questions.
Hope this helps!
Related
An attempt to programmatically create a rounded rectangular button in an Objective-C View Controller in Xcode 6 and iOS 8.1 only produces a non-rounded rect button. The UIButton buttonWithType: method is being used.
Why?
//
// ViewController.m
//
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)loadView // Called the first time the view property is accessed.
{
CGRect viewRect = [[UIScreen mainScreen] bounds];
UIView *view = [[UIView alloc] initWithFrame:viewRect];
self.view = view;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Set the view's background color.
self.view.backgroundColor = [UIColor colorWithRed:0.462 green:0.999 blue:0.999 alpha:1.0];
// Create a button.
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
// Place and size the button on the screen.
btn.frame = CGRectMake(100, 100, 90, 44);
// Set the button's background color.
btn.backgroundColor = [UIColor yellowColor];
// Set the button's normal title.
[btn setTitle:#"Test Button" forState:UIControlStateNormal];
// Add the button as a subview.
[self.view addSubview:btn];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Add this line and try:
btn.layer.cornerRadius = 5;
Purpose:
I want to set right view as label in searchbar's textfield
Following Code working fine in ios 6 for doing the same thing:
UISearchBar *search = [[UISearchBar alloc] init];
[search setTintColor:[UIColor grayColor]];
search.frame = CGRectMake(0, 150, 320,50);
search.delegate = self;
UITextField *searchField=[search.subviews objectAtIndex:1];//Changed this line in ios 7
searchField.backgroundColor=[UIColor redColor];
UILabel *label=[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
label.text=#"Hello";
label.textColor=[UIColor greenColor];
searchField.rightView = label;
searchField.rightViewMode = UITextFieldViewModeAlways;
[self addSubView:search];
When i have Run the same code in ios 7(with xcode 7.0.2 fully updated), It was giving me error, after googling i got that hiearchy of searchbar to textfield has been changed, so i have modified my code as:
replaced commented line in above code with:
UITextField *searchField=[((UIView *)[search.subviews objectAtIndex:0]).subviews lastObject];
after doing this, it is not giving me any error(also checked the logs by printing the description of textfield and everything is working good), when i run it, it gives textfield with red background but the rightView's label is not shown to me. Now, can anyone help me how to show this rightview.
If you want to do this programatically then you have to declare UISearchBar object in your .h file.
UISearchBar *searchBar;
And in your .m file you can code like:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
searchBar = [[UISearchBar alloc] init];
[searchBar setTintColor:[UIColor grayColor]];
searchBar.frame = CGRectMake(0, 150, 320,50);
searchBar.delegate = self;
[self.view addSubview:searchBar];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UITextField *searchField;
if ([[[UIDevice currentDevice] systemVersion] floatValue]<7.0)
searchField=[searchBar.subviews objectAtIndex:1];
else
searchField=[((UIView *)[searchBar.subviews objectAtIndex:0]).subviews lastObject];
searchField.backgroundColor=[UIColor redColor];
UILabel *label=[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
label.text=#"Hello";
label.textColor=[UIColor greenColor];
searchField.rightView = label;
searchField.rightViewMode = UITextFieldViewModeAlways;
}
I think this will work for both iOS7 and prior versions of iOS7.
First of all, your approach is not good and not maintainable across iOS versions.
I think that initialization of UISearchBarTextField's right view is taking place after you set your custom view to it's rightView property. You will see correct result if you set searchField.rightView in viewDidAppear method:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UITextField *searchField=[((UIView *)[_searchBar.subviews objectAtIndex:0]).subviews lastObject];
UILabel *label=[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
label.text=#"Hello";
label.textColor=[UIColor greenColor];
searchField.rightView = label;
searchField.rightViewMode = UITextFieldViewModeAlways;
}
I've tested it on iOS 7 simulator and it works.
You have to get the text field first.
No need to index subviews to get text field or bar button.
You can directly get the text field and bar button
In swift
let textField = searchBar.valueForKey("searchField") as? UITextField
let cancelBarButton = searchBar.valueForKey("cancelBarButtonItem") as? UIBarButtonItem
In Objective-C
UITextField *textField = [searchBar valueForKey:#"searchField"]:
UIBarButtonItem *cancelBarButton = [searchBar valueForKey:#"cancelBarButtonItem"]:
Then you can set the left view and right view with
textField.leftView = yourView
textField.rightView = yourView
I have an animation that moves an image to the right then stops when I let go of the button. I need the frame of the image to be different at different times so I used a CGRect variable in place of myImageView.frame = CGRectMake. But when I use the variable image hops back to its original spot every time I let go instead of stoping in place like usual.
if (myInt == 2) {
MyCGRect = CGRectMake(myImageView.frame.origin.x,myImageView.frame.origin.y,18,42);
} else {
MyCGRect = CGRectMake(myImageView.frame.origin.x,myImageView.frame.origin.y,35,28);
}
-(IBAction)holdToMakeImageMove:(id)sender
{
//!!!!!This Works!!!!!!
myImageView.frame = CGRectMake(myImageView.frame.origin.x,myImageView.frame.origin.y,18,42);
//!!!!!!THIS doesnt work
myImageView.frame = MyCGRect;
//...animation
}
For example, this code works for me. Change button frame from (0,800,50,50) to (0,0,100,100)
#interface ViewController ()
...
#property (nonatomic, assign) CGRect myRect;
...
#end
#implementation ViewController
...
#synthesize myRect = _myRect;
...
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setFrame:CGRectMake(0, 800, 50, 50)];
[btn addTarget:self action:#selector(avvia:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
self.myRect = CGRectMake(100, 0, 100, 100);
}
...
- (void)avvia:(id)sender {
((UIButton *)sender).frame = self.myRect;
}
...
#end
In my TestApp, I created a class "Carousel" which should let me create a swipe menu with a UIPageControl in an easy way (by simply creating an instance of the class Carousel).
Carousel is a subclass of UIView
At init, it creates an UIView, containing UIScrollView, UIPageControl
I can add further UIViews to the scroll view
I don't know if this is the proper way to do it, but my example worked quite well in my TestApp. Swiping between pages works perfectly and the display of the current page in the UIPageControl is correct.
If there were not one single problem: The UIPageControl sometimes reacts to clicks/taps (I only tested in Simulator so far!), sometimes it doesn't. Let's say most of the time it doesn't. I couldn't find out yet when it does, for me it's just random...
As you can see below, I added
[pageControl addTarget:self action:#selector(pageChange:) forControlEvents:UIControlEventValueChanged];
to my code. I thought this would do the proper handling of taps? But unfortunately, pageChange doesn't get always called (so the value of the UIPageControl doesn't change every time I click).
I would appreciate any input on this because I couldn't find any solution on this yet.
This is what I have so far:
Carousel.h
#import <UIKit/UIKit.h>
#interface Carousel : UIView {
UIScrollView *scrollView;
UIPageControl *pageControl;
BOOL pageControlBeingUsed;
}
- (void)addView:(UIView *)view;
- (void)setTotalPages:(NSUInteger)pages;
- (void)setCurrentPage:(NSUInteger)current;
- (void)createPageControlAt:(CGRect)cg;
- (void)createScrollViewAt:(CGRect)cg;
#end
Carousel.m
#import "Carousel.h"
#implementation Carousel
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Create a scroll view
scrollView = [[UIScrollView alloc] init];
[self addSubview:scrollView];
scrollView.delegate = (id) self;
// Init Page Control
pageControl = [[UIPageControl alloc] init];
[pageControl addTarget:self action:#selector(pageChange:) forControlEvents:UIControlEventValueChanged];
[self addSubview:pageControl];
}
return self;
}
- (IBAction)pageChange:(id)sender {
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * pageControl.currentPage;
frame.origin.y = 0;
[scrollView scrollRectToVisible:frame animated:TRUE];
NSLog(#"%i", pageControl.currentPage);
}
- (void)addView:(UIView *)view {
[scrollView addSubview:view];
}
- (void)createPageControlAt:(CGRect)cg {
pageControl.frame = cg;
}
- (void)setTotalPages:(NSUInteger)pages {
pageControl.numberOfPages = pages;
}
- (void)setCurrentPage:(NSUInteger)current {
pageControl.currentPage = current;
}
- (void)createScrollViewAt:(CGRect)cg {
[scrollView setPagingEnabled:TRUE];
scrollView.frame = cg;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width*pageControl.numberOfPages, scrollView.frame.size.height);
[scrollView setShowsHorizontalScrollIndicator:FALSE];
[scrollView setShowsVerticalScrollIndicator:FALSE];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
float frac = scrollView.contentOffset.x / scrollView.frame.size.width;
NSUInteger page = lround(frac);
pageControl.currentPage = page;
}
#end
ViewController.m (somewhere in viewDidLoad)
Carousel *carousel = [[Carousel alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
for (int i=0; i<5; i++) {
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(i * 320, 0, 320, 420)];
UIColor *color;
if(i%3==0) color = [UIColor blueColor];
else if(i%3==1) color = [UIColor redColor];
else color = [UIColor purpleColor];
view.backgroundColor = color;
[carousel addView:view];
view = nil;
}
[carousel setTotalPages:5];
[carousel setCurrentPage:0];
[carousel createPageControlAt:CGRectMake(0,420,320,40)];
[carousel createScrollViewAt:CGRectMake(0,0,320,420)];
Your code is correct. Most likely the frame of your pageControl is pretty small, so theres not a lot of area to look for touch events. You would need to increase the size of the height of pageControl in order to make sure taps are recognized all of the time.
I have a scroll view that doesn't scroll right, I've simplified the code for below.
It draws the view and some horizontal buttons that i add more stuff to in the real code.
If you drag the whitespace between the buttons the view scrolls. If you happen to put your finger on a button, it won't scroll.
After a related suggestion, I tried to add the delaysContentTouches = YES line, but it doesn't seem to make a difference.
UIScrollview with UIButtons - how to recreate springboard?
What am I doing wrong?
TIA,
Rob
Updated the code
- (void)viewDidLoad {
l = [self landscapeView];
[self.view addSubview:l];
[l release];
}
- (UIScrollView *) landscapeView {
// LANDSCAPE VIEW
UIScrollView *landscapeView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 325)];
landscapeView.backgroundColor = [UIColor whiteColor];
landscapeView.delaysContentTouches = YES;
NSInteger iMargin, runningY, n;
iMargin = 3;
runningY = iMargin;
for (n = 1; n <= 38; n++) {
//add day labels
UIButton *templabel = [[UIButton alloc] initWithFrame:CGRectMake(iMargin,runningY,320 - ( 2 * iMargin),20)];
templabel.backgroundColor = [UIColor grayColor];
[landscapeView addSubview:templabel];
[templabel release];
runningY = runningY + 30;
}
landscapeView.contentSize = CGSizeMake( 320, runningY);
return landscapeView;
}
I can't duplicate your results; when I create a scrollView and add buttons, scrolling is still active even when doing a touch-down on the button. Are you setting any other UIScrollView properties, or subclassing any methods, that aren't showing up in your simplified code?
It looks like one thing that's going on is that the getter for landScapeView is a complicated constructor...so every time you do [self landscapeView] or self.landscapeView, you're creating a whole new UIScrollView and operating on that.
I'd try something like this in your .h file:
#interface MyClass: MyParent {
UIScrollView *landscapeView;
}
#property (retain) UIScrollView *landscapeView;
...and this in your .m file:
#implementation MyClass
#synthesize landscapeView;
(void)viewDidLoad
{ l = [[[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 325)] autorelease];
[self.view addSubview:self.landscapeView]; [l release];
landscapeView.backgroundColor = [UIColor whiteColor];
landscapeView.delaysContentTouches = YES;
NSInteger iMargin, runningY, n;
iMargin = 3;
runningY = iMargin;
for (n = 1; n <= 38; n++) { //add day labels
UIButton *templabel = [[UIButton alloc] initWithFrame:CGRectMake(iMargin,runningY,320 - ( 2 * iMargin),20)];
templabel.backgroundColor = [UIColor grayColor];
[landscapeView addSubview:templabel];
[templabel release]; runningY = runningY + 30;
}
landscapeView.contentSize = CGSizeMake( 320, runningY);
}