-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
..
//this cell is custom cell.
[cell.textview setContentOffset:CGPointZero animated:YES]; //did not work
..
}
////////////////
- (void)tableView:(UITableView *)tableView willDisplayCell:(CustomCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
..
[cell.textview setContentOffset:CGPointZero animated:YES]; //did not work
..
}
all of them not effect. textview scroll was shown bottom.
I got it myself
solution here.
- (void)tableView:(UITableView *)tableView willDisplayCell:(CouponCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
CGPoint bottomOffset = CGPointMake(0, cell.textview.frame.size.height - cell.textview.contentSize.height);
if (cell.textview.contentSize.height >= cell.textview.bounds.size.height) {
[cell.textview setContentOffset:bottomOffset animated:NO];
}else{
[cell.textview setContentOffset: CGPointMake(0,0) animated:NO];
}
}
scrolled positon is set (0,0) by iOS inner...maybe.
so setting minus y values.
thanks for answer.
have a good day all!
Try to use without animation
[cell.textview setContentOffset:CGPointZero]
Or add animation block
[UIView animateWithDuration:0.5 animations:^{
[cell.textview setContentOffset:CGPointZero]
}];
Hope this help
Try with below code:
[cell.textview scrollRangeToVisible:NSMakeRange(0, 0)];
OR
[cell.textview setContentOffset:CGPointZero animated:NO];
This is a hack that works well. In cellForRow you disable textView scrolling. Then in viewDidAppear you find the specific index path that contains the textView and you enable scrolling again. If you want you can delete padding from textView:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:4 inSection:0];
FileInfoNotesTableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
cell.notesTextView.scrollEnabled = YES;
//I cut the padding from the textview
cell.notesTextView.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0);
Related
I am trying to perform an animation on a cell when the accessory view is tapped. The tapped delegate method is firing and I can get the row to do something--change label, but it is ignoring the animation (or in another case--not even making the change.) How can I get the animation to work properly?
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath{
MyCustomCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
[UIView animateWithDuration:5.0
delay: 5.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
//NEXT TWO LINES HAVE NO EFFECT ON CELL SO COMMENTED OUT
//cell.nameLabel.text = #"Thank you. FIRST ANIMATE TRY";
// [self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
//NEXT THREE LINES CHANGE TEXT BUT WITHOUT ANIMATION
[self.tableView beginUpdates];
cell.nameLabel.text = #"Thank you. Second try!";
[self.tableView endUpdates];
}
completion:^(BOOL finished){
NSLog(#"animation finished");
}];
}
BTW I also tried explicitly dispatching this in the main queue but it had no effect. It should already be in main queue.
First of all, you don't need to call beginUpdates or endUpdates. Second, you can't animate the change of a label's text value.
What you need to is have a label on the cell and initialize the alpha property to 0.0. When accessoryButtonTappedForRowWithIndexPath is called set the alpha property to 1.0 inside of your animation block.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
AwesomeCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.thankYouLabel.text = #"Thank you";
cell.thankYouLabel.alpha = 0.0;
return cell;
}
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
AwesomeCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[UIView animateWithDuration:1.0 animations:^{
cell.thankYouLabel.alpha = 1.0;
}];
}
My requirement is simple , i just need to add a TableCell with rightRowAnimation and scroll to it. It happens as long as i am with within tableView height , as i cross the height of tableView to add cell further , it adds cell but displays no animation when scrolling to it.
Attached is a simple project with a UITableView for reference , Appreciate your help !!
Sample Project with a simple UItableView and Add Button
Code
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyCell1"];
BOOL myBool = indexPath.row%2 == 0;
if(myBool){
cell.backgroundColor = [UIColor redColor];
}else{
cell.backgroundColor = [UIColor whiteColor];
}
cell.textLabel.text = [self.dataArray objectAtIndex:indexPath.row];
return cell;
}
-(IBAction)addTapped:(id)sender {
[self.dataArray addObject:#"New Object"];
// [_tableView beginUpdates];
[_tableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:self.dataArray.count-1 inSection:0]] withRowAnimation:UITableViewRowAnimationRight];
// [_tableView endUpdates];
[_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.dataArray.count-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
Use bellow method for the animation.
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
cell.alpha = 0;
cell.layer.transform = CATransform3DMakeScale(0.5, 0.5, 0.5);
[UIView animateWithDuration:0.7 animations:^{
cell.alpha = 1;
cell.layer.transform = CATransform3DScale(CATransform3DIdentity, 1, 1, 1);
}];
}
change what ever your requirements
you can try this to animate row put in table.
-(void)viewWillAppear:(BOOL)animated
{
dispatch_async(dispatch_get_main_queue(), ^{
[UIView transitionWithView:yourtablename
duration:5.1f
options:UIViewAnimationOptionTransitionFlipFromTop
animations:^(void) {
[yourtablename reloadData];
} completion:NULL];
});
}
also you can change animation style.
I would like to make something like expandable cells. Result I'm trying to achieve is:
Actually I have:
Here is my code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
DoctorCell *cell = self.prototypeCell;
DoctorModel *doctor = [self.fetchController objectAtIndexPath:frcIndexPath];
// depending on isActive property I add (or do not add) some content.
[cell cellForDoctor:doctor isActiveCell:[self.activeCellIndexPath isEqual:indexPath]];
[cell setNeedsUpdateConstraints];
[cell setNeedsLayout];
[cell layoutIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
return height + 1;
}
Here is my cell selection method
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
NSIndexPath *oldIndexPath = self.activeCellIndexPath;
if ([indexPath isEqual:self.activeCellIndexPath]) {
self.activeCellIndexPath = nil;
oldIndexPath = nil;
} else {
self.activeCellIndexPath = indexPath;
}
[self.doctorTableView beginUpdates];
[self.doctorTableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, oldIndexPath, nil] withRowAnimation:UITableViewRowAnimationNone];
[self.doctorTableView endUpdates];
[self.doctorTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
As you can see, my animation looks weird (kind of moving to wrong position, jumps, etc). What I'm doing wrong? Or do I need to pick another approach for expanding cells?
You can use UITableViews animation automation like this:
Call [tableView beginUpdates];
Change the data source.
Insert or delete rows and sections, or reload them
This should cause new heights to be calculated, etc.
Make sure you use something appropriate for the withRowAnimation parameter of these methods
Call [tableView endUpdates];
Your animation should now perform as expected.
Maybe your problem is that you selected UITableViewRowAnimationNone for the row animation.
I have a problem with the default separator on UITableView in iOS 7.
When used as default the first and last separators have no insets, others are a bit inset. The original situation can be seen below:
Everything is ok. The first and last separators spread through the entire width of the table while the others are a bit smaller. Now I have the table view set to editing and I allow the user to reorder cells. And when the user does so the separators get messed up and do not appear correctly. The situation can be seen on the images below:
Do I really need to reload the data in order to fix this issue or is it an iOS 7 bug or am I doing something wrong?
How to fix this?
EDIT
Added some info about my implementation. I return NO on - (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath and UITableViewCellEditingStyleNone on - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath. My - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath is:
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.shouldIndentWhileEditing = NO;
cell.textLabel.font = [UIFont someFont];
UIColor *color = [UIColor randomColor];
cell.textLabel.text = #"Some text";
CGRect rect = CGRectMake(0, 0, 15, 15);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
CGContextRef ctx = UIGraphicsGetCurrentContext();
[color set];
CGContextFillEllipseInRect(ctx, rect);
cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return cell;
}
and
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
if (sourceIndexPath.row == destinationIndexPath.row) return;
NSString *tmp = [itemOrder objectAtIndex:sourceIndexPath.row];
[itemOrder removeObjectAtIndex:sourceIndexPath.row];
[itemOrder insertObject:tmp atIndex:destinationIndexPath.row];
didReorder = YES;
}
This seems to be a problem in the iOS SDK. One way to solve it would be to manually apply the correct separator insets to all cells. However, I personally prefer to let the system do that.
If you reload a cell after reordering, the correct separator insets will be applied by the system. Therefore, you should simply make sure to reload the relevant cells after reordering.
Fix for user reorderings
There's a private method tableView:didEndReorderingRowAtIndexPath: that's called on your table view's delegate after the reordering (animation) has ended. In this method you should reload the cells:
- (void)tableView:(UITableView *)tableView didEndReorderingRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section]
withRowAnimation:UITableViewRowAnimationNone];
}
This fix only works if rows are only moved within a section (and not between sections).
(It would be more efficient to only reload the moved cell and the cell at the old location using the method reloadRowsAtIndexPaths:withRowAnimation:. However, you'd have to store the old location before the cell is moved. which would be more complex to implement. For small sections/simple cells reloading the whole section might be a little bit easier.)
Fix for programmatic moves
Unfortunately, the private delegate method used in the previous fix is only called after reorderings by the user, and not after programmatically moving a row (using moveRowAtIndexPath:toIndexPath:). Therefore, we'll have to use another fix for that.
Since table views internally use CALayer animations, we can use a CATransaction to get to know when the animation has ended. (You do need to add QuartzCore.framework to your project for this.) My fix looks like this:
UITableView+NicelyMoves.h
#import <UIKit/UIKit.h>
#interface UITableView (NicelyMoves)
- (void)nicelyMoveRowAtIndexPath:(NSIndexPath *)indexPath
toIndexPath:(NSIndexPath *)newIndexPath;
#end
UITableView+NicelyMoves.m
#import <QuartzCore/QuartzCore.h>
#import "UITableView+NicelyMoves.h"
#implementation UITableView (NicelyMoves)
- (void)nicelyMoveRowAtIndexPath:(NSIndexPath *)indexPath
toIndexPath:(NSIndexPath *)newIndexPath
{
[CATransaction begin];
[CATransaction setCompletionBlock:^{
// This is executed after the animations have finished
[self reloadRowsAtIndexPaths:#[indexPath, newIndexPath]
withRowAnimation:UITableViewRowAnimationNone];
}];
[self moveRowAtIndexPath:indexPath toIndexPath:newIndexPath];
[CATransaction commit];
}
#end
Usage
Now, instead of using moveRowAtIndexPath:toIndexPath:, you should use the custom method nicelyMoveRowAtIndexPath:toIndexPath:. For example, you could do this:
#import "UITableView+NicelyMoves.h"
#implementation YourTableViewController
- (void)moveTheRow
{
// Move row 0 to 2 in section 0
NSIndexPath *from = [NSIndexPath indexPathForRow:0 inSection:0];
NSIndexPath *to = [NSIndexPath indexPathForRow:2 inSection:0];
[self.tableView nicelyMoveRowAtIndexPath:from toIndexPath:to];
}
#end
Please try forcing inset size or setting them to zero in the viewDidLoad to ensure tableView respects them.
This is going to set your tableView separator insets to 30.
- (void)viewDidLoad {
[super viewDidLoad];
if ([self.tableView respondsToSelector:#selector(setSeparatorInset:)]) {
[self.tableView setSeparatorInset:UIEdgeInsetsMake(0, 30, 0, 0)];
}
}
You can also set separator insets only on specific cells as:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyCellId"];
if (indexPath.section == 0 && indexPath.row == 0) {
[cell setSeparatorInset:UIEdgeInsetsMake(0, 30, 0, 0)];
} else {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
return cell;
}
I have uitableview and it has 1 button "TOP" in each row. I want to when user click on this button, this row has been push on top in Uitableview ( with animation). Can i reuse BVReorderTableView to do that? How can i do that? Thanks much
i am assuming your -cellForRowAtIndexPath loads cell contents from an array such as the one i named arrObjects which:
is an NSMutableArray object
has many NSString objects
something like:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//...
[cell.textLabel setText:[arrObjects objectAtIndex:indexPath.row]];
UIButton *btnUp = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btnUp setFrame:CGRectMake(0, 0, 30, 30)];
//[btnUp setTag:100];
[btnUp setTitle:#"\u261D" forState:UIControlStateNormal];
[btnUp addTarget:self
action:#selector(moveToTop:)
forControlEvents:UIControlEventTouchUpInside];
[cell setAccessoryView:btnUp];
return cell;
}
- (void)moveToTop:(UIButton *)sender
{
UITableViewCell *cell = (UITableViewCell *)sender.superview; //iOS6 prior
//UITableViewCell *cell = (UITableViewCell *)sender.superview.superview; //iOS7
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
//uncomment lines for safety, incase indexPath ever comes nil... prevent the crash
//if (indexPath == nil) {
// return;
//}
//1. move and animate row to top
[self.tableView moveRowAtIndexPath:[NSIndexPath indexPathForItem:indexPath.row
inSection:indexPath.section]
toIndexPath:[NSIndexPath indexPathForItem:0
inSection:indexPath.section]];
//2. make appropriate changes to the datasource
//so that it reflects logically and is not just an aestehtical change
//PRE-NOTE:
//arrObjects is an object of a category on NSMutableArray
//with a custom instance method named -moveObjectFromIndexPath:toIndex:
//uncomment the following line when you are ready with the category
//[arrObjects moveObjectFromIndex:indexPath.row toIndex:0];
}
the category is easy to create, follow:
http://www.icab.de/blog/2009/11/15/moving-objects-within-an-nsmutablearray/
other links to try:
http://adeem.me/blog/2009/05/29/iphone-sdk-tutorial-add-delete-reorder-uitableview-row/
http://learn-iphone-app-development.com/2011/01/31/tables-part-iii-%E2%80%94-re-ordering-moving-cells-and-swipe-to-delete/
have you tried
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
you can use animations if you want so..
You can easy do that like this:
[self.tableView setContentOffset:CGPointMake(0, 0) animated:YES];
or:
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
or:
[self.tableView scrollRectToVisible:CGRectMake(0.f, 0.f, CGRectGetWidth(self.tableView.frame), CGRectGetHeight(self.tableView.frame)) animated:YES];
Edit
Sorry, I misunderstood what you meant.
You should do that like this:
[tableView moveRowAtIndexPath:indexPath toIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
If you want to tableView scroll to the top immediately after move the cell, you can try the above code.
Edit
// A more detailed description
- (void)buttonHandle:(UIButton *)sender {
// Assuming button is added directly on the cell.
UITableViewCell *cell = (UITableViewCell *)sender.superview;
NSIndexPath *indexPath = [tableView indexPathForCell:cell];
[tableView moveRowAtIndexPath:indexPath toIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
}