I have a problem with header view while reloading UITableView. Actually problem is with unexpected blinking the entire view just after reload.
I want dynamically change the height of the view and this animation is definitely unwanted.
Is it possible to rid of this.
To reload section I use:
[self.table reloadSections:indexSet withRowAnimation:UITableViewRowAnimationNone];
- (void)swipeAction:(UIPanGestureRecognizer *)gesture
{
CGFloat posY = [gesture translationInView:self.view].y;
self.dynamicHeight = posY;
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:0];
[self reloadSection:indexSet];
}
- (void)reloadSection:(NSIndexSet *)indexSet
{
[self.tblContainer beginUpdates];
[self.tblContainer reloadSections:indexSet withRowAnimation:UITableViewRowAnimationNone];
[self.tblContainer endUpdates];
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIViewController *vc = self.controllers[section];
if ([self.childViewControllers containsObject:vc]) {
} else {
[self addChildViewController:vc];
[vc didMoveToParentViewController:self];
}
return vc.view;
}
- (CGFloat)heightCell
{
return MIN_HEIGHT + dynamicHeight;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return [self.controllers[section] heightCell];
}
Hmm probably you should use this approach try to indicate when you start and end update of table view :
[self.tableView beginUpdates];
[self.table reloadSections:indexSet withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
Related
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.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView beginUpdates]; // tell the table you're about to start making changes
if ([indexPath compare:self.expandedIndexPath] == NSOrderedSame) {
self.expandedIndexPath = nil;
} else {
self.expandedIndexPath = indexPath;
}
[tableView endUpdates]; // tell the table you're done making your changes
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([indexPath compare:self.expandedIndexPath] == NSOrderedSame) {
return 200.0; // Expanded height
}
return 44.0; // Normal height
}
- (void)pieChart:(XYPieChart *)pieChart didSelectSliceAtIndex:(NSUInteger)index
{
This is a function of getting the index , when clicking a pie chart.
what i need to do is expand the corresponding row of table when pie is selected
}
#end
If i got your idea you need to select the row at index path
- (void)pieChart:(XYPieChart *)pieChart didSelectSliceAtIndex:(NSUInteger)index
{
// get indexPath with index
// remember if you have few sections then you will need to update inSection:0 value
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
[yourTableView selectRowAtIndexPath:indexPath
animated:NO
scrollPosition:UITableViewScrollPositionNone];
// This will also Highlighted the row. Then delegate
[yourTableView.delegate someTableView didSelectRowAtIndexPath:indexPath];
}
I have a UIWebView inside my custom UITableViewCells. The problem is that I don't quite know how to dynamically size my UITableViewCell cells since the webview inside the cell needs to render before I can know the webview's height.
My proposed solution is as follows:
CustomCell.m conforms to UIWebViewDelegate and it returns its own height with delegate method after the webview inside it has finished loading.
- (void)webViewDidFinishLoad:(UIWebView *)webView {
CGFloat height = [[webView stringByEvaluatingJavaScriptFromString:#"document.body.scrollHeight"] floatValue];
[self.contentWebview setFrameHeight:height];
[self.delegate cellDidFinishLoadingWithCell:self withHeight:height];
}
Then TableViewController.m conforms to the cell's delegate, and redraws by doing something like:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
return [self.heights[[NSString stringWithFormat:#"%i%i",indexPath.section,indexPath.row]] floatValue];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UIWebViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"webview-cell" forIndexPath:indexPath];
MyData *d = self.data[indexPath.section];
[cell setUpCellForData:d];
[cell setDelegate:self];
return cell;
}
- (void)cellDidFinishLoadingWithCell:(LessonTableViewCell *)cell withHeight:(CGFloat)height {
NSIndexPath *indexPath = [self.tableview indexPathForCell:cell];
NSString *key = [NSString stringWithFormat:#"%i%i",indexPath.section,indexPath.row];
if (!self.heights[key]) {
[self.heights setObject:[NSNumber numberWithFloat:height] forKey:key];
}
[self.tableview beginUpdates];
[self.tableview endUpdates];
}
Some cells seem to be the correct height, but many of them end up having a height of 0...
remove :
[self.tableView beginUpdates];
[self.tableView endUpdates];
add :
[self.tableView reloadData];
This is Apple Documents:
beginUpdates
reloadData
https://stackoverflow.com/a/8174094/2530660
I have code as follows:
#import "TestTableViewController.h"
#interface TestTableViewController ()
#property (nonatomic,strong) NSMutableArray *testDataArray;
#end
#implementation TestTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.testDataArray = [[NSMutableArray alloc] init];
for(int i = 0; i < 20; i++){
[self.testDataArray addObject:[NSString stringWithFormat:#"TestString - %#",#(i)]];
}
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.testDataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"testCell" forIndexPath:indexPath];
cell.textLabel.text = [self.testDataArray objectAtIndex:indexPath.row];
return cell;
}
- (IBAction)insertNewElement:(UIBarButtonItem *)sender
{
[self.testDataArray insertObject:#"AAAAAA" atIndex:0];
[self.tableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForItem:0 inSection:0]]
withRowAnimation:UITableViewRowAnimationAutomatic];
}
As you see code is very simple.
Storyboard is also standard:
But when I select third cell and insert new cell this happen (Newly inserted cell is without separator line):
I found one solution, but there is a problem with it.First it uses Private API, and second I'm not sure that this is good practice to do:
- (void)layoutSubviews {
[super layoutSubviews];
for (UIView *subview in self.contentView.superview.subviews) {
if ([NSStringFromClass(subview.class) hasSuffix:#"SeparatorView"]) {
subview.hidden = NO;
}
}
}
Is it possible, that this is bug in Apple?
I would suggest to make little bit change in you simplified version of application with method implementation like,
- (IBAction)insertNewElement:(UIBarButtonItem *)sender
{
//Update 1:
[self.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:selectedrow inSection:0] animated:NO];
[self.testDataArray insertObject:#"AAAAAA" atIndex:0];
[self.tableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForItem:0 inSection:0]]
withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:selectedrow+1 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionNone];
} //selectedrow define in your .m file as NSInteger.
May this help you!!
Building on the other answers I would use begin and endUpdates instead
- (IBAction)insertNewElement:(UIBarButtonItem *)sender
{
[self.tableView beginUpdates];
[self.testDataArray insertObject:#"AAAAAA" atIndex:0];
[self.tableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForItem:0 inSection:0]]
withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:selectedrow+1 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionNone];
[self.tableView endUpdates];
}
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/index.html#//apple_ref/occ/instm/UITableView/beginUpdates
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.