IPhone: How to put UITextField and UITableView on same View? recomended way - iphone

I am new to IOS development. I want to create the view like the shown in Pic.
I also want that when user write in textfield and Keyboard appears TextField scrollup to Keyboard and should be hidden behind Key board.
thanks, Help please

You can not use a UITableViewController but a standard view controller and implement UITableViewDelegate and UITableViewDataSource and implement the necessary delegate methods in your controller, like cellForRowAtIndexPath.
This will allow you to have a table view and control it like you would with a UITableViewController and have any other interface elements you wish.

You would want to add the textfield and button inside of the footer. You can use keyboard notifications to move the view offset so that your textfield will be visible when the user is typing in the keyboard.
Footer:
*I'm assuming the textfield and send button are ivars.
// add footer to table
UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.view.frame.size.width, 85.0f)];
if(yourTextField ==nil){
yourTextField = [[UITextField alloc] initWithFrame:CGRectMake(5,5,200,35)];
}
if(yourSendButton ==nil){
yourSendButton = [[UIButton alloc] initWithFrame:CGRectMake(225,5,75,35)];
yourSendButton addTarget:self action:#selector(sendBtnClicked) forControlEvents:UIControlEventTouchUpInside];
}
[footerView addSubview:yourTextField];
[footerView addSubview:yourSendButton];
[tableView setTableFooterView:footerView];
Here is some example code for moving the view for the keyboard:
- (void)keyboardWillShow:(NSNotification *)notification
{
NSValue *keyboardFrameValue = [[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardFrame = [[self view] convertRect:[keyboardFrameValue CGRectValue] fromView:nil];
NSNumber *duration = [[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey];
[UIView animateWithDuration:[duration floatValue] animations:^{
[scrollView setFrame:CGRectMake(scrollView.frame.origin.x,
scrollView.frame.origin.y,
scrollView.frame.size.width,
keyboardFrame.origin.y - scrollView.frame.origin.y)];
}];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
NSNumber *duration = [[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey];
[UIView animateWithDuration:[duration floatValue] animations:^{
[scrollView setFrame:CGRectMake(scrollView.frame.origin.x,
scrollView.frame.origin.y,
scrollView.frame.size.width,
self.view.frame.size.height - (iPhone ? 44.0f : 0.0f))];
}];
}

You will need to implement the UITableView's delegate methods:
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
an example of adding a textfield to the footer would look something like:
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;
{
UIView* footer = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)] autorelease];
footer.backgroundColor = [UIColor whiteColor];
UITextField* field = [[[UITextField alloc] initWithFrame:CGRectMake(0, 0, 320, 44)] autorelease];
[field setBorderStyle:UITextBorderStyleBezel];
[footer addSubview:field];
return footer;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
{
return 44;
}
To get the keyboard will respond properly automatically - you just just need to resign the textfield when you are done with it.

Related

need an advice with orientation change iphone

my problem might be simple to some of you but i can't find a solution. I have a method where a create my views automatically (text fields, labels and text views). It's like a registration form. The problem is that when i change the screen to landscape mode, i want to change the views width. To do that i used [self.view removeFromSuperview] and created the views again. The problem is that the views won't get recreated with the landscape width. I can't use IB to autosize the views at orientation change. The views are created in viewDidLoad and removed and recreated in - (void) adjustViewsForOrientation:(UIInterfaceOrientation)orientation {} I don't know why they don't get recreated after being removed. If there was another solution that you could share with me i would appreciate it.
Here's how i create the views:
-(void)createViews:(int)width
{
for(int i = 0; i < numberOfTextfields; i++) {
textfieldPadding = textfieldPadding+40;//set some space between the text fields
labelPadding = labelPadding+40;//set some space between the labels
UITextField *field = [[UITextField alloc] initWithFrame:
CGRectMake(10,i*textfieldHeight+textfieldPadding+firstTextfieldHeight+10,width, textfieldHeight)];
field.autoresizingMask = UIViewAutoresizingFlexibleWidth;
//field.backgroundColor= [UIColor cyanColor];
field.placeholder = [labels objectAtIndex:i];
field.borderStyle=UITextBorderStyleRoundedRect;
field.returnKeyType = UIReturnKeyDone;
[field addTarget:self action:#selector(doneButton:)
forControlEvents:UIControlEventEditingDidEndOnExit];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, i*labelHeight+firstLabelHeight+labelPadding-20, width, labelHeight)];
label.text = [labels objectAtIndex:i];
//label.backgroundColor = [UIColor brownColor];
[scrollView addSubview:field];
[scrollView addSubview:label];
[textfields addObject:field];
[labels addObject:label];
[field release];
[label release];
}
}
Here's where i wanted to remove them and recreate them:
- (void) adjustViewsForOrientation:(UIInterfaceOrientation)orientation
{
if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
[self.view removeFromSuperview];
[self createViews:landscapeWidth];
}
else if(orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
{
[self.view removeFromSuperview];
[self createViews:portraitWidth];
}
}
Thanks in advance!
Instead of removing, resizing and then re-adding as you currently are why not just set the appropriate autoresizingMask (link) when you create the view initially?
UITextField *myTextField = [[UITextField alloc] initWithFrame:someRect];
// the following will automatically resize the width on orientation change
myTextField.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[myView addSubview:myTextField];
[myTextField release];

How do I add elements above a UITableView that is animated down

Basically, I am trying to add a View above a UITableView programatically. The code below, will animate the UITableView down 150 Pixels and I would like to add elements to the space that is created above. But anytime I try to add something, like the Label in the code, it disappears. It's a UITableViewController so I am thinking that might have something to do with it.
Help!
- (IBAction)chooseCity:(id)sender {
[UIView beginAnimations:nil context: NULL];
[UIView setAnimationDuration:0.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
CGRect frame = self.tableView.frame;
if (frame.origin.y > 0) {
frame.origin.y = 0;
} else {
frame.origin.y += 150;
}
[self.tableView setFrame:frame];
[UIView commitAnimations];
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, -30, 200, 30)];
testLabel.text = #"Hello";
testLabel.backgroundColor = [UIColor redColor];
[self.view addSubview:testLabel];
}
If you want to add UILabel at top of view, you can add it in tableview's tableHeaderView property,
Allocate UILabel and assign it to tableHeaderView, Even you can put this part in UIView animation, so it will animate according to your requirement.
you can use
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, -30, 200, 30)];
testLabel.text = #"Hello";
testLabel.backgroundColor = [UIColor redColor];
tableView.tableHeaderView = testLabel;
[testLabel release];
//to add in footer tableView.tableFooterView = testLabel;
according to your condition you can set that to nil
tableView.tableHeaderView = testLabel;
Would implementing this in
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if (section == 0)
{
return someViewIWantInMyHeader;
}
}
and
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if (section == 0) {
return someSize;
}
}
not work for you?

Customizing UIPickerView (background and spacing)

I would like to change the white background in a UIPickerView to an image of my own.
Is this possible?
Also, I have managed to get my UIPickerView to scroll horizontally instead of vertical. Now, I would like to know if there is any way to adjust the spacing between two rows of the picker view?
I have attached an image to show what I mean.
This is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
arrayDays = [[NSMutableArray alloc] init];
[arrayDays addObject:#"ONSDAG"];
[arrayDays addObject:#"TORSDAG"];
[arrayDays addObject:#"FREDAG"];
[arrayDays addObject:#"LØRDAG"];
arrayDates = [[NSMutableArray alloc] init];
[arrayDates addObject:#"29. JUNI"];
[arrayDates addObject:#"30. JUNI"];
[arrayDates addObject:#"1. JULI"];
[arrayDates addObject:#"2. JULI"];
pickerViewDay = [[UIPickerView alloc] initWithFrame:CGRectZero];
[pickerViewDay setDelegate:self];
[pickerViewDay setShowsSelectionIndicator:NO];
CGAffineTransform rotate = CGAffineTransformMakeRotation(-M_PI/2);
rotate = CGAffineTransformScale(rotate, 0.25, 2.0);
[pickerViewDay setTransform:rotate];
[pickerViewDay setCenter:CGPointMake(self.view.frame.size.width/2, (pickerViewDay.frame.size.height/2)-3)];
[self.view addSubview:pickerViewDay];
// Adding selection indicator to pickerview
UIImage *selectorImage = [UIImage imageNamed:#"DayPickerView_SelectionIndicator.png"];
UIView *customSelector = [[UIImageView alloc] initWithImage:selectorImage];
[customSelector setFrame:CGRectMake(0, 0, 120, 74)];
[customSelector setCenter:CGPointMake(self.view.frame.size.width/2, customSelector.frame.size.height/2)];
[self.view addSubview:customSelector];
[customSelector release];
// Adding background to pickerview
UIImage *backgroundImage = [UIImage imageNamed:#"DayPickerView_Background.png"];
UIView *custombackground = [[UIImageView alloc] initWithImage:backgroundImage];
[custombackground setFrame:CGRectMake(0, 0, 320, 74)];
// [self.view addSubview:custombackground];
[custombackground release];
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
UIView *viewRow = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 150, 80)];
CGAffineTransform rotate = CGAffineTransformMakeRotation(3.14/2);
rotate = CGAffineTransformScale(rotate, 0.25, 2.0);
// Date
CGRect rectDate = CGRectMake(30, 0, 150, 80);
UILabel *date = [[UILabel alloc]initWithFrame:rectDate];
[date setTransform:rotate];
[date setText:[arrayDates objectAtIndex:row]];
[date setFont:[UIFont fontWithName:#"Arial-BoldMT" size:37.0]];
[date setShadowColor:[UIColor whiteColor]];
[date setShadowOffset:CGSizeMake(0, -1)];
[date setTextAlignment:UITextAlignmentCenter];
[date setBackgroundColor:[UIColor clearColor]];
[date setClipsToBounds:YES];
[viewRow addSubview:date];
// Day
CGRect rectDay = CGRectMake(-30, 0, 150, 80);
UILabel *day = [[UILabel alloc]initWithFrame:rectDay];
[day setTransform:rotate];
[day setText:[arrayDays objectAtIndex:row]];
[day setFont:[UIFont fontWithName:#"Arial-BoldMT" size:21.0]];
[day setTextColor:[UIColor colorWithRed:0.35 green:0.35 blue:0.35 alpha:1]];
[day setTextAlignment:UITextAlignmentCenter];
[day setBackgroundColor:[UIColor clearColor]];
[day setClipsToBounds:YES];
[viewRow addSubview:day];
return viewRow;
}
- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [arrayDays objectAtIndex:row];
}
- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component {
return [arrayDays count];
}
EDIT 1
For RickiG (on background):
EDIT 2
For RickiG:
Hi
There is no direct way to change the background. What you can do is to have the view you return in viewForRow feature its own background (then add the shadow in each side afterwards if you need it). You can also go looking for viewWithTag: but that is never a good idea as this might change in future iOS releases.
Is there a special reason you implement both viewForRow and TitleForRow? I usually just populate the viewForRow's labels inside this delegate method.
The viewForRow has the ability to reuse the views in the Picker, much like a UITableView you should test if the "reusingView:(UIView *)view" is nil and if not there is no need to draw everything again. Just populate the labels.
I usually never customize the picker, if I need something not completely custom I subclass the UITableView, it is much more flexible and can what the Picker does + more.
For the spacing you can use the "height" of the rows, the picker will center the views you return in viewForRow, then just make sure:
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
returns a value bigger than your view.
Held og lykke;)
I just figured out how to apply background color or image in the picker view. Hope it may help someone.
Just define a category in the file where you want to you picker view as follow:
#implementation UIPickerView(Extension)
-(void)drawRect:(CGRect)rect
{
NSArray* subviews = [self subviews];
for(UIView* view in subviews)
{
if([view isKindOfClass:[UITableView class]])
{
view.backgroundColor = appColor;
}
}
[super drawRect:rect];
}
#end
You can look further at subviews for more customization.
Looks like this is an old thread, but in iOS 7 (Possibly earlier, I'm not sure), UIPickerViews have a background color property, so setting the background color is simple:
[pickerView setBackgroundColor:[UIColor whiteColor]];
Setting a background image is similarly simple thanks to [UIColor colorWithPatternImage:]. (Note that the pattern will tile if the image is smaller than the UIPickerView.)
[pickerView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"someBackgroundImage.png"]]];
To modify the component widths you can implement the delegate method widthForComponent in order to set various widths for each component. In theory, you should be able to add an empty component and use it's blank width to create spacing, but I haven't tried this.
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component;
I haven't been able to find a way to change the padding between components which seems like a nicer way to modify the spacing and would also allows you to remove the ~5 px spacing between components, but if I'm able to find one I will update my answer.
How about adding an empty view on the right of your labels? And for the background you should probably use insertSubview:aboveView: method with the default background view as the second parameter (if you can access to it).

Update UIPickerView Number of Rows

I have a UIPickerView that is populated by an NSMutableArray called sectionNamesArray. When an item is added to sectionNamesArray, how do I manually get this delegate to be called?
-- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return ([sectionNamesArray count] + 1);
}
The problem is that I add this pickerView to the center of a navBar in the titleView. If I try to nil the UIPickerView and reallocate it in order to hopefully get the delegate called again, the PickerView shows up on the left side of the navbar, instead of the center. I am guessing maybe the interface builder settings got it in the center...?
Here's the code for that:
-(void) setupPickerView{
myPickerView = nil;
myPickerView = [[UIPickerView alloc] init];
myPickerView.backgroundColor = [UIColor clearColor];
myPickerView.delegate = self;
myPickerView.dataSource = self;
myPickerView.showsSelectionIndicator = YES;
[self.navigationController.navigationBar setBackgroundView:myPickerView];
CGSize pickerSize = [myPickerView sizeThatFits:CGSizeZero];
UIView *pickerTransformView = [[UIView alloc] initWithFrame:CGRectMake(-40.0, -43.0, pickerSize.width, pickerSize.height)];
pickerTransformView.transform = CGAffineTransformMakeScale(.55f, .55f);
[pickerTransformView addSubview:myPickerView];
[self.navigationController.navigationBar setBackgroundView:pickerTransformView];
}
When you add something to your array can't you use [UIPickerView reloadAllComponents] or - (void)reloadComponent:(NSInteger)component?
That will most likely query your delegate and call everything necessary to check your array and reload the view.

UIPickerView tap to scroll & custom row UIViews

You can scroll an UIPickerView both by swiping and by tapping items under or above the selection belt.
You can populate an UIPickerView by either specifying NSString as titles or reusable UIViews for each row.
What I've noticed is that when I switched from providing strings to providing view, tap to scroll no longer worked. Is this expected behavior. Should my views forward some touch events to the UIPickerView?
Thanks
EDIT:
Here's a code sample from my implementation:
// Creating the picker
screenPicker_ = [UIPickerView new];
screenPicker_.showsSelectionIndicator = YES;
screenPicker_.delegate = delegate_;
screenPicker_.dataSource = delegate_;
[self addSubview:screenPicker_];
[screenPicker_ release];
// Row view creation delegate
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
PickerRowView *pickerRowView = (PickerRowView*)view;
if(view == nil)
{
pickerRowView = [[PickerRowView alloc] initWithFrame:CGRectMake(0, 0, pickerView.frame.size.width, PICKER_ROW_HEIGHT)];
}
[pickerRowView SetTitle:#"some title"];
return pickerRowView;
}
// initailizer of the PickerRowView class (an UIView subclass)
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame]))
{
CGFloat titleHeight = frame.size.height * CONTENT_TO_FRAME_RATIO;
title_ = [[UILabel alloc] initWithFrame:CGRectMake(TITLE_X, (frame.size.height - titleHeight) / 2, frame.size.width, titleHeight)];
[title_ setFont:[UIFont fontWithName:#"StainlessExt-Light" size:titleHeight]];
title_.backgroundColor = [UIColor clearColor];
[self addSubview:title_];
[title_ release];
self.userInteractionEnabled = NO;
}
return self;
}
Setting userInteractionEnabled property to NO for your row views must solve your problem.
In your PickerRowView class, define the following method:
- (void)didMoveToSuperview {
if ([[self superview] respondsToSelector:#selector(setShowSelection:)])
{
[[self superview] performSelector:#selector(setShowSelection:) withObject:NO];
} }
and that should get rid of the highlight