Based on the page change of a paged UIScrollView, I'm calling scrollToRowAtIndexPath:atScrollPosition:animated to the table specifics for that page that's in display.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
CGFloat pageWidth = self.scrollView.frame.size.width;
int page = floor((self.scrollView.contentOffset.x - pageWidth/2)/pageWidth)+1;
self.pageControl.currentPage = page;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:page];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
However, the animation of the automatic scrolling is happening too slow. Is there a way to make this animation more snappy?
A fast solution might be:
[UIView animateWithDuration:aSmallValue animations:^{
[self.tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionTop
animated:NO];
}];
Related
How to update number of rows in
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
}
When it will expand increase number of rows.
`- (void) rotateButtonToExpanded:(UIButton*)aButton section:(int)aSection{
// Rotate the button with animation.
[UIView beginAnimations:ROTATE_TO_EXPAND context:nil];
[UIView setAnimationDuration:ANIMATION_DURATION];
aButton.transform = CGAffineTransformMakeRotation(M_PI*2.5);
[UIView commitAnimations];
// Save the state (expanded or collapsed) of button with index path as key.
BOOL isExpanded=![[mStateOfNodes objectAtIndex:aSection] isExpanded];
[[mStateOfNodes objectAtIndex:aSection] setIsExpanded:isExpanded];
NSArray*theDataOfChildCells=[[self.mNodes objectAtIndex:aSection] valueForKey:CHILD_NODES];
for (int i=0; i<theDataOfChildCells.count; i++) {
mNumberOfCells++;
[self beginUpdates];
NSIndexPath*theIndexPath=[NSIndexPath indexPathForRow:i inSection:aSection];
[self insertRowsAtIndexPaths:[NSArray arrayWithObject:theIndexPath] withRowAnimation:UITableViewRowAnimationMiddle];
[self endUpdates];
}
}`
used reload data methods,
[self.tableview reloadData];
Use Following code that use for add row in UITable with specific row and section
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowNO inSection:SectionNO];
[self.tblView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
rowNO=rowNO+1;
[self.tblView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
[self.tblView reloadData];
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)
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.
This may be a simple question for you experts but I can't figure out the correct solution.
In my app I created a a table view to list a no of items.
In the first row of the cell there a switch (ON/OFF).
So my client need to hide the bottom cells(other than zeroth cell) when switch is OFF and show all the cells when switch is ON.
I created the switch through code.
Can anyone please help me with how to do this?
Thanks in advance.
numberOfRows dataSource method - make it return 1 and reloadTableView
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
/// ....
self.switchView = [[[UISwitch alloc] initWithFrame:CGRectZero]autorelease];
cell.accessoryView = self.switchView;
[self.switchView setOn:NO animated:NO];
[self.switchView addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
//....
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if [self.switchView.on]
return 1;
else
{
// normal code return
}
}
- (void) switchChanged:(id)sender {
[self.tableView reloadData];
}
You could use insertRowsAtIndexPaths, this will not only add, but also do the animation of adding new row
first add target UIControlEventTouchUpInside into UISwitch.
[switch addTarget:self action:#selector(switchChange:) forControlEvents:UIControlEventValueChanged];
-(void) switchChange:(UISwitch*) sender{
isSwitchOn = sender.on; //edited
[myTable beginUpdates];
NSIndexPath *row1 = [NSIndexPath indexPathForRow:1 inSection:0];
NSIndexPath *row2 = [NSIndexPath indexPathForRow:2 inSection:0];
//you may add as many row as you want here.
[myTable insertRowsAtIndexPaths:[NSArray arrayWithObjects:row1,row2,nil] withRowAnimation:UITableViewRowAnimationMiddle];
[myTable endUpdates];
}
and make sure you will add how many rows you will insert in numberOfRowsInSection:
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (isSwitchOn) return 1;
else
return 3; //how many rows would have after switched on
}
You might want to check [myTable insertSections:withRowAnimation: to insert another section and do the same as above. but remember to state how many section you will add, in numberOfSectionsInTableView:
UPDATE :
implement deleteRowsAtIndexPaths: if switch off.
-(void) switchChange:(UISwitch*) sender{
isSwitchOn = sender.on;
if(isSwitchOn){
[myTable beginUpdates];
NSIndexPath *row1 = [NSIndexPath indexPathForRow:1 inSection:0];
NSIndexPath *row2 = [NSIndexPath indexPathForRow:2 inSection:0];
//you may add as many row as you want here.
[myTable insertRowsAtIndexPaths:[NSArray arrayWithObjects:row1,row2,nil] withRowAnimation:UITableViewRowAnimationMiddle];
[myTable endUpdates];
}
else{
[myTable beginUpdates];
NSIndexPath *row1 = [NSIndexPath indexPathForRow:1 inSection:0];
NSIndexPath *row2 = [NSIndexPath indexPathForRow:2 inSection:0];
//you may add as many row as you want here.
[myTable deleteRowsAtIndexPaths:[NSArray arrayWithObjects:row1,row2,nil] withRowAnimation:UITableViewRowAnimationFade];
[myTable endUpdates];
}
}
There's a UITableViewDataSource method called tableView:numberOfRows:inSections method.Just check for the state of the switch and return 1 if it's OFF or all the rows if it is ON. Just call the [tableView reloadData] method each time you switch ON and OFF. As simple as that.
I have a subclass of UITableViewController. I have code that can add/remove a UISearchBar to/from the tableHeaderView of my tableView. Here's the code I have to perform these tasks:
self.tableView.tableHeaderView = uiSearchBar; //Make the search bar appear
self.tableView.tableHeaderView = nil; //Make the search bar disappear
The problem is that I want the adding/removing of the UISearchBar to be animated; slide into view from the top when I add it then slide upwards and out of view when I remove it instead of just appearing and disappearing. Any suggestions?
Thanks.
I was finally able to figure this out. Turned out to be pretty simple. Instead of adding the UISearchBar to the table header, I insert it into the first cell of the table with animation UITableViewRowAnimationTop and remove it using the same method. This results in the bar sliding in and out from the top. Here is the code that makes the bar appear:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.baseUiTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
[self.baseUiTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
And here is the code that removes the search bar:
[uiSearchBar resignFirstResponder];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.baseUiTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
A much simpler way that is also suitable for UITableViewStyleGrouped (plus doesn't require changing the number of rows) is to animate the contentInset of the table:
CGFloat h = uiSearchBar.bounds.size.height;
UITableView *tv = self.tableView;
if (tv.tableHeaderView)
{ // hide bar
[UIView animateWithDuration:0.3 animations:^{
tv.contentInset = UIEdgeInsetsMake(-h, 0, 0, 0);
} completion:^(BOOL finished) {
tv.contentInset = UIEdgeInsetsZero;
tv.tableHeaderView = nil;
[tv scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
}];
}
else
{ // show bar
uiSearchBar.frame = CGRectMake(0, -h, tv.frame.size.width, h);
[UIView animateWithDuration:0.3 animations:^{
[tv scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
tv.tableHeaderView = uiSearchBar;
}];
}
I know this is three years after the OP asked the question, but since this is a good alternative to achieve the desired effect, I thought it might be useful for others meeting the same problem.
Try having your table view scroll—animated—so that only the row below the search bar is visible, then remove the search bar and scroll to the same row without animation.