I have to create a tableview with one of the cell having a scrollview with paging enabled and paging control in it. I have already tried following.
I have created a TableView Cell in IB which has two things in it
1.ScrollView
2.Page control and some labels placed at runtime on each page of scrollview, I have tested this scrollview and paging control in normal view and it works as expected.
I have following code in the ScrollViewCell.h
#import <UIKit/UIKit.h>
#interface ScrollViewCell : UITableViewCell<UIScrollViewDelegate>
{
UIPageControl* pageControl;
UIScrollView* scrollView;
BOOL pageControlBeingUsed;
}
#property (nonatomic, retain) IBOutlet UIScrollView* scrollView;
#property (nonatomic, retain) IBOutlet UIPageControl* pageControl;
- (IBAction)changePage;
#end
And following code in ScrollViewCell.m
#import "ScrollViewCell.h"
#implementation ScrollViewCell
#synthesize scrollView;
#synthesize pageControl;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString*)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
NSArray *colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor], [UIColor blueColor], nil];
for (int i = 0; i < colors.count; i++) {
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
subview.backgroundColor = [UIColor grayColor];
[self.scrollView addSubview:subview];
// add buttons
CGRect Frame= CGRectMake(frame.origin.x,frame.origin.y,200,50);
//set your x and y position whatever u want.
UIButton *Button = [UIButton buttonWithType:UIButtonTypeCustom];
Button.frame = Frame;
UIImage *Img = [UIImage imageNamed:#"second.png"];
[Button setBackgroundImage:Img forState:UIControlStateNormal];
[scrollView addSubview: Button];
// add text
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(frame.origin.x,frame.origin.y+60,200,50)];
label.textAlignment = UITextAlignmentCenter;
label.text = #"Here you write your text";
label.textColor = [UIColor blackColor];
[scrollView addSubview:label ];
[subview release];
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * colors.count, self.scrollView.frame.size.height);
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)scrollViewDidScroll:(UIScrollView *)sender {
if (!pageControlBeingUsed) {
// Switch the indicator when more than 50% of the previous/next page isvisible
CGFloat pageWidth = self.scrollView.frame.size.width;
int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl.currentPage = page;
}
}
- (IBAction)changePage {
// update the scroll view to the appropriate page
CGRect frame;
frame.origin.x = self.scrollView.frame.size.width * self.pageControl.currentPage;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
[self.scrollView scrollRectToVisible:frame animated:YES];
pageControlBeingUsed = YES;
}
#end
I am loading this cell in the table view as follows
static NSString *CellIdentifier = #"ScrollViewCell";
ScrollViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[ScrollViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
return cell;
When I am running this app it shows an empty table with desired height but nothing in it.
Is my approach correct ? if yes whats missing ?
Thanks
Regards
Vishal
You are trying to add customize your UIScrollView in UITableViewCell class itself, i am not sure whether it will work.
instead try like this in your UITableView class cellForRowAtIndexPath,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * CellIdentifier = #"GroupButtonCell";
CustomCell * cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray * customcellArray = [[NSBundle mainBundle]loadNibNamed:#"CustomCell" owner:self options:nil];
for(id customcellObject in customcellArray){
if([customcellObject isKindOfClass: [UITableViewCell class]]){
cell = (CustomCell *)customcellObject;
break;
}
}
}
// Customize your UIScrollView here..
[cell.scrollView setDelegate:self];
[cell.scrollView setPagingEnabled:YES];
NSArray *colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor],[UIColor blueColor], nil];
cell.scrollView.contentSize = CGSizeMake(cell.scrollView.frame.size.width * colors.count,cell.scrollView.frame.size.height);
for (int i = 0; i < colors.count; i++) {
CGRect frame;
frame.origin.x = cell.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = cell.scrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
subview.backgroundColor = [colors objectAtIndex:i];
[cell.scrollView addSubview:subview];
}
// Configure the cell...
return cell;
}
try this in ScrollViewCell.m
Inside init method.
[self.contentView addSubview:scrollView];
You should add scrollview on cell. Check M not sure. I dint got time to try in project.
Related
I want to display table view in which every cell contain nested UIview but i am facing some problems.
1) My app crash when i try to scroll table view.
Solved by add root view instead of subview into app delegate
Now problem number 2
2) I want to add horizontal scroll view inside table cell.so i can display 3 subview in single cell and i can scroll horizontally with in cell..how can i do that.
I want to do this..
To achive this i have code this..
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
UIView *wagon = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 430, 187)];
UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"wagon.png"]];
wagon.backgroundColor = background;
UIScrollView *scrollview = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 830, 187)];
scrollview.showsVerticalScrollIndicator=YES;
scrollview.scrollEnabled=YES;
scrollview.userInteractionEnabled=YES;
UIView *videoview = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 220 , 100)];
UIImageView *video = [[UIImageView alloc]initWithFrame:CGRectMake(wagon.frame.origin.x+18, wagon.frame.origin.y+35, 220, 100)];
UIImage *bgImage = [UIImage imageNamed:#"video.png"];
video.image = bgImage;
videoview.contentMode = UIViewContentModeLeft;
[videoview addSubview:video];
UIView *textview = [[UIView alloc]initWithFrame:CGRectMake(wagon.frame.origin.x+238,wagon.frame.origin.y+28, 150 , 187)];
textview.contentMode = UIViewContentModeRight;
UILabel * label = [[UILabel alloc]initWithFrame:CGRectMake(28,10, 150 , 87)];
label.text=#"This is testing text for IOS app to check line are aligned or not and to check video image and nested views for UIviews";
label.backgroundColor = [UIColor clearColor];
label.textColor=[UIColor redColor];
label.numberOfLines = 4;
[textview addSubview:label];
[wagon addSubview:textview];
[wagon addSubview:videoview];
[scrollview addSubview:wagon];
[self addSubview:scrollview];
}
return self;
}
and call this view from table cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = #"StateCell";
UITableViewCell *cell;
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Wagon1 *wg=[[Wagon1 alloc]init];
[cell addSubview:wg];
return cell;
}
by adding wg i get one train boggi, wagon view.. i want 2 wagon view and engine at last or first.
** Table crashing problem is solve**
1) to solve crashing problem i search on stackoverflow and i found solution like adding to delegates or change to retain or strong bla bla.. but non of these work for me.
Here is my code. and one more thing i am not use XIB , nib or storyboard..
#interface MainScreenViewController : UIViewController
{
UITableView* table;
NSString * name;
}
#property (strong, retain) UITableView *table;
#property (strong, retain) NSString *name;;
#end
.m file
#interface MainScreenViewController ()
#end
#implementation MainScreenViewController
#synthesize table;
#synthesize name;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:Nil bundle:Nil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
name=[[NSString alloc]init];
name=#"testing of row";
CGRect frame = self.view.frame;
table= [[UITableView alloc] initWithFrame:frame];
table.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
[table setDelegate:self];// app crash here
table.dataSource = self;// here also
[table reloadData];
[self.view addSubview:table];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 8;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return #"test";
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath*)indexPath;
{
return 190;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = name;
return cell;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I tried your code and it is working perfectly for me , I guess problem should be with view controller initialisation , try this Applications are expected to have a root view controller at the end of application launch and let me know.
As you have mentioned
i have added both but still it crash..i got this 2013-04-23 12:37:28.361 AMM[2231:c07] Application windows are expected to have a root view controller at the end of application launch 2013-04-23 12:37:32.533 AMM[2231:c07] * -[MainScreenViewController respondsToSelector:]: message sent to deallocated instance 0x71edb70
In the application delegate file have you added the mainview controller to window's rootviewcontroller? Also could you try with some hardcoded text instead of assigning name to cell text.
Here,
Check this is happening in App Delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[MainScreenViewController alloc] initWithNibName:#"MainScreenViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
and in MainScreenViewController.m
#interface MainScreenViewController () <UITableViewDataSource,UITableViewDelegate>
#property (nonatomic, strong)UITableView * table;
#property (nonatomic, strong)NSString * name;
#end
#implementation MainScreenViewController
#synthesize table,name;
- (void)viewDidLoad
{
[super viewDidLoad];
name = [[NSString alloc]init];
name = #"testing of row";
CGRect frame = self.view.frame;
table = [[UITableView alloc] initWithFrame:frame];
table.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
[table setDelegate:self];
[table setDataSource:self];
[self.view addSubview:table];
// Do any additional setup after loading the view, typically from a nib.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 8;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return #"Test";
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath*)indexPath;
{
return 190;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
// cell.textLabel.text = name;
// Add UIScrollView for Horizontal scrolling.
NSArray * colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor],[UIColor blueColor],[UIColor orangeColor], [UIColor blackColor],[UIColor purpleColor], nil];
UIScrollView * scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0.0,0.0,320.0,190.0)];
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * colors.count,scrollView.frame.size.height);
for (int i = 0; i < colors.count; i++) {
CGRect frame;
frame.origin.x = scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = scrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
subview.backgroundColor = [colors objectAtIndex:i];
[scrollView addSubview:subview];
}
[cell.contentView addSubview:scrollView];
return cell;
}
I have a custom cell designed with a scrollview and a pageview control, which I am displaying as follows
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString * CellIdentifier = #"ScrollViewCell";
cell = (ScrollViewCell*)[newsTable dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray * customcellArray = [[NSBundle mainBundle]loadNibNamed:#"ScrollViewCell" owner:self options:nil];
for(id customcellObject in customcellArray){
if([customcellObject isKindOfClass: [UITableViewCell class]]){
cell = (ScrollViewCell *)customcellObject;
break;
}
}
}
// Customize your UIScrollView here..
[cell.scrollView setDelegate:self];
[cell.scrollView setPagingEnabled:YES];
scrollView = cell.scrollView;
pageControl = cell.pageControl;
cell.backgroundColor = [UIColor grayColor];
NSArray *colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor],[UIColor blueColor], nil];
cell.scrollView.contentSize = CGSizeMake(cell.scrollView.frame.size.width * colors.count,cell.scrollView.frame.size.height);
for (int i = 0; i < colors.count; i++) {
CGRect frame;
frame.origin.x = cell.scrollView.frame.size.width * i;
frame.origin.y = 0;
frame.size = cell.scrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
subview.backgroundColor = [colors objectAtIndex:i];
[cell.scrollView addSubview:subview];
}
// Configure the cell...
UIView* bgview = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
bgview.opaque = YES;
bgview.backgroundColor = [UIColor grayColor];
[cell setBackgroundView:bgview];
return cell;
}
The scrollview appears and scrolls just fine in cell , but problem is page control doesnt update with the scroll, basically I want to update the page control on scroll of scrollview but since page control and scrollview both are from cell I am not getting how to achieve this, I tried implementing UIScrollViewDelegate protocol with cell and then the parent view of table view but couldnt get it working, pleas guide.
Thanks
Vishal
Don't place your UIPageControll over UIScrollview in your custom cell, if it is then it will get scroll along UIScrollView itself.So create your Custom cell like this and make outlet for each UIScrollview & UIPageControll,
One change in your cellForRowAtIndexPath
// Customize your UIScrollView here..
[cell.scrollView setDelegate:self];
[cell.scrollView setPagingEnabled:YES];
[cell.scrollView setTag:indexPath.row]; // set indexpath.row as tag for cell.scrollview
NSArray * colors = [NSArray arrayWithObjects:[UIColor redColor], [UIColor greenColor],[UIColor blueColor],nil];
cell.pageControll.numberOfPages = [colors count];
And in,
- (void)scrollViewDidScroll:(UIScrollView *)sender {
CGFloat xOffset = sender.contentOffset.x;
CGFloat frameWidth = sender.frame.size.width;
int page = floor((xOffset - frameWidth / 2) / frameWidth) + 1;
GroupButtonCell * cell = (GroupButtonCell*)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:sender.tag inSection:0]]; // get appropriate cell based on scrollview tag (sender.tag).
cell.pageControll.currentPage = page; // assigning to pagecontroll
}
Hope this will help..
After a some time, searching here for some solutions we found this post:
How to navigate through textfields (Next / Done Buttons)
We tried that but unfortunately it doesn't work at all. Note that we put the UITextFields inside a UITableView.
We think the problem is around the Delegates but we don't know how to deal with it. Following i show you our code:
.h:
#import <UIKit/UIKit.h>
#interface LoginViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate> {
UITableView *loginTableView;
UITextField *textField;
}
#property UITableView *loginTableView;
#property UITextField *textField;
#property UIButton *loginButton;
#property UIButton *cancelButton;
#end
.m:
#import <QuartzCore/QuartzCore.h>
#import "LoginViewController.h"
#import "RootViewController.h"
#interface LoginViewController ()
#end
#implementation LoginViewController
#synthesize loginTableView, textField, loginButton, cancelButton;
- (void)viewDidLoad {
[super viewDidLoad];
// Make rounded corners view
[self.view.layer setCornerRadius:4.0];
[self.view.layer setMasksToBounds:YES];
self.view.layer.opaque = NO;
self.view.backgroundColor = [UIColor whiteColor];
// Create background image view
UIImageView *loginBackgroundImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height+20)];
// Create background's image
UIImage *backgroundImage = [UIImage imageNamed:#"loginbackground.png"];
loginBackgroundImageView.image = backgroundImage;
[self.view addSubview:loginBackgroundImageView];
// Create logo's image
UIImage *logoImage = [UIImage imageNamed:#"logo.png"];
// Create logo's image view
UIImageView *logoImageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.view.bounds.size.width/2 - logoImage.size.width/2, self.view.bounds.size.height/9, logoImage.size.width, logoImage.size.height)];
// Set image to logo's image view
logoImageView.image = logoImage;
[self.view addSubview:logoImageView];
// Create login table view
loginTableView = [[UITableView alloc] initWithFrame:CGRectMake(self.view.bounds.size.width/2 - (self.view.bounds.size.width/1.2)/2, self.view.bounds.size.height/3, self.view.bounds.size.width/1.25, 100) style:UITableViewStylePlain
];
loginTableView.delegate = self;
loginTableView.dataSource = self;
// Create login container table view
UIImage *containerImage = [UIImage imageNamed:#"loginform.png"];
UIImageView *containerImageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.view.bounds.size.width/2 - containerImage.size.width/2, self.view.bounds.size.height/3, containerImage.size.width, containerImage.size.height)];
containerImageView.image = containerImage;
[self.view addSubview:containerImageView];
// Custom table view
loginTableView.backgroundColor = [UIColor clearColor];
loginTableView.separatorColor = [UIColor clearColor];
// Disable scroll
loginTableView.scrollEnabled = NO;
// Add login table view to main view
[self.view addSubview:loginTableView];
// Create buttons images
UIImage *loginImage = [UIImage imageNamed:#"loginbtn2.png"];
UIImage *cancelImage = [UIImage imageNamed:#"cancelbtn.png"];
// Create buttons
loginButton = [UIButton buttonWithType:UIButtonTypeCustom];
cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
// Set buttons' normal state image
[loginButton setImage:loginImage forState:UIControlStateNormal];
[cancelButton setImage:cancelImage forState:UIControlStateNormal];
// Place buttons
loginButton.frame= CGRectMake((self.view.bounds.size.width/2)-(loginImage.size.width/2), self.view.bounds.size.height/1.65, loginImage.size.width, loginImage.size.height);
cancelButton.frame= CGRectMake((self.view.bounds.size.width/2)-(cancelImage.size.width/2), self.view.bounds.size.height/1.375, cancelImage.size.width, cancelImage.size.height);
// Set buttons' action
[loginButton addTarget:self action:#selector(loginButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[cancelButton addTarget:self action:#selector(cancelButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
// Set button to the main view
[self.view addSubview:loginButton];
[self.view addSubview:cancelButton];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if ([indexPath section] == 0) {
textField = [[UITextField alloc] initWithFrame:CGRectMake(50, 11, 200, 25)];
textField.adjustsFontSizeToFitWidth = NO;
textField.textColor = [UIColor darkGrayColor];
textField.backgroundColor = [UIColor clearColor];
if ([indexPath row] == 0) {
textField.placeholder = #"Username";
textField.keyboardType = UIKeyboardTypeEmailAddress;
textField.returnKeyType = UIReturnKeyNext;
textField.autocorrectionType = UITextAutocorrectionTypeNo;
textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
textField.tag = 0;
}
else {
textField.placeholder = #"Password";
textField.keyboardType = UIKeyboardTypeEmailAddress;
textField.returnKeyType = UIReturnKeyDone;
textField.autocorrectionType = UITextAutocorrectionTypeNo;
textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
textField.secureTextEntry = YES;
textField.tag = 1;
}
textField.clearButtonMode = UITextFieldViewModeAlways;
textField.delegate = self;
[textField setEnabled: YES];
[cell addSubview:textField];
}
}
if ([indexPath section] == 0) { // Email & Password Section
if ([indexPath row] == 0) { // Email
cell.imageView.image = [UIImage imageNamed:#"usernameico.png"];
}
else {
cell.imageView.image = [UIImage imageNamed:#"passwordico.png"];
}
}
else { // Login button section
cell.textLabel.text = #"Log in";
}
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *) tableView {
return 1;
}
-(BOOL)textFieldShouldReturn:(UITextField*) formTextField {
NSInteger nextTag = formTextField.tag + 1;
// Try to find next responder
UIResponder* nextResponder = [textField.superview viewWithTag:nextTag];
if (nextResponder) {
// Found next responder, so set it.
[nextResponder becomeFirstResponder];
} else {
// Not found, so remove keyboard.
[formTextField resignFirstResponder];
}
return NO; // We do not want UITextField to insert line-breaks.
}
- (void)loginButtonPressed: (UIButton *) sender {
}
- (void)cancelButtonPressed: (UIButton *) sender {
}
#end
Thank you in advance!
The problem is the table. When you ask you text view for it's superview, it will return the cell, which doesn't contain any other siblings. Try:
UIResponder* nextResponder = [tableView viewWithTag:nextTag];
Creare an array with your UITextField inside the cellForRowAtIndexPath: method..
[txtArray addObject:textField];
and then this bellow method it will work...
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
int i=[txtArray count];
int x=textField.tag+1;
UITextField *nextTextField = (UITextField *)[txtArray objectAtIndex:x];
if (x<i-1) {
[nextTextField becomeFirstResponder];
} else {
[textField resignFirstResponder];
}
return YES;
}
i hope this help you...
Give tag to your textField one by one and use textField delegate
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
int NextTextField = textField.tag+1;
UITextField *txt = (UITextField *) [tableView viewWithTag:NextTextField];
[txt becomeFirstResponder];
return NO;
}
I want to display two lots of text in two different footers in my table.
The text for section 3 uses titleForFooterInSection :
- (NSString *)tableView:(UITableView *)tv titleForFooterInSection:(NSInteger)section
{
if (section == 3)
return #"SOME TEXT FOR SECTION 3";
else
return #"";
}
and works great and is styled correctly.
I also want to add some more complicatedly formatted text (just left aligned really), so I create a label and add it to viewForFooterInSection, which works but is not padded (doesn't start at x = 20 & y = 20, starts hard up against the main windows edge) and is not styled like the other text.
- (UIView *)tableView:(UITableView *)tv viewForFooterInSection:(NSInteger)section
{
if (section == 1)
{
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(20, 20, 100, 50)] autorelease];
label.text = #"SOME COMPLICATED TEXT FOR SECTION 1\r\n"
"\r\n"
"MORE TEXT HERE\r\n"
"AND HERE.\r\n"
label.backgroundColor = [UIColor clearColor];
label.font = [UIFont systemFontOfSize:14];
label.shadowColor = [UIColor colorWithWhite:0.8 alpha:0.8];
label.textColor = [UIColor blueColor];
label.lineBreakMode = UILineBreakModeWordWrap;
label.textAlignment = UITextAlignmentLeft;
label.numberOfLines = 0;
[label sizeToFit];
return label;
}
else
return nil;
}
-(CGFloat)tableView:(UITableView *)tv heightForFooterInSection:(NSInteger)section
{
if (section == 1)
return 180.0f;
else if (section == 3)
return 50.0f;
else
return 0.0f;
}
To get the padding add the label into another view before returning that as the footer view;
- (UIView *)tableView:(UITableView *)tv viewForFooterInSection:(NSInteger)section
{
...
CGRect footerFrame = [tv rectForFooterInSection:1];
CGRect labelFrame = CGRectMake(20, 20, footerFrame.size.width - 40, footerFrame.size.height - 40);
UIView *footer = [[UIView alloc] initWithFrame:footerFrame];
UILabel *footerLabel = [[UILabel alloc] initWithFrame:labelFrame];
[footer addSubview:footerLabel];
[footerLabel release];
...
return footer;
}
NB: You might want to scope *footer better to avoid a memory leak or use autorelease.
I'm not sure what the system defaults are for the label it creates to hold the text you supply as the title for footer. I guess you'll need to experiment when creating the footer label as Google hasn't thrown anything useful up.
EDIT: Rather than put all the code in the viewForFooterInSection method I use a custom UIView;
#interface CustomHeaderView : UIView {
NSString *headerTitle;
}
#property (nonatomic, retain) NSString *headerTitle;
#end
#implementation CustomHeaderView
#synthesize headerTitle;
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
// create frame with padding
CGRect labelFrame = CGRectMake(8, 8, frame.size.width - 16, frame.size.height - 16);
UILabel *headerText = [[UILabel alloc] initWithFrame:labelFrame];
[headerText setNumberOfLines:0];
[headerText setFont:[UIFont boldSystemFontOfSize:14.0]];
[self addSubview:headerText];
[headerText release];
}
return self;
}
- (void)setHeaderTitle:(NSString *)title {
[title retain];
[headerTitle release];
UILabel *label = [[self subviews] objectAtIndex:0];
[label setText:title];
[label sizeToFit];
CGRect viewFrame = [self frame];
CGRect labelFrame = [label frame];
viewFrame.size.height = labelFrame.size.height + 16;
[self setFrame:viewFrame];
[self setNeedsLayout];
headerTitle = title;
}
- (void)dealloc {
[headerTitle release];
[super dealloc];
}
#end
This allows me to set my title text and have the header resize for the content. I lazy load this in my view controller;
#interface MyViewController
{
UIView *headerView;
}
- (UIView *) headerView;
#end
#implementation MyViewController
- (UIView *) headerView {
if(headerView)
return headerView;
float w = [[self view] bounds].size.width;
// height irrelevant as long as non zero custom view will resize
CGRect headerFrame = CGRectMake(0, 0, w, 32);
headerView = [[CustomHeaderView alloc] initWithFrame:headerFrame];
return headerView;
}
- (UIView *) tableView:(UITableView *)tv viewForHeaderInSection:(NSInteger)sec {
return [self headerView];
}
- (void) viewWillAppear:(BOOL)animated {
[(CustomHeaderView *)[self headerView] setHeaderTitle:#"My Custom Header"]];
}
#end
Make sure u return proper height in - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section; delegate method.
I am using the 'swipe to delete' functionality of the UITableView.
The problem is I am using a customised UITableViewCell which is created on a per item basis in
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
I need to alter the position of the delete button (simply to move it around 10px to the left), how would I go about doing this?
Here is my existing code for creating the cell:
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"cellForRowAtIndexPath");
#if USE_CUSTOM_DRAWING
const NSInteger TOP_LABEL_TAG = 1001;
const NSInteger BOTTOM_LABEL_TAG = 1002;
UILabel *topLabel;
UILabel *bottomLabel;
#endif
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
//
// Create the cell.
//
cell =
[[[UITableViewCell alloc]
initWithFrame:CGRectZero
reuseIdentifier:CellIdentifier]
autorelease];
#if USE_CUSTOM_DRAWING
const CGFloat LABEL_HEIGHT = 20;
UIImage *image = [UIImage imageNamed:#"trans_clock.png"];
//
// Create the label for the top row of text
//
topLabel =
[[[UILabel alloc]
initWithFrame:
CGRectMake(
image.size.width + 2.0 * cell.indentationWidth,
0.5 * (aTableView.rowHeight - 2 * LABEL_HEIGHT),
aTableView.bounds.size.width -
image.size.width - 4.0 * cell.indentationWidth
,
LABEL_HEIGHT)]
autorelease];
[cell.contentView addSubview:topLabel];
//
// Configure the properties for the text that are the same on every row
//
topLabel.tag = TOP_LABEL_TAG;
topLabel.backgroundColor = [UIColor clearColor];
topLabel.textColor = fontColor;
topLabel.highlightedTextColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.9 alpha:1.0];
topLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize]];
//
// Create the label for the top row of text
//
bottomLabel =
[[[UILabel alloc]
initWithFrame:
CGRectMake(
image.size.width + 2.0 * cell.indentationWidth,
0.5 * (aTableView.rowHeight - 2 * LABEL_HEIGHT) + LABEL_HEIGHT,
aTableView.bounds.size.width -
image.size.width - 4.0 * cell.indentationWidth
,
LABEL_HEIGHT)]
autorelease];
[cell.contentView addSubview:bottomLabel];
//
// Configure the properties for the text that are the same on every row
//
bottomLabel.tag = BOTTOM_LABEL_TAG;
bottomLabel.backgroundColor = [UIColor clearColor];
bottomLabel.textColor = fontColor;
bottomLabel.highlightedTextColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.9 alpha:1.0];
bottomLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize] - 2];
//
// Create a background image view.
//
cell.backgroundView =
[[[UIImageView alloc] init] autorelease];
cell.selectedBackgroundView =
[[[UIImageView alloc] init] autorelease];
#endif
}
#if USE_CUSTOM_DRAWING
else
{
topLabel = (UILabel *)[cell viewWithTag:TOP_LABEL_TAG];
bottomLabel = (UILabel *)[cell viewWithTag:BOTTOM_LABEL_TAG];
}
topLabel.text = #"Example Text";
topLabel.textColor = fontColor;
bottomLabel.text = #"More Example Text";
bottomLabel.textColor = fontColor;
//
// Set the background and selected background images for the text.
// Since we will round the corners at the top and bottom of sections, we
// need to conditionally choose the images based on the row index and the
// number of rows in the section.
//
UIImage *rowBackground;
UIImage *selectionBackground;
NSInteger sectionRows = [aTableView numberOfRowsInSection:[indexPath section]];
NSInteger row = [indexPath row];
if (row == 0 && row == sectionRows - 1)
{
rowBackground = [UIImage imageNamed:#"topAndBottomRow.png"];
selectionBackground = [UIImage imageNamed:#"topAndBottomRowSelected.png"];
}
else if (row == 0)
{
rowBackground = [UIImage imageNamed:#"topRow.png"];
selectionBackground = [UIImage imageNamed:#"topRowSelected.png"];
}
else if (row == sectionRows - 1)
{
rowBackground = [UIImage imageNamed:#"bottomRow.png"];
selectionBackground = [UIImage imageNamed:#"bottomRowSelected.png"];
}
else
{
rowBackground = [UIImage imageNamed:#"middleRow.png"];
selectionBackground = [UIImage imageNamed:#"middleRowSelected.png"];
}
((UIImageView *)cell.backgroundView).image = rowBackground;
((UIImageView *)cell.selectedBackgroundView).image = selectionBackground;
cell.imageView.image = [UIImage imageNamed:#"Example_Image.png"];
#else
cell.text = #"Example";
#endif
return cell;
}
For me the best way to solve this was overriding -(void)layoutSubviews in MyCell:UITableViewCell
Here you can see not only the Delete button custom position, but also repositioning the Edit and Reorder controls for Edit mode
- (void)layoutSubviews
{
[super layoutSubviews];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.0f];
for (UIView *subview in self.subviews) {
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"]) {
CGRect newFrame = subview.frame;
newFrame.origin.x = 200;
subview.frame = newFrame;
}
else if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellEditControl"]) {
CGRect newFrame = subview.frame;
newFrame.origin.x = 100;
subview.frame = newFrame;
}
else if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellReorderControl"]) {
CGRect newFrame = subview.frame;
newFrame.origin.x = 200;
subview.frame = newFrame;
}
}
[UIView commitAnimations];
}
Iwat's code doesn't work for me. But this works.
- (void)willTransitionToState:(UITableViewCellStateMask)state {
[super willTransitionToState:state];
if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableViewCellStateShowingDeleteConfirmationMask) {
for (UIView *subview in self.subviews) {
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"]) {
subview.hidden = YES;
subview.alpha = 0.0;
}
}
}
}
- (void)didTransitionToState:(UITableViewCellStateMask)state {
[super didTransitionToState:state];
if (state == UITableViewCellStateShowingDeleteConfirmationMask || state == UITableViewCellStateDefaultMask) {
for (UIView *subview in self.subviews) {
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"]) {
UIView *deleteButtonView = (UIView *)[subview.subviews objectAtIndex:0];
CGRect f = deleteButtonView.frame;
f.origin.x -= 20;
deleteButtonView.frame = f;
subview.hidden = NO;
[UIView beginAnimations:#"anim" context:nil];
subview.alpha = 1.0;
[UIView commitAnimations];
}
}
}
}
I haven't been able to change the actual look of the delete button, but you can change the text. Perhaps you can use this to get the effect you are looking for?
Check out the following member of the UITableViewDelegate protocol:
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
Additionally, you can detect when the delete button is being displayed by subclassing UITableViewCell and overriding the the following:
- (void)willTransitionToState:(UITableViewCellStateMask)state
- (void)didTransitionToState:(UITableViewCellStateMask)state
For either of these, the state mask will be UITableViewCellStateShowingDeleteConfirmationMask when the delete button is being displayed.
Hopefully these clues will point you in the right direction.
I use a solution that on first sight looks kind of hacky but does the trick and is not relying on undocumented apis:
/**
* Transition to state
*/
-(void)willTransitionToState:(UITableViewCellStateMask)state {
if(state & UITableViewCellStateShowingDeleteConfirmationMask)
_deleting = YES;
else if(!(state & UITableViewCellStateShowingDeleteConfirmationMask))
_deleting = NO;
[super willTransitionToState:state];
}
/**
* Reset cell transformations
*/
-(void)resetCellTransform {
self.transform = CGAffineTransformIdentity;
_background.transform = CGAffineTransformIdentity;
_content.transform = CGAffineTransformIdentity;
}
/**
* Move cell around if we are currently in delete mode
*/
-(void)updateWithCurrentState {
if(_deleting) {
float x = -20;
float y = 0;
self.transform = CGAffineTransformMakeTranslation(x, y);
_background.transform = CGAffineTransformMakeTranslation(-x, -y);
_content.transform = CGAffineTransformMakeTranslation(-x, -y);
}
}
-(void)setFrame:(CGRect)frame {
[self resetCellTransform];
[super setFrame:frame];
[self updateWithCurrentState];
}
-(void)layoutSubviews {
[self resetCellTransform];
[super layoutSubviews];
[self updateWithCurrentState];
}
Basically this shifts the cell position and readjusts the visible portions.
WillTransitionToState just sets an instance variable indicating whether the cell is in delete mode. Overriding setFrame was necessary to support rotating the phone to landscape and vice-versa.
Where _background is the background view of my cell and _content is a view added to the contentView of the cell, holding all labels etc.
I don't know of any way to "move the delete button 10px to the left". However, you can animate the custom contents of your table cell around the static position of the unmovable delete button by listening for the willTransitionToState: message from a UITableViewCell sub-class see here.
To quote the docs:
Subclasses of UITableViewCell can
implement this method to animate
additional changes to a cell when it
is changing state. UITableViewCell
calls this method whenever a cell
transitions between states, such as
from a normal state (the default) to
editing mode. The custom cell can set
up and position any new views that
appear with the new state. The cell
then receives a layoutSubviews message
(UIView) in which it can position
these new views in their final
locations for the new state.
Subclasses must always call super when
overriding this method.
What you are looking for is the UITableViewCellStateShowingDeleteConfirmationMask value. This is one of those times where creating UITableViewCell subclass might be better, so from the controller you are just creating an instance of your custom cell. Then the cell can just adjust itself like animateLeft and animateRight and handle the inner workings of adjusting its own subviews.
I don't know the final solution, but as far as I tried the following code might be useful.
// subclass UITableViewCell
- (void)willTransitionToState:(UITableViewCellStateMask)state
{
[super willTransitionToState:state];
if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableCellStateShowingDeleteConfirmationMask)
{
for (UIView *subview in self.subviews)
{
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"])
{
subview.hidden = YES;
subview.alpha = 0;
}
}
}
}
- (void)didTransitionToState:(UITableViewCellStateMask)state
{
[super willTransitionToState:state];
if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableCellStateShowingDeleteConfirmationMask)
{
for (UIView *subview in self.subviews)
{
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"])
{
subview.frame = CGRectMake(subview.frame.origin.x - 10, subview.frame.origin.y, subview.frame.size.width, subview.frame.size.height);
subview.hidden = NO;
[UIView beginAnimations:#"anim" context:nil];
subview.alpha = 1;
[UIView commitAnimations];
}
}
}
}