Scroll Group tableView when keyboard appears - iphone

I'm trying to create a view, where user enter his info (name, email, bio...).
To do this I'm using a group table view with 5 section (0..4), each has one cell that has a UITextField inside (except the cell in section 4 that has a UITextView inside).
When user tap on one of those textFields/textView the keyboard appears, and the cell (with the selected textField/textView) scroll to the position just above the keyboard.
My problem is with the textView at section 4, when keyboard appears it somehow automatically scroll the cell to be visible, but not exactly in the right position (half of the text view is hidden behind the keyboard).
When I try to do the scroll myself (after keyboard finish animating) I get an ugly bounce of the textView.
It seams that the cause for the ugly bounce is that the textView automatic scrolls when the keyboard appear + my scrolling. This behavior (of automatic scrolling) happens only for the textView, for example if I use a textField instead of the textView in section 4, it doesn't automatically scroll.
So the question is: how can I smoothly scroll the textView to the right position?
This is my code:
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 5;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
switch (indexPath.section) {
case 0:
[cell.contentView addSubview:self.textField1];
break;
case 1:
[cell.contentView addSubview:self.textField2];
break;
case 2:
[cell.contentView addSubview:self.textField3];
break;
case 3:
[cell.contentView addSubview:self.textField4];
break;
case 4:
// this is the text view
[cell.contentView addSubview:self.textView];
break;
default:
break;
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
#pragma mark - UITextFieldDelegate
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
self.activeResponder = textField;
return YES;
}
#pragma mark - UITextViewDelegate
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
self.activeResponder = textView;
return YES;
}
- (void)keyboardWillShow:(NSNotification*)notification {
NSLog(#"keyboard show");
CGFloat animationDuration = [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect tableViewFrame = self.tableView.frame;
tableViewFrame.size.height -= keyboardFrame.size.height;
[UIView animateWithDuration:animationDuration delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.tableView.frame = tableViewFrame;
} completion:^(BOOL finished) {
[self scrollToActiveResponder];
}];
}
- (void)keyboardWillHide:(NSNotification*)notification {
NSLog(#"keyboard hide");
CGFloat animationDuration = [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect tableViewFrame = self.tableView.frame;
tableViewFrame.size.height += keyboardFrame.size.height;
[UIView animateWithDuration:animationDuration delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.tableView.frame = tableViewFrame;
} completion:^(BOOL finished) {
}];
}
- (NSIndexPath *)indexPathForActiveResponder {
NSIndexPath *indexPath = nil;
if (self.activeResponder == self.textField1) {
indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
}
else if (self.activeResponder == self.textField2) {
indexPath = [NSIndexPath indexPathForRow:0 inSection:1];
}
else if (self.activeResponder == self.textField3) {
indexPath = [NSIndexPath indexPathForRow:0 inSection:2];
}
else if (self.activeResponder == self.textField4) {
indexPath = [NSIndexPath indexPathForRow:0 inSection:3];
}
else if (self.activeResponder == self.textView) {
indexPath = [NSIndexPath indexPathForRow:0 inSection:4];
}
return indexPath;
}
- (void)scrollToActiveResponder {
NSIndexPath *activeResponderIndexPath = [self indexPathForActiveResponder];
if (activeResponderIndexPath) {
[self.tableView scrollToRowAtIndexPath:activeResponderIndexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
}
}

I would try something like this:
.h
#interface YourViewController : UIViewController <UITextViewDelegate>
.m
//Set delegate to your textView
textView.delegate = self
#pragma mark - TextView Delegate
//TextView Became First Responder
- (void)textViewDidBeginEditing:(UITextView *)textView{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:4];
// Other way to get the IndexPath
//NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[[textView superview] superview]];
CGRect frame = [self.tableView rectForRowAtIndexPath:indexPath];
//It only works for Portrait iPhone
CGFloat keyboardHeight = 216.0f;
CGPoint offset = CGPointMake(0, self.view.frame.size.height - keyboardHeight - frame.size.height - frame.origin.y);
[self.tableView setContentOffset:offset animated:YES];
}
I didn't test it, but it's how I would try to approach this problem. You can find more information about how calculate keyboard size here: (http://www.idev101.com/code/User_Interface/keyboard.html)

Related

Merging UITableViewCells

I would like to be able to drag a cell over another cell, and when I release it would effectively "merge" the cells (display a different cell). I'm not sure if a UITableView is the best control or a UICollectionView. Does anyone have any thoughts on how to proceed?
May be I didn't get u properly but as I got, u want to merge cells by dragging so implement some code for you.Have a look at this.
If u Wanna something like this...
use editing code like that :---
ViewDidLoad initializing array and set table to edit mode as:
fruitsArray=[[NSMutableArray alloc] initWithObjects:#"Apple",#"Banana",#"Mango",#"Guava",#"PineApple",#"Watermelon",#"Grapes",#"GroundNut",#"Muskmelon",#"Orange",#"Cherry",nil];
[tblView setEditing:YES];
datasources for tableView set as:->
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewCellEditingStyleNone;
}
- (BOOL)tableView:(UITableView *)tableview shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
if (sourceIndexPath.row!=destinationIndexPath.row) {
NSString *sourceString=[fruitsArray objectAtIndex:sourceIndexPath.row];
NSString *destinationString=[fruitsArray objectAtIndex:destinationIndexPath.row];
destinationString=[destinationString stringByAppendingFormat:#",%#",sourceString];
[fruitsArray replaceObjectAtIndex:destinationIndexPath.row withObject:destinationString];
[fruitsArray removeObjectAtIndex:sourceIndexPath.row];
[tblView reloadData];
}
}
Try this sampleCode
Here's the solution I used to develop it in pseudocode.
Add a UILongPressGestureRecognizer to the UITableView
On the UIGestureRecognizerStateBegan, use the [UITableView indexPathForRowAtPoint] in order to determine what cell is being "long pressed". You will turn this cell into the hover UITableViewCell.
Set a reference variable to the corresponding model object.
Use the UIGraphicsBeginImageContextWithOptions to render an image of the actual UITableViewCell contents. Create a UIImageView and add some custom chrome to it (shadows, etc.)
Add the custom UIImageView as a subview to the UITableView, and remove the original selected pinned UITableViewCell (removeFromSuperview).
On UIGestureRecognizerStateChanged, calculate the location of the hover UITableViewCell in the UITableView and animate the pinned cell. (You will also want to toggle the animation for the previously highlighted pinned cell).
When the user releases the LongPress, you'll want to re-order the model array, remove the underlying pinned cell, and then reload the UITableView all in a beginUpdates call.
There are a few other things to watch out for such as scrolling when you hit a boundary condition, dropping the hover cell over the original location, etc. but that's the basic gist of it. Hopefully that helps.
I used Long press gesture for this. here is sample code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:cell action:nil];
longPress.delegate = self;
[cell addGestureRecognizer:longPress];
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
if([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]){
[gestureRecognizer addTarget:self action:#selector(moveRight:)];
}
return YES;
if([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]){
[gestureRecognizer addTarget:self action:#selector(tapAction:)];
}
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
- (void)moveRight:(UILongPressGestureRecognizer *)sender {
/*if (sender.view.tag==4)
{
[super setEditing:YES animated:YES];
[self.Table4 setEditing:YES animated:YES];
}
else
{
*/
UIView *view = sender.view;
int t = sender.view.tag;
CGPoint point = [sender locationInView:view.superview];
NSLog(#"its added %f", point.x);
NSLog(#"its added %f", point.y);
// view.frame = CGRectMake(sender.view.frame.origin.x, sender.view.frame.origin.y+200,200, 30);
CGPoint center = view.center;
center.x = point.x ;
center.y = point.y ;
view.center = center;
[self.view addSubview:view];
// int x = Table4.frame.origin.x;
// int y = Table4.frame.origin.y;
if (sender.state == UIGestureRecognizerStateChanged) {
CGPoint center = view.center;
center.x += point.x - _priorPoint.x;
center.y += point.y - _priorPoint.y;
NSLog(#"its Center %f", center.x);
if (center.x > Table4.frame.origin.x &&
center.x < Table4.frame.origin.x +
Table4.frame.size.width &&
center.y > Table4.frame.origin.y &&
center.y < Table4.frame.origin.y +
Table4.frame.size.height
)
{
int count = [self.rowdata count];
if (t>=100 && t<200)
{
t=t-100;
[self.rowdata insertObject:[listData objectAtIndex:t] atIndex:count];
}
else if (t>=200 && t<300)
{
t=t-200;
[self.rowdata insertObject:[listData2 objectAtIndex:t] atIndex:count];
}
else
{
t=t-300;
[self.rowdata insertObject:[listData3 objectAtIndex:t] atIndex:count];
}
//[self.rowdata addObject:[listData objectAtIndex:t]];
//[sender release];
[Table4 reloadData];
[Table1 reloadData];
[Table2 reloadData];
[Table3 reloadData];
}
view.center = center;
//}
_priorPoint = point;
}
}
I think this is helpful for you. Take some code what you want from this.

Expand And Collapse UITableview

Am using below code for uitableview expand and collapse.Its works fine.But,when i select any section its expand but not collapse the previously expanded section.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self tableView:tableView canCollapseSection:indexPath.section])
{
if (!indexPath.row)
{
// only first row toggles exapand/collapse
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSInteger section = indexPath.section;
BOOL currentlyExpanded = [expandedSections containsIndex:section];
NSInteger rows;
NSMutableArray *tmpArray = [NSMutableArray array];
if (currentlyExpanded)
{
rows = [self tableView:tableView numberOfRowsInSection:section];
NSLog(#"expanded");
[expandedSections removeIndex:section];
screenTypeReloadCheck = NO;
}
else
{
screenTypeReloadCheck =YES;
[expandedSections addIndex:section];
rows = [self tableView:tableView numberOfRowsInSection:section];
}
for (int i=1; i<rows; i++)
{
NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i
inSection:section];
[tmpArray addObject:tmpIndexPath];
}
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (currentlyExpanded)
{
[tableView deleteRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
UIImageView *imView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"UITableExpand"]];
cell.accessoryView = imView;
}
else
{
[tableView insertRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
UIImageView *imView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"UITableContract"]];
cell.accessoryView = imView;
}
}
}
}
Thanks
I've done same thing in my app.. Here is solution ..
in your .h
#import "sampleCustomCell.h"
#interface second : UIViewController <UITableViewDelegate,UITableViewDataSource>
{
NSMutableDictionary *selectedIndexes;
sampleCustomCell *samplCustom;
UITableView *tblTempData;
NSMutableArray *yourAry;
}
#property(nonatomic,retain) sampleCustomCell *samplCustom;
#property (nonatomic,retain) NSMutableArray *yourAry;
#property (nonatomic,retain) IBOutlet UITableView *tblTempData;
#end
in your .m
#synthesize samplCustom;
#synthesize tblTempData;
BOOL isSelected;
int kCellHieght=0;
- (void)viewDidLoad
{
[super viewDidLoad];
yourAry = [[NSMutableArray alloc] initWithObjects:#"1_id",#"2_id",#"3_id",#"4_id",#"5_id",#"6_id",#"7_id",#"8_id",#"9_id",#"10_id", nil];
selectedIndexes = [[NSMutableDictionary alloc] init];
}
#pragma mark TableView with Expand and collapse
- (BOOL)cellIsSelected:(NSIndexPath *)indexPath {
// Return whether the cell at the specified index path is selected or not
NSLog(#"%#", selectedIndexes);
NSNumber *selectedIndex = [selectedIndexes objectForKey:indexPath];
NSLog(#"%#", selectedIndex);
return selectedIndex == nil ? FALSE : [selectedIndex boolValue];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self cellIsSelected:indexPath])
{
kCellHieght = 200; //Expanded height for your customCell xib.
}
else
{
kCellHieght = 130; // Height of your customCell xib
}
return kCellHieght;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [yourAry count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
sampleCustomCell *cell;
if (tableView.tag == 11)
{
cell = (sampleCustomCell *)[tableView dequeueReusableCellWithIdentifier:#"sampleCustomCell"];
NSArray *nib;
for (UIControl *subview in cell.contentView.subviews) {
[subview removeFromSuperview];
}
if(cell == nil)
{
nib = [[NSBundle mainBundle] loadNibNamed:#"sampleCustomCell" owner:self options:nil];
for(id oneobject in nib)
{
if([oneobject isKindOfClass:[sampleCustomCell class]])
{
cell = (sampleCustomCell *)oneobject;
//[cell setIndexpath:indexPath];
//[cell setDelegete:self];
cell.lblProduct.text = [yourAry objectAtIndex:[indexPath row]];
}
}
}
if([self cellIsSelected:indexPath])
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:3];
[UIView commitAnimations];
[self performSelector:#selector(showHidden:) withObject:cell afterDelay:0.4];
}
}
return cell;
}
- (void)tableView:(UITableView *)aTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyleforRowAtIndexPath:(NSIndexPath *)indexPath
{
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
isSelected = ![self cellIsSelected:indexPath];
[tableView deselectRowAtIndexPath:indexPath animated:TRUE];
BOOL isSelected = ![self cellIsSelected:indexPath];
NSNumber *selectedIndex = [NSNumber numberWithBool:isSelected];
[selectedIndexes removeAllObjects];
[self hideTV:tableView];
[selectedIndexes setObject:selectedIndex forKey:indexPath];
NSLog(#" array %#", selectedIndexes);
[self.tblTempData beginUpdates];
sampleCustomCell *selectedCell = (sampleCustomCell *)[tblTempData cellForRowAtIndexPath:indexPath];
if([self cellIsSelected:indexPath])
{
samplCustom = selectedCell;
[UIView animateWithDuration:15 delay:0.2 options:UIViewAnimationCurveLinear animations:^{NSLog(#"animating");} completion:^(BOOL finished){
NSLog(#"Done 1!");
}];
[UIView commitAnimations];
}
else
{
[UIView animateWithDuration:5 delay:0.2 options:UIViewAnimationCurveLinear animations:^{NSLog(#"animating");} completion:^(BOOL finished){
NSLog(#"Done 1!");
}];
[UIView commitAnimations];
}
[self.tblTempData endUpdates];
[tblTempData reloadData];
}
-(void)hideTV:(UIView *) view{
[tblTempData reloadData];
for (id View in [view subviews]) {
if ([View isKindOfClass:[UITextView class]]) {
[View setHidden:YES];
}
if ([View isKindOfClass:[UITableViewCell class]]) {
UITableViewCell *cell = (UITableViewCell *) View;
[self hideTV:cell.contentView];
}
}
}
-(void) showHidden : (UITableViewCell *)cell{
for (id View in [cell subviews]) {
if ([View isKindOfClass:[UITextView class]]) {
if ([View tag] == 111) {
[View setHidden:NO];
}
}
}
}
Hopr this helps.. happy coding.. Thanks..
TableView section is not collapse but expand. Because, Your currentlyExpanded is always return NO. SO, you are always getting expand.
if (currentlyExpanded)
{
rows = [self tableView:tableView numberOfRowsInSection:section];
NSLog(#"expanded");
[expandedSections removeIndex:section];
screenTypeReloadCheck = NO;
}
else
{
screenTypeReloadCheck =YES;
[expandedSections addIndex:section];
rows = [self tableView:tableView numberOfRowsInSection:section];
}
I do not know how do you set currentlyExpanded value. If you need more help, please share few more lines of code.

How to zoom in/out only any one particular cell of a table view not the whole table?

I want to zoom in/out only any one particular row/cell of table view not the whole table.
I have used pinch gesture but its not working on table cell its working on whole table.
i need to zoom one cell at a time and when I want to zoom 2nd cell frist cell automitically resize then ?
Please help me out.
Thanks in advance.
You can try following code :
// For Zoom in
CGAffineTransform trans = CGAffineTransformScale(cell.contentView.transform, 100, 100);
view.transform = trans;
// For Zoom Out
CGAffineTransform trans = CGAffineTransformScale(cell.contentView.transform, 0.01, 0.01);
view.transform = trans;
You can use this on didSelectRowAtIndexPath method.
Under didSelectRowAtIndexPath: write in the following code to get the selected cell
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
Now you have got the cell
You can do it like that:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
[self itemSelected:indexPath];
}
- (void)itemSelected:(NSIndexPath *)indexPath {
[UIView animateWithDuration:0.3 animations:^{
[self animate:indexPath highlighted:YES];
} completion:^(BOOL finished) {
[self animate:indexPath highlighted:NO];
}];
}
- (void)animate:(NSIndexPath *)indexPath highlighted:(BOOL)highlighted {
SoundEffectsCell *cell = (SoundEffectsCell *)[_collectionView cellForItemAtIndexPath:indexPath];
float scale = highlighted ? 0.9 : 1.0;
[UIView transitionWithView:_collectionView duration:0.1 options:UIViewAnimationOptionTransitionNone animations:^{
cell.transform = CGAffineTransformMakeScale(scale, scale);
} completion:nil];
}
Please replace CollectionViewCell with yours. I have implemented it with UICollectionView but it is the same also with UITableView.
take a variable
NSInteger selectedindex
Now put this thing in
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//whatever your code write here
if (selectedindex == indexPath.row) {
[self animateZoomforCell:cell];
}else
{
[self animateZoomforCellremove:cell];
}
return cell;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//whatever your code write here
selectedindex =indexPath.row;
[self.tableView reloadData];
}
You can use this method for zooming in/out cell
-(void)animateZoomforCell:(UITableViewCell*)zoomCell {
[UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseOut
animations:^{
zoomCell.transform = CGAffineTransformMakeScale(1.6,1.6);
}
completion:^(BOOL finished){
}];
}
-(void)animateZoomforCellremove:(UITableViewCell*)zoomCell {
[UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
zoomCell.transform = CGAffineTransformMakeScale(1.0,1.0);
}
completion:^(BOOL finished){
}];
}
Swift 5
Disclaimer: it will zoom the whole tableView content.
For zooming out repeat same with transformation scale value as 1.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! YourCellName
let zoomView = cell.contentView.transform.scaledBy(x: 2, y: 2)
view.transform = zoomView
}
}
Have you tried writing #Devang answered code inside
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
Hope this helps.

enable/disable edit mode in UITableViewCell

I have a custom UITableViewCell that has 1 textfield and a label on it. I would like to enable the textfield editing only when the tableview is in edit mode.
I'm using following methods to enable textfield edit mode and disable textfield edit mode. but this is not working. I'm not sure whether this is correct approach or not. If it's not the correct way, can you let me know how to disable enable textfield?
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSIndexPath *rowToSelect = indexPath;
EditingTableViewCell *detSelCell;
detSelCell = (EditingTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
detSelCell.textField.enabled = self.editing;
// Only allow selection if editing.
if (self.editing)
{
return indexPath;
}
else
{
return nil;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (!self.editing)
{
return;
}
EditingTableViewCell *detcell;
detcell = (EditingTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
detcell.selectionStyle = style;
detcell.textField.enabled = self.editing;
also I've the following lines:
self.tableView.allowsSelection = NO; // Keeps cells from being selectable while not editing. No more blue flash.
self.tableView.allowsSelectionDuringEditing = YES; // Allows cells to be selectable during edit mode.
Please help!
--- I found the answer:
I've removed the enable/disable code from following methods:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
and added the following in custom cell.m
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.1];
[UIView setAnimationDelegate:self];
[UIView setAnimationBeginsFromCurrentState:YES];
if(editing){
textField.enabled = YES;
}else{
textField.enabled = NO;
}
[UIView commitAnimations];
}
it's working now. i'm not sure whether this is correct approach or not but its working fine.
EDIT: my bad, didn't properly read the method signatures. What you're asking is quite hard to do, because all textfields are most likely subviews of the cell or it's contentView. What you need to do is disable the cell's selectionStyle, return nil for everything in willSelect... Then allow selection during editing.
Since I've been looking for the same for some time, here's the full code achieving it
TextFieldTableViewCell.h
#interface TextFieldTableViewCell : UITableViewCell <UITextFieldDelegate> {
UITextField *textField;
}
#property (nonatomic, strong) UITextField *textField;
// add delegate/protocol to inform of change
#end
TextFieldTableViewCell.m
#import "TextFieldTableViewCell.h"
#implementation TextFieldTableViewCell
#synthesize textField;
- (void)initializeTextField {
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.textField = [[UITextField alloc] initWithFrame:CGRectZero];
self.textField.autocorrectionType = UITextAutocorrectionTypeDefault;
self.textField.enabled = NO; // not editable unless the table is in edit mode
// do all the necessary textfield setup here, font/alignment and so on
[self addSubview:self.textField];
self.accessoryType = UITableViewCellAccessoryNone;
}
// from code
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if( (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
[self initializeTextField];
}
return self;
}
// from storyboard
- (id)initWithCoder:(NSCoder *)aDecoder {
if( (self = [super initWithCoder:aDecoder])) {
[self initializeTextField];
}
return self;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[self.textField resignFirstResponder];
return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
// Extra code to be added here to notify a delegate that text has changed since cell is holding the value temporarily
// .....
UITableView *tableView = (UITableView *)self.superview;
[tableView deselectRowAtIndexPath:[tableView indexPathForCell:self] animated:YES];
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect editFrame = CGRectInset(self.contentView.frame, 10, 10);
if (self.textLabel.text && [self.textLabel.text length] != 0) {
CGSize textSize = [self.textLabel sizeThatFits:CGSizeZero];
editFrame.origin.x += textSize.width + 10;
editFrame.size.width -= textSize.width + 10;
self.textField.textAlignment = UITextAlignmentRight;
} else {
self.textField.textAlignment = UITextAlignmentLeft;
}
self.textField.frame = editFrame;
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
self.textField.enabled = editing;
}
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
if (selected) {
[self.textField becomeFirstResponder];
}
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
if (selected) {
[self.textField becomeFirstResponder];
}
}
#end
And with the setup on the table view you have the expected behavior of having a string displayed in normal mode and editable when in edit mode
self.tableView.allowsSelection = NO;
self.tableView.allowsSelectionDuringEditing = YES;

UITableView Animations

I am attempting to create a animated cell when it is selected. Everything seems to be working really odd. If I send the ButtonView to the Self.contentView of the UITableView Cell it works like it is supposed to and adds the cell in desired row but I loose button functionality at index row. If I send the buttonview to just self "UITableViewCell" I have button index row but it adds the button view in about every 10 rows.
Now the animation itself looks great when it works right. The issue is I am using a method to toggle the path selected so I can grow the cell height to twice the size when selected and stay selected until another cell is selected.
Really I have no idea where to go from here I was hoping maybe someone could help me find my mistake or have delt with something similar.
Thanks I appreciate any insight!
- (BOOL)cellIsSelected:(NSIndexPath *)indexPath {
// Return whether the cell at the specified index path is selected or not
NSNumber *selectedIndex = [selectedIndexes objectForKey:indexPath];
return selectedIndex == nil ? FALSE : [selectedIndex boolValue];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
*)indexPath {
[sounds PlayButtonClick:nil];
// Deselect cell ..?
//[tableView deselectRowAtIndexPath:indexPath animated:TRUE];
// Toggle 'selected' state
BOOL isSelected = ![self cellIsSelected:indexPath];
// Store cell 'selected' state keyed on indexPath
NSNumber *selectedIndex = [NSNumber numberWithBool:isSelected];
[selectedIndexes setObject:selectedIndex forKey:indexPath];
// This is where magic happens...
[tableView beginUpdates];
[tableView endUpdates];
[sounds PlaySlide:nil];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath
*)indexPath {
// If our cell is selected, return double height
if([self cellIsSelected:indexPath]) {
return 70 *2;
}
return 70;
}
And from my CellClass
- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
if (self == [super initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:reuseIdentifier]) {
self.contentView.clipsToBounds = YES;
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
if (selected == YES) {
NSLog(#"is selected");
[self showButtonView:!selected];
[self applyDropShadow:!selected];
// TweettextLabel.hidden = YES;
// Tweettext.hidden = NO;
}
if (selected == NO){
[self removeButtonView:!selected];
[self removeDropShadow:!selected];
//TweettextLabel.hidden = NO;
//Tweettext.hidden = YES;
NSLog(#"is NOT selected");
}
}
-(void)showButtonView:(int)view{
CGRect viewFrame = [ButtonView frame];
viewFrame.origin.y = 0;
self.ButtonView.frame = viewFrame;
[self.contentView insertSubview:self.ButtonView belowSubview:self.cellView];
[self addSubview:self.contentView];
[UIView beginAnimations:#"animateView" context:nil];
[UIView setAnimationDuration:0.3];
CGRect viewFrame1 = [ButtonView frame];
viewFrame1.origin.y = 70;
ButtonView.frame = viewFrame1;
[UIView commitAnimations];
}
-(void)removeButtonView:(int)view{
[UIView beginAnimations:#"animateView" context:nil];
[UIView setAnimationDuration:0.3];
CGRect viewFrame1 = [self.ButtonView frame];
viewFrame1.origin.y = 0;
self.ButtonView.frame = viewFrame1;
[UIView commitAnimations];
// timer = [NSTimer scheduledTimerWithTimeInterval:0.4 target:self
selector:#selector(removeLastViewFromSuper) userInfo:Nil repeats:NO];
}
-(void)applyDropShadow:(int)shadow{
self.contentView.layer.shadowColor = [[UIColor blackColor] CGColor];
self.contentView.layer.shadowOffset = CGSizeMake(0.8f, -4.0f);
self.contentView.layer.shadowRadius = 5.0f;
self.contentView.layer.shadowOpacity = 1.0f;
}
-(void)removeDropShadow:(int)shadow{
self.contentView.layer.shadowColor = [[UIColor clearColor] CGColor];
self.contentView.layer.shadowOffset = CGSizeMake(0.0, 0.0);
self.contentView.layer.shadowRadius = 0.0;
self.contentView.layer.shadowOpacity = 0.0;
}
Add the buttonView to the cell's contentView when you create it. Show and hide it by setting the hidden or alpha property. Now the problem of not getting the button to work should go away.
Also, your dictionary with the selected indexes seems a bit overdone if you only have one cell that is selected. Just create a property "selected" of type NSIndexPath in the controller.
Finally, your selected cell repeating when you scroll is due to the re-queuing mechanism of UITableView. Make sure that you set the correct hidden property for the button in cellForRowAtIndexPath each time. This way, when a cell is recycled that has a non-hidden button, it will hide it if the index path is not the selected one.