UITableView - Sliding content inside each cell horizontally - ios

This is my first native iOS app...
Exactly like the iTunes app on iOS does, by having a tableview that you can scroll vertically, and then each row, you can scroll independently horizontally. At least this is ow I imagine it to work.
how would I implement this? I imagine a view inside each tableCell that can scroll horizontally?
Can any one please shed some light on this and what I might read or try to do

You can add the scroll view into the cells content view and then just the content size property of the scroll view to whatever length you want. Here I have set the width of scroll view to 1000 and the height to 44 (which is the default size of the UITableViewCell).
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
UIScrollView *vwScroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
vwScroll.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
vwScroll.contentSize = CGSizeMake(1000, 44);
[cell.contentView addSubview:vwScroll];
return cell;
}

The only option I can think of is if you place a UIScrollView inside the UITableViewCell's view.
Note though, that this may cause problems in regard to the vertical scrolling behavior of the UITableView itself.

To achieve independently scrolling rows similar to the App Store app on iOS, one approach is to nest a Collection View inside a Table View Cell.
I wrote a Swift tutorial with step-by-step instructions on the setup, including how to wire the Collection View dataSource to the Table View Cell.
The tutorial includes a working sample project on GitHub and a link to an Objective-C tutorial.

I believe the free Sensible TableView framework provides these cells out of the box. Should give you a good head start since you're still starting out. Hope this helps.

Related

How to update UITableViewCell height because of text entered into UITextView

I have different examples where we can update the UITableViewCell height based on growing UITextView which actually is working for me. The issue which I am facing is, I have more subviews below UITextView inside a UITableViewCell. This way, the cell's height updates but the position of the subviews remain fixed which causes overlap of UITextView and the subviews.
Just to mention, I am not using auto layout.
How do I fix this ?
These are the three screenshots which will help in understanding my issue :
1. Before TextView is shown :
2. After TextView is shown :
3. After text is entered :
I'm assuming you are using auto layout for this cell (but we could use a code example or Xcode screenshot to help you more specifically). If you are using auto layout, you'll want to make sure that:
You have a constraint between the UITextView and the other UIView subviews below it in the cell
The other UIView subviews are eventually constrained to the bottom of the cell.
Because UITableViewCells are reused, you will find that when adding objects to the contentView, those objects will also be reused without being removed, leading to overlapping subviews. The way around this it to start your cellForRowAtIndexPath with the following code:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
for (UIView * view in [cell.contentView subviews]) {
// clears the cell before reusing
[view removeFromSuperview];
}
Hope this helps.
Are you using auto layout? I have done this before several times with UITableViewCells though it’s mainly been with UILabel and not UITextView.
Your problem might be resolved with auto layout. You layout all your subviews (inside of UITableViewCell) relative to each other. If one view (i.e. UITextView) changes size the other views will then adjust relative to that view. Here are a few useful links.
This isn’t specific to UITableViewCell but has a lot of good examples of various scenarios.
Stanford University Developing iOS 7 Apps: Lecture 9 - Animation and Autolayout
https://www.youtube.com/watch?v=r1sc7NI6-wo

Horizontal UICollectionView in UITableView not scrolling

In my project, I have a UITableView with different types of cells.
One of these cells contains a horizontally scrolling UICollectionView.
When I run my project, the UICollectionView is correctly populated, but I cannot scroll horizontally, clicking and dragging inside this UICollectionView only allows for me to scroll the tableview vertically.
The desired behaviour would be that a click inside the cell with the UICollectionView would allow the user to scroll horizontally, clicking in any other cell allows for vertical scrolling.
I'm assuming that I need to overwrite/pass on or disable some OnClick event in this cell however I cannot find the correct solution.
Any help pointing me in the good direction would be greatly appreciated :)
The code for creating the concerning TableViewCell looks like this.
#property(nonatomic) HorizontalCollectionViewDelegate *horizontalCollectionViewDelegate;
- (UITableViewCell *) createHorizontalScrollCell:(NSIndexPath *)indexPath tableView:(UITableView *)tableView{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:myCellIdentifier];
MyHorizontalScrollingTableCell *myHorizontalScrollingTableCell = (MyHorizontalScrollingTableCell *)cell;
UICollectionView *horizontalCollectionView = myHorizontalScrollingTableCell.myHorizontalCollectionView;
//Link collectionView to its delegate
self.horizontalCollectionViewDelegate = [[HorizontalCollectionViewDelegate alloc] init];
horizontalCollectionView.delegate = _horizontalCollectionViewDelegate;
horizontalCollectionView.dataSource = _horizontalCollectionViewDelegate;
_horizontalCollectionViewDelegate.data = myData;
//Define the cells in HorizontalCollectionView
UINib *cellNib = [UINib nibWithNibName:#"CollectionViewCell" bundle:nil];
[horizontalCollectionView registerNib:cellNib forCellWithReuseIdentifier:#"horizCell"];
//Define flow of AttachmentsCollectionView
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
[flowLayout setItemSize:CGSizeMake(90, 90)];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[horizontalCollectionView setCollectionViewLayout:flowLayout];
return cell;
}
EDIT: I'm using the same HorizontalCollectionViewDelegate elsewhere in my project (just not in a tableview) and over there it is working, so I assume the problem is not there.
EDIT 2: Problem solved, turns out there wasn't a problem (see answer below), will be accepting my answer in two days when I can.
Solved...
Turned out I only needed to add more content to the UICollectionView.
With 2 or 3 elements the Cells did not fill the complete view. Because the swipe animation was not showing I assumed there was an error somewhere.
However just adding more content solved this issue.

UITableview cell subview larger height then cell

#All Hello
Its quite interesting problem i have.
Actually i have subviews which can be larger in height then cell height itself (Its required for my design). For example cell "A" height is 40 while subview height= 70.
I can show larger subview but when the cell A goes off the screen (i scroll to top) then its subview also disappear (Obvious) result. But that gives undesired effect as larger subview which before extends to cell say "B" beneath container cell suddenly disappear.
I have tried to set cell background as transparent in willDisplayCell delegate method but no luck.
Below is my related method if anyone wants to see
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
NSArray *newArray = [[dataDictionary allKeys] sortedArrayUsingSelector: #selector(compare:)];
[cell.contentView addSubview: [[[dataDictionary objectForKey:[newArray objectAtIndex:indexPath.section]] objectForKey:#"DayView"] objectAtIndex:indexPath.row]];
return cell;
}
Pardon me if i am not very much clear but this is best i can explain my situation.
I want to show views like http://postimg.org/image/e5ok5hybl/ image.
If you must do this, you can use a simple trick:
Move the y-origin of the table to a negative value equal to the amount your view extends below the cell, e.g. origin -30px.
Make the table height taller by the same amount, i.e. make it 30px taller.
Increase the top content inset of the table by the same amount, i.e. increase by 30px.
What you've effectively done is extend the table view off-screen while maintaining the original position of the cells. Since the table view extends off-screen, the cell will not be dequeued until the part that extends below the cell has scrolled off screen.
Here is a sample project demonstrating the trick.

On iOS, what is the difference between adding a subview to a UITableViewCell object "cell" vs to "cell.contentView"?

In the following code, if we do [cell addSubview: someLabel] vs [cell.contentView addSubview: someLabel], they seem to work the same. Is there any difference doing one or the other? (the custom cell in the real code is adding UIImageView and UILabel) (UIView, on the other hand, doesn't have contentView, so we don't need to add subview to its contentView. UITableViewCell is a subclass of UIView by the way)
-(UITableViewCell *) tableView:(UITableView *) tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
if ([tableView isEqual:self.songsTableView]){
static NSString *TableViewCellIdentifier = #"MyCells";
cell = [tableView dequeueReusableCellWithIdentifier:TableViewCellIdentifier];
if (cell == nil){
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:TableViewCellIdentifier];
}
// ... some code to create a UILabel (not shown here)
[cell addSubview: someLabel]; // vs using [cell.contentView addSubView: ...]
I believe If I am not wrong, the contentView is a subview of UITableViewCell.
If you look at this page here, you can see there are actually 3 subviews in a UITableViewCell
I think by default, the Editing Control is hidden until you enter edit mode for a table in which case, the Editing Control appears (the minus button left of each row) and your contentView gets resized and pushed to the right. This is probably what gives the "proper animation" effect mentioned by the other answer.
To test the difference, try adding a subview such as UILabel with text, to the cell rather than the cell.contentView. When you add it to cell rather than cell.contentView and you enter edit mode for your table, I believe your UILabel will not resize, you will see the edit button ontop/below the minus sign button.
Placing your views in the contentView affects proper animation in and out of edit mode. Place all of your subviews in contentView when you're not subclassing, which should be all of the time unless you know what you're doing.

Removing old data from reusable cell

I have a uitableview with each cell having a scroll view as the subview.
the scrollview has a bunch of images in it.
so when i change the data in the data source and after calling the reload table
the images doesn't change but when i remove the dequeue the new data is reloaded.
is there any method to remove the contents in the dequeue so that i don't get the old data
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"looser"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
scrollview=[[myscrollView alloc]initwitharray:imagearray];
[cell.contentView addSubview:scrollview];
}
}
A tableview works as follows:
It has room for a certain amount of cells on the screen, let's say 7 as an example. The tableview will ask you for the 7 cells of indexes 0 through 6.
If the top cell leaves the screen by scrolling, it will be placed in the reusable cell queue. There are now 6 cells on the tableview.
A new one comes up at the bottom now, the tableview asks for the cell at index 7. You call dequeueReusableCell, and you get the one that was at the top earlier.
The tableView has no idea what your cell is like, as it can be subclassed, so it will not make any changes to it. It is up to you to use your knowledge of how the tablecell is constructed to empty it, then fill it with the correct new data.
The reason tableview works like this is for performance. In stead of having maybe 100 views that would have to be checked (or mostly, ignored, which also costs time) for every scroll movement, it has a maximum of 7.
So in short, no. There are no default methods to remove data from reusable cells in UITableView, since UITableView can not and should not know what kind of cells they are. It is up to you to clear the cells when the tableview gives them to you.
Create a custom cell and it generates a method
- (void) prepareForReuse{}
Which do you cleanse all data from a cell and the output will be an empty cell.
No, not while the cell is in the cache. When you dequeue a reusable cell you should clear out the old data first before using it again.
Maybe you should just remove the stuff you don't want.

Resources