i have added a TableView inside Collection View Cell, but the Collection View Cell height should depend on TableView data.
Thanks.
Maybe this can be achieved by reloading the tableview first, waiting for it complete, fetch the tableview Content height then load the collectionview giving the cell the right values
tableView.reloadData()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
requiredCellHeight = self.tableView.contentSize.height
})
This waits on the main thread for the tableview to load. Though not an ideal solution as we are blocking the main thread, might work for this complex setup
Related
I want to animate the subviews of the TableViewCell which is StackView. When I hide the StackView, the TableViewCell height not updating. After googling, I found that I should call tableView.beginUpdates and tableView.endUpdates to notify tableView that there is a change in the cell. The problem is the hide animation and the change of tableview not sync.
Here is the view hierarchy for tableview cell
Content view - Container View (for card shadow) - Container Stack View - [Stack View for label and switch] & [StudentStackView for container of StudentView]
How can I sync the cell height and hide animation the correct way?
Here is the github repo: GitHub
Gif of the App:
You are right in using beginUpdates()/endUpdates(). Make sure you're not placing the someArrangedSubview.isHidden = true/false in an animate block since the table view and stack view will handle the animations accordingly. When the table view begins update operations, the stack view will resize any arranged subviews that you aren't removing to fill the entire space of the cell (even if you have height constraints on the arranged subview). In my case, the cell content jumped every time I wanted to collapse a cell via removing an arranged subview--so I added a dummy view between the view I wished to remain static* and the collapsible view. The static view won't resize, and the dummy view will expand/collapse as needed. Hope this helps.
*static in the sense that I didn't want the view to move when animating.
`public func setup(classRoom: ClassRoom, toggleInProcess: #escaping () -> (), toggled: #escaping () -> ()) {
containerStackView.addArrangedSubview(studentStackView)
self.nameLabel.text = classRoom.name
self.activeSwitch.isOn = classRoom.isActive
self.studentStackView.isHidden = !self.activeSwitch.isOn // Let him know his hide/unhide.
for student in classRoom.students {
let studentView = StudentView()
studentView.nameLabel.text = student.name
studentStackView.addArrangedSubview(studentView)
}
activeSwitch.addTarget(self, action: #selector(toggleShowStudents(show:)), for: .valueChanged)
self.toggleInProcess = toggleInProcess
self.toggled = toggled
setupShadow()
}`
` #objc func toggleShowStudents(show: Bool) {
UIView.animate(withDuration: 0.3, animations: {
self.studentStackView.isHidden = !self.activeSwitch.isOn
self.toggleInProcess()
self.containerView.layoutIfNeeded()
}) { _ in
self.toggled()
}
}`
your studentStackView also know his hide/unhide status while assigning values in function setup.
I left this as a comment but for anyone else experiencing this behavior, the root cause is the UILabel is expanding to fill the visible area before collapsing.
This can be fixed by doing the following 2 things:
Right below the UILabel, insert a Blank UIView
Adjust the Content Hugging Priority of the UILabel to "Required"
With these two adjustments, instead of the UILabel expanding to fill the visible area, the UIView expands instead. Visually, this appears as if the the cell just collapses.
tableView.beginUpdates and tableView.endUpdates are functions that should be called when you are about to modify rowcount or selected state of the rows.
You should try reloadData or reloadrowsatindexpaths, that should take care of the cell height adjustment.
You would better do it using performSelector API so as not to cause recursion in cellForRowAt call stack.
I have used this tutorial to put a collectionView inside a UITableView. https://ashfurrow.com/blog/putting-a-uicollectionview-in-a-uitableviewcell-in-swift/
The UITableViewController is the dataSource & delegate for both the UITableView & the different collection views in each cell.
The problem is that I want to dynamically hide the CollectionView and to change its height to 0 whenever the collectionview is empty.
To do so, I have this code in CellForRowAtIndexPath
if (patients.paraclinicImage.count == 0){
[cell.collectionView setHidden:true];
cell.collectionViewHeight.constant = 0;
} else {
[cell.collectionView setHidden:false];
cell.collectionViewHeight.constant = 80;
}
By having this code, the collectionView shows up correctly initially. However, when scrolling fast, I will sometime have the cell load with the correct cell height, however the collection view will be empty. Refreshing the cell fixes this issue. Removing the above line of codes also fixes the issue.
Here are two images showing how the cell looks when first rendered, and after multiple scrollings (and re-renderings of the cell).
Before scrolling issue looks like below image
But After scrolling issue seems to like below one
I would appreciate any ideas you guys might have.
Debug view hierarchy showing an empty collectionView with an appropriate cell height
It is because your cell height is not updated on fast scrolling. UITableView caches the row height of indexPath just to calculate the scroll area. You need to set constraints properly and adjust the height of cell in heightForRowAtIndexPath: method.
Apply the logic inside heightForRowAtIndexPath: and your problem will be solved.
Happy Coding!!
I had the same issue. Sometimes, my collection view inside a tableviewcell wouldn't show the collectionview cells. I solved it by calling collectionView reload on main thread. I don't exactly know the reason, as I have many background calls on each cell and was reloading the tableview on main thread itself. Still, had to reload collectionview on main thread.
DispatchQueue.main.async {
cell.colViewProperties.reloadData()
}
I've noticed this with a couple of UITableView's that I have coded, and that is when there is a lengthy list, or if I animate the displaying of the table itself, the cells have an animation, like the table is constructing the cells as I'm scrolling down.
The animation looks like the accessory view sliding from the left to the right, and I have a top-right label that does the same.
On another table that I slide in from the bottom, it looks like the buttons and text from the table expand as the table does.
How do I stop this?
I am using Swift, but if you know the answer in OBJ-C that would be okay too.
Also, if you need a preview, check this:
I've tried searching for this and I only get posts about making an animation within the table cells not removing this one!
So I found out how to stop it! It was because of the accessory view and making sure the cells have performed the layoutIfNeeded.
First, I removed the accessoryview from StoryBoard and in willDisplayCell: I used this:
UIView.performWithoutAnimation { () -> Void in
cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
cell.layoutIfNeeded()
}
As well as:
UIView.performWithoutAnimation { () -> Void in
cell.layoutIfNeeded()
}
in cellForRowAtIndexPath:
I'm trying to synchronize scrolling in all collection views within a table view (see image link below) :
Example Image :
http://postimg.org/image/dduhr89e5/
The sample that I have been able to find explains how you can sync two separate scroll views by identifying each. However I am unsure how to identify each collection view when they are in a table view. There could be 1 or hundreds that all need synchronized.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if ([scrollView isEqual: theFirstScrollView])
{
theSecondScrollView.contentOffset =
CGPointMake(theFirstScrollView.contentOffset.x, 0);
}
else
{
theFirstScrollView.contentOffset =
CGPointMake(theSecondScrollView.contentOffset.x, 0);
}
}
Assuming each collection view has its own cell and the collection views are similar widths (or at least you have that part figured out), here is the approach I would use:
1) Make your VC the delegate for all of the collection views.
2) When any of them scrolls, go through the TableViews visibleCells and set the content offset for the cells collectionView. Also, store the content offset in the viewController.
3) Whenever a new cell is dequeued, set the content offset to that last stored value in the VC.
I need to show a tableview within a cell of a tableView. I have a separate dictionary for tableview that is residing inside each cell of tableView. Where i need to assign the dictionary values to the tableview that is inside the cell
Add the tableView as a subview to the cell. Next assign a delegate/datasource to the tableview. This can be the same object as the outer tableViews datasource/delegate. Every time a delegate method is called, the tableView is send along as a parameter and you can simply do (assuming you have properties for both tableViews):
if (tableView == self.outerTableView){
// ... do stuff for outer tableView
} else if (tableView == self.innerTableView) {
// ... do stuff for inner tableVIew
}
I am assuming here that you have only one cell with one tableView in it. If you have more cells with a tableView in it, the idea can stay the same, except that with many cells with tableViews there is surely a better place to handle the tableViewCallbacks than in the viewController of the outer tableView.