I have in my View a long UIScrollView (about 1000 px in height), and at the end of this UIScrollView I have a UITableView.
The cellForRowAtIndexPath is never called (surely i checked the delegate and datasource if they are connected right, and the IBOutlet of the table is strong) but numberOfRowsInSection is getting called.
I tried reloading the TableView when the UIScrollView scrolls so when the table is at focus the cellForRowAtIndexPath might get called, but with no luck.
Did anyone encounter a similar behaviour when trying to use tableview and scrollview together?
Your hierarchy is like this:
A parentView is there. Inside the parent view there is a scroll view and there is a table view. So, your tableview is somewhere at 1000 from origin of parentview.
So, tableview will never become visible to your parentview and no delegates will be fired.
Include your view as a headerView of your UITableView like that:
Update for 2020, swift 5.X. To create a custom UITableView that allows your tableview inside a scrollview!
1) Create a subclass of UITableView:
import UIKit
final class ContentSizedTableView: UITableView {
override var contentSize:CGSize {
didSet {
invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
layoutIfNeeded()
return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
}
}
2) Add a UITableView to your layout and set constraints on all sides. Set the class of it to ContentSizedTableView.
3) You should see some errors, because Storyboard doesn't take our subclass' intrinsicContentSize into account. At runtime it will use the override in our ContentSizedTableView class
Related
I have a custom uitableviewcell that has an embeded child view controller. This child view controller uses autolayout and contains another uitableview. I'm trying to render the cell so that the child view controller's tableview is exactly the height of the contents.
I know that you can do that by setting tableview height constraint equal to the contentsize.height
but since it's in a tableviewcell, there is already an encapsulated height calculated. How do I force the cell to resize with the new child view controller's uitableview updated height constraint?
Try to Use AutoHeight TableView inside your custom cell instead of child View Controller.
Set scrolling and jumping property to false of AutoHeight Table.
final class AutoHeightTableView: UITableView {
override var intrinsicContentSize: CGSize {
self.layoutIfNeeded()
return self.contentSize
}
override var contentSize: CGSize {
didSet{
UIView.performWithoutAnimation {
self.invalidateIntrinsicContentSize()
}
}
}
}
I have an issue at the moment I am trying to put two table views inside a scrollview in one controller and these tableview are placed one below another. these two tableview uses scrollview for scrolling.
so I used vertical stackview inside scrollview. but when I create cell, both tableview height is not increases as well as scrollview is not able to scroll.
How should i use scrollview scroll for scrolling tableview?
-- scrollview
-----VerticalStackView
--------Tableview 1
--------Tableview 2
I'm really lost with this.Any help will be greatly appreciate it.
You need to make each UITableView define it's own size based on their content. To do that subclass both of them using the class below.
final class ContentSizedTableView: UITableView {
override var contentSize:CGSize {
didSet {
invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
layoutIfNeeded()
return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
}
}
Then, for each UITableView you need to set isScrollEnabled = false. Otherwise their defined size will be 0.
Then just add each table view to the stack view you're using inside the scrollview. If their combined height is larger than the screen height, it'll scroll.
I am trying to zoom in and out a TableView. The TableView is in a View which is inside a ScrollView. The TableView is scrollable but the pinch to zoom isn't working like it works with ImageView.
I would really appreciate if anyone could shed some light to this problem and share a working example.
I have already tried setting min and max zoom for UIScrollView in attribute inspector.
You can do that by:
first you have to make your table view content size intrinsic by make it subclass the below class.
class IntrinsicTableView: UITableView {
override open var contentSize: CGSize {
didSet{
invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize{
return contentSize
}
}
Then you will stop scrolling of your table view from the storyboard.
Then you will configure scroll view to enable zooming.
That's it.
I'm trying to put a UIView (banner) on top of the list (tableView), so the UIview will not disappear when the user scrolls down the list.
I tried this code, but didn't work.
override func viewDidLayoutSubviews() {
self.view.addSubview(banner)
banner.frame.size.width = self.view.frame.size.width
}
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
var rect = self.banner.frame
rect.origin.y = max(0,scrollView.contentOffset.y + scrollView.contentInset.top)
self.banner.frame = rect
}
Any advice how to fix it? Thank you
Instead of trying to keep the view within the scrollView, a much easier method would be to use a standard UIViewController with a UIView attached to the top using AutoLayout with constraints and UITableView attached to the bottom of the UIView and the bottom of the UIViewController.
With this layout, only your smaller tableView would be scrolling and your UIView would be stationary in place, outside the scope of the scrolling UITableViewCells.
If you are currently using an UITableViewController, you'll need to remove the override modifiers from your tableView methods, make your UIViewController implement UITableViewDataSource and UITableViewDelegate, then attach the delegates either in code or storyboard.
Your new UIViewController would look like this at the top:
class MyController: UIViewController, UITableViewDataSource, UITableViewDelegate {
...
}
I have a UITableViewController embedded in a UIView container, which is at the bottom of a UIScrollView in a UIViewController. Here is a screenshot of the current configuration in the storyboard.
The UITableView will contain responses to the selected post. Because the height and number of responses in the UITableView will be variable, I want the UIView container's height to change based on the height of the table. The current (undesirable) behavior is the UIView container stays a constant height, and scrolls when the UITableView height is greater than the UIView containter's height.
The most viable method seems to be having the UITableViewController pass the height of the table to the UIViewController using prepareForSegue, and then set the UIView's height to that passed value. However, I can't seem to set a value with the height of the table until after prepareForSegue is run.
What Isn't Working
Set the identifier of the embed segue between the UIView and the UITableViewController to "embedSegue"
At the top of the the embedded UITableViewController class, create a variable to hold the height of the table:
var tableHeight: CGFloat!
Still in the embedded UITableViewController, override viewDidLoad like so, printing passedHeight to the console for checking:
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.estimatedRowHeight = 68.0
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableHeight = self.tableView.contentSize.height
print(tableHeight)
}
In the UIViewController class that contains the UIView container, create a variable to hold the value passed from the UITableViewController:
var viewHeight: CGFloat!
Still in the UIViewController, override prepareForSegue like so, setting viewHeight to the passed tableHeight value, and printing viewHeight to the console for checking:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "embedSegue" {
let responseTableView = segue.destinationViewController as! ResponseViewController
self.viewHeight = responseTableView.tableHeight
if viewHeight == nil {
print("Nil")
} else {
print(viewHeight)
}
}
}
When I run the app, viewHeight prints as Nil first, then tableHeight prints, which means prepareForSegue has run prior to tableHeight being set.
I have also tried other methods besides prepareForSegue, including calling various functions on the UIView container in viewDidLayoutSubviews() like:
.sizeThatFits()
.needsUpdateConstraints()
.layoutIfNeeded()
However, the UIView container remains the same height as set in the storyboard.
As an epilogue, this is my first StackOverflow post, and I'm excited to be joining the community. Please do let me know if I can clarify my question. Thank you for taking the time.
Instead of using a UIViewController with a UIScrollView containing three UIViews, I created one UITableView with three custom cells. Each cell has their own custom UITableViewCell class for flexibility.
This meant I lost the ability to use constraints to dynamically change the height of each section. I wanted the Post Title and Post Text to be centered on a fullscreen image. To achieve this, I added the logic below:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == 0 {
//Fullscreen image cell - the "20" is for the status bar
return tableView.frame.size.height - self.navigationController!.navigationBar.frame.size.height - 20
} else {
//Just use the current rowHeight
return self.tableView.rowHeight
}
}
References
How to embed a UITableView in a UIScrollview
A short answer to a similar question which sparked the idea
UITableview with more than One Custom Cells with Swift
Detailed explanation of how to create a UITableView with 3 custom UITableViewCells