iOS Jump to next cell in UITableView when cell scrolled - ios

I would like to implement a UITableView with cells that are full screen. When the user moves the cell up a portion, I would like to jump to the next cell as opposed to allowing it to scroll naturally.
I can't see a great deal of questions or answers out there on this, and perhaps it's because it's a daft idea, but the client wants to see it and the designer has designed it as such so I really must try.
Does anyone have ANY suggestions on how to implement this?
Thanks. (and thanks for pointing out my ignorance in not saying thanks!)

If your cells are going to be the same size as your tableView's height, set the pagingEnabled property to YES. This will make it snap to a full cell on each vertical swipe. I would ensure that the height is exactly full-screen if you do this, otherwise you'll end up with some weird offsets as you scroll.
- (void)viewDidLoad
{
[super viewDidLoad];
// or somewhere similar
self.tableView.pagingEnabled = YES;
}
...
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return self.tableView.frame.size.height;
}
It actually isn't a terrible idea- you could achieve similar functionality with a paging scroll-view, but this has the advantage of not needing to have all of your data loaded at once.
Edit: I also had to make sure to disable automaticallyAdjustsScrollViewInsets on the controller, otherwise I had an undesired initial offset for the first cell, just in case you run in to that as well.

Related

Self Sizing Cells make UITableView jump

I've got a UITableView, each cell has an image and two labels, as you can see on the first picture
So I am trying ti use self-sizing cells and everything is great, except 2 things:
1) First and Second cell don't show content properly, but after I scroll down and then return to them everything is ok. I tried to use [tableview reloadData] in viewDidAppear, but it doesn't help. Watch the labels at first they don't fit. You can watch it on this video https://www.youtube.com/watch?v=I9DGBl1c5vg
Look at the labels on the first cell.
2) It's a tough one. I'm scrolling the table and everything is great, but the problem happens, when I select the row. It's pushing me to detail view, but when I press "back" and return to master view, the tableview jumps,so I'm coming back not to the selected row, also if I scroll the table it doesn't scroll smooth, but jumps. Here are the links for two videos, first one shows that scroll is smooth https://www.youtube.com/watch?v=9wAICcZwfO4 if i don't go to detail view, and the second shows the jumping problem https://www.youtube.com/watch?v=fRcQ3Za1wDM .
It's absolutely sure connected with self sizing cells, because if I don't use it, none of this problem happens.
Okay, I solved both of the problems.
Question 1
I've added these two lines
[cell.contentView setNeedsLayout];
[cell.contentView layoutIfNeeded];
in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath before return cell
Question 2
The solution appeared to be very simple. I've just needed to implement viewWillDissapear and reload data in it, so the code looks like this
- (void)viewWillDisappear:(BOOL)animated;{
[super viewWillDisappear:animated];
[self.tableView reloadData];
}
Solution for me was simple, if it doesn't work for someone, here I found some useful links.
1) UITableView layout messing up on push segue and return. (iOS 8, Xcode beta 5, Swift)
2) http://useyourloaf.com/blog/2014/08/07/self-sizing-table-view-cells.html
Unfortunately I believe both of the questions that you ask about are IOS bugs.
Question (1)
A easy fix is suggested by this blog.
When the table view is first displayed, you may find some of the cells are not sized properly. But when you scroll the table view, the new cells are displayed with correct row height. To workaround this issue, you can force a reload after the view appears:
Simply add the following to your viewDidAppear method. I have tested it and it works very well.
[self.tableView reloadData];
Question (2)
This second question is a duplicate of this following question:
IOS 8 UITableView self-sizing cells jump/shift visually when a new view controller is pushed
A workaround is suggested by the author of the question himself, which seems okay. However, I have not tried out this one yet.
Okay, I solved it by caching my cell heights in sizeThatFits, and returning that value for estimated cell heights within the delegate. Works beautifully.
Feel free to head over to that question for other proposed solutions.

iOS 8: UITableViewCell detail text not correctly updating

tl;dr: Can I cause the detailTextLabel to have its size updated by the auto layout system in iOS on a value change?
Has anyone else had issues with the detailText label within an UITableViewCell since iOS 8?
I have a table which both text and detail strings. Initially detail text is an empty string (#""). After performing a storyboard segue to an edit screen, I return with a new value for the detail text and update it. I attempt to reload the table in viewWillAppear so that the value is present immediately upon returning to the previous view.
Once the table view is visible again, the table cell has shifted the text field up to make room for the detail text, but no detail text is displayed. The text does not display until I return to the edit screen, and come back a second time.
What I've done to troubleshoot: It looks as thought the auto layout for the detail text label isn't correctly updating as I think it should, and logging the size and makeup of the detailTextLabel's frame confirms this.
I am able to force the text to update by running [table reloadData] within viewDidAppear, however that leaves me with a flicker effect I don't like, and looks unprofessional.
Edit: Additional things I've done: I've also forced the detailTextLabel to re-size itself using [cell.detailTextLabel sizeToFit]. This causes it to display, but offset in an odd way in the cell. After going to the edit page again, the detailTextLabel fixes it's position.
I've created a simple project as a github repo, to show exactly what I'm dealing with:
https://github.com/acidaris/ios8_table_issue
The main code of the view controller I'm using is also below.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.table reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
cell.textLabel.text = #"This is a test";
cell.detailTextLabel.text = self.value;
CGRect frame = cell.detailTextLabel.frame;
NSLog(#"detailTextLabel x=%f y=%f width=%f height=%f",
frame.origin.x,frame.origin.y,frame.size.width,frame.size.height);
return cell;
}
The cell is prototyped within a StoryBoard, and so the cell selected by dequeueReusableCellWithIdentifier: is always defined. Additionally, the cell type within the storyboard is set to subtitle, and it does display if the initial value is defined.
If anyone could help me figure this out, I would be incredibly grateful.
Partial Solution
If you are sub-classing UITableViewCell, you can modify the frame for the detailTextLabel when the layout is done. This is what I've done, and it seems to have worked, but on the 6 plus, I get a weird dividing line between the textLabel and the detailTextLabel. edit: (I have adjusted for this.) I don't like this solution, but thus far it's the best I've come across. It doesn't update after presenting the view, and is relatively simple. As I said above, I will continue to look for a better solution.
- (void)layoutSubviews {
[super layoutSubviews];
CGRect textFrame = self.textLabel.frame;
[self.detailTextLabel sizeToFit];
CGFloat x = textFrame.origin.x;
CGFloat y = textFrame.origin.y + textFrame.size.height;
CGSize detailSize = self.detailTextLabel.frame.size;
CGRect newFrame = CGRectMake(x, y, detailSize.width, detailSize.height);
self.detailTextLabel.frame = newFrame;
}
I've also updated my Github project to reflect my current solution. Edit3: This doesn't work perfectly, as it has wrong values for truly auto layout frames, but it works for my uses for the moment.
Edit 4: I've updated my layoutSubviews function to be smarter. It will size to fix the content within the label, and position the label appropriately within the x/y coordinates in relation to the text label.
Having the same problem. My solution was to call [cell layoutSubviews] before returning the cell at the end of -tableView:cellFForRowAtIndexPath. This works for me, and I didn't find it necessary to override layoutSubviews in the cell subclass.
I have same problem with cell not updating correctly when using segue in storyboard.
Tried
[setNeedsLayout] and [layoutIfNeeded]
on the view and the tableview and it is NOT working.
[self.tableView reloadData] is in viewDidAppear, as it should.
Then I tried the advice from pixbug, and it worked. But one should NOT use [layoutSubviews] directly. So I tried the ones that is adviced by the documents on the cell instead of tableView or the view.
Tried
[cell setNeedsLayout]
but this did NOT work.
Tried
[cell layoutIfNeeded]
this WORKED for me.
I put this before returning the cell.
I had the same problem in an iOS 8 storyboard (without Auto Layout enabled).
I had a Table View with a static Table View Cell at the bottom of it. In IB, I added some spaces into that table cell's content area (Style: "Right Detail"). Then in code (ViewDidLoad), I updated that cell's content with...
self.copyrightsCell.detailTextLabel.text = #"<a string>";
WITHOUT the IB spaces, the cell was INVISIBLE in portrait mode.
But WITH the initial spaces, the cell's content later appears correctly.
Hope this helps someone.
I have the same issue.
I have am certain that the data is available and being assigned to the cell.detailTextLabel.text
I have noticed that once a value has been assigned then there is no flicker if the value is changed on the return to the tableView.
So it appears to me that there is only an issue on the first assignment of a value to the detailTextLabel.
So, I followed this tread and many others. This one lead me to what seems to be the correct answer. I hope this helps others, since this has driven me crazy since iOS 7 / 8 made some sort of changes.
My answer was to put the normal processing code in viewWillAppear and add this [self.tableview layoutSubviews] instead of [self.tableView reload data]. I think this has to do with Apple making things much more controllable in iOS 7 / 8. I struck upon that idea when reviewing some info on how cells were working.
Again, I hope this helps others resolve this annoying problem.
I had a similar problem with a static UITableView. I change a label's text and it doesn't get updated on the screen unless I clicked on the cell or did anything to force update its views.
My workaround was to call after updating the text:
tableView.reloadData()
P.S This doesn't make any sense; because this is a static table view, and I don't know why it worked, but it did!
I think that if you need to reloadData, that means that the table data isn't loaded when its created.
You'd just need to load your data in the viewdidload (or somewhere else BEFORE the table view gets its data ) where your tableview is, and then create the cells accordingly.
Usually, i just use an array of whatever object i'm using and then use [array objectAtIndex:indexpath.row], which you probably know about.
Also, you ante-last paragraph has an unfinished sentence that looks important.
Confirming the problem using Xcode 6.3.2 (6D2105) OS X Yosemite 10.10.3
I made sure that the correct value was being assigned, still first time no show,
second time show.
cell.layoutSubviews() seemed logical to me since it appeared as if the view lacked a refresh and adding layoutSubviews() did the trick.

Implement a UIScrollView with different sections (i.e. Yahoo! Weather app)

I'm trying to figure out an optimal way to implement a UIScrollView similar to that of the Yahoo! Weather app.
As per image (http://i.stack.imgur.com/hj1xG.png) there's one section for 'Precipitation', one for 'Details', etc.
Each of these sections is also movable up and down. It would also be ideal to be able to have a dynamic height (according to the length of the content that goes into one section) without the following section to overlap/be too far down, and to have the possibility to exclude and now show one or more section if certain conditions are not met.
Being a total amateur in Xcode and Objective-C programming, my approach would be just going with a single UIView and put elements in it, hiding/showing them when needed, simulating the division of the different sections with a UIImage with a background, and defining each element's position programmatically. I'm sure there's a better way to this painfully long and limited approach.
Thank you for your help!
I think you should give UITableView a try.
UITableView inherits from UIScrollView : UIView : UIResponder : NSObject
If you set the tableView.pagingEnabled = YES; you would get the desired effect.
Ray Wenderlich has an example here. Although the tutorial is on something else it starts by creating a paging enabled table view.
Hope this helps
Better to use Custom UITableView with custom cell as uitableview has a method like -
-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
//Even if the method is empty you should be seeing both rearrangement icon and animation.
}
So you could easily have that sorting effects of Yahoo Weather app along with scroll up/down effect.

How to make a UITableView row grow dynamically with the user modified content

I am asking this question already knowing the answer is "no you can't" but in the hopes someone has a brilliant idea here we go.
I have a subclass of UITableViewCell that has a few different subviews one of witch is a UITextField that I have as user editable. So naturally the textField grows with the text that is entered.
Now the question is how could I get the tableview row to grow with the textField.
I have a variety of different size cells so I know how to use - (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath but the problem is that I need to modify the after the cell is already in the tableview.
Also note that the previously noted delegate method gets called before the data source delegate method - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
I have thought of just pulling up another view for the user to edit then putting that data into my data model then I would have to force the tableview to reload. (Can I reload just a certain cell/row)
Interestingly enough I think apple is doing what I want in their iTunes U app. When you tap a assignment it expands. I think they are using tableviews their right?
I know I have a lot of questions and talk here but I believe it is all related and just to show what I have researched. I am just looking for the possibility that one of you has a stroke of genius.
Hopefully this can help others also because this seems to be a hot topic but no one ask the question well or gets good answers.
Actually, this has been asked and answered many times -- it's not impossible. Search for "UITableView custom row height" or "UITableView multi line UITextField" or similar and you'll find several well-answered questions.
You're on the right track -- you need to return a height in tableView:heightForRowAtIndexPath:, even though that method is called before you create/configure the cell. This is okay... you just need a way to compute that height without having the cell. Other answers reference -[NSString sizeWithFont:constrainedToSize:] and related methods... this should get you on the right track.
Changing the height while the text field is editing is less obvious, but this answer has the key... if you call
[tableView beginUpdates];
[tableView endUpdates];
the table view will not only ask its delegate for heightForRowAtIndexPath: again and resize the cell to match, it'll do it with a smooth animation.

Moving Delete icon on UITableView in 'grouped' style into the cell?

I have a UITableView style set to grouped. This works correctly except when in edit mode the 'minus' icon for Deleting a cell isn't within the cell. It's to the left. In the Weather App that icon is in the cell. Anyone know how to fix this?
Image here:
I know this is an old post, but I had a hard time finding the solution to this, so I figured I'd post it:
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
This is normal. It looks like Weather uses a plain table view with its corners rounded, not a grouped table view. But I'd you mist have this behavior, try changing the size of the cell's background view when it's editing...

Resources