I am trying to implement a scrollView that contains a text field, button, and table view. I am completely lost trying to get the thing to scroll, I've tried changing the height of UITableView but that has not worked, I've tried adjusting the height of the content View and scrollView, but that has not worked either. How can I get the scrollview to scroll and adjust the size when another tableViewCell is added to the tableView?
override func viewDidLayoutSubviews() {
tableView.frame = CGRect(x: tableView.frame.origin.x, y: tableView.frame.origin.y, width: tableView.frame.size.width, height: CGFloat(tableView.numberOfRows(inSection: 0) * 120))
tableView.reloadData()
}
#IBAction func addExercisePressed(_ sender: Any) {
test.append("nice")
tableView.reloadData()
tableView.frame = CGRect(x: tableView.frame.origin.x,y: tableView.frame.origin.y ,width: self.view.frame.size.width, height: CGFloat(test.count * 120))
scrollView.frame.size = CGSize(width: self.view.frame.size.width, height: tableView.frame.size.height)
}
Please dont use tableView inside a scrollView, tableView is subclass of scrollView and that's mean tableView already have scroll function
your answer to set
tableHeight.constant = tableView.contentSize.height
It will make recycle/dequeue cell function useless because tableView will show all the cell immediately, tableview will call cellForRowAt for all indexes that showed in tableview viewport
UITableview inside Scrollview call cellforrow too many times
Here why we use dequeueReusableCellWithIdentifier
From what I see you want something like this right
you can check this repo how I only use a tableview to achieved that
please note that tableHeaderView is scrollable, sectionHeaderView is sticky
All I needed was to set a height constraint for the TableView and connect that via IBOutlet, then this line of code wherever reloading table data is needed
tableHeight.constant = tableView.contentSize.height
Related
I have weird design scenario where I have used two UITableviews - one at the top and another at the bottom, The top one is inside the cell of and other one.
Initially, both the Tableview's scroll is enabled.
Only if the top Tableview moves upward then I am disabling the scroll of the top tableview so that the bottom one scrolls.
tableView1.isScrollEnabled = false
It works but not in a single touch. I have to remove the first touch first then only in the second touch the bottom Tableview scrolls.
Is there any way so that I can make scrollable to the bottom tableview in a single touch?
Thanks in advance!
You can take both the UITableView in a UIScrollView and assign the following class to both the UITableView.
You don't need to play with the isScrollEnabled property.
Remember to give the intrinsic size to tableView as well
class DynamicTableView: UITableView {
override var contentSize:CGSize {
didSet {
if contentSize == CGSize(width: UIScreen.main.bounds.size.width, height: 0.0) {
self.separatorStyle = .none
contentSize = CGSize(width: UIScreen.main.bounds.size.width, height: 50.0)
} else {
self.invalidateIntrinsicContentSize()
}
}
}
override var intrinsicContentSize: CGSize {
self.layoutIfNeeded()
return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
}}
I am creating a dynamic height TableViewCell based on the contents of the Cell. I would like to create a custom separator between the cells. I have the following code in the TableViewCell swift file. It appears that the custom separator is created using the default height of the cell and not the calculated height of the cell based on the contents of the cell - which was calculated in the TableView heightForRowAt override function. As a result, the customer separator is rendered across the cell. It appears that the awakeFromNib is called before the height calculation. Any suggestions?
class FeedTableViewCell: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
// add a custom seperator between table view cells.
let screenSize = UIScreen.main.bounds
let separatorHeight = CGFloat(10.0)
let additionalSeparator = UIView.init(frame: CGRect(x: 0, y: self.frame.size.height-separatorHeight, width: screenSize.width, height: separatorHeight))
additionalSeparator.backgroundColor = UIColor(named: "TEXTVIEWCELL_SEPARATOR")
self.addSubview(additionalSeparator)
}
}
The awakeFromNib is called before the height calculation. While the solution works for fixed height TableViewCells, it won't work for variable height TableViewCells. The solution that I used was to create a view on the bottom of the TableViewCell, use constraints to pin it to the bottom of the TableViewCell. You can size the view to 10pt and of course set the color. I did this in StoryBoards, not programmatically.
I am having a tableview in which the row height is dynamic as per its UILabel content (using UITableViewAutomaticDimension). Now, I need a 15 point border around the table view, that also changes as per the tableview height.
I tried two approaches -
Took a UIView and placed the tableView on top of it with constraints
as 15 on each side (top, bottom, left and right).
Added four UIViews around the tableView with 0 constraint for each
view to the tableView. (so that the views are always attached to the
tableView).
In both the approaches, the bottom view (or bottom area) is always giving a space in towards tableView bottom.
And to achieve the dynamic height to the tableView, I am using the below code -
open override func viewDidLayoutSubviews() {
if isPopup! {
tableView.frame = CGRect(x: tableView.frame.origin.x, y: tableView.frame.origin.y, width: tableView.frame.size.width, height: tableView.contentSize.height + 190)
tableView.reloadData()
}
}
Here are my Storyboard and the result on the simulator -
How to make the bottom UIView always be attached with the tableView bottom, so it looks like a border around the tableView?
Use your first approach and a custom table view subclass that uses its contentSize to determine its height. That way you can remove the code in your viewDidLayoutSubviews and should be good to go.
class AutoHeightTableView: UITableView {
override var contentSize: CGSize {
didSet {
invalidateIntrinsicContentSize()
}
}
override var intrinsicContentSize: CGSize {
return CGSize(width: UIView.noIntrinsicMetric,
height: contentSize.height)
}
}
I have a SegmentedControl on a Cell at the top of my tableView (the tableView consists of all static cells)...I want the top cell (and segmentedControl) to "stick" so that it is always visible as a user scrolls through the table (see screenshot below). Is this possible?
Usually, for applying this behavior you should add it as a header view instead of a cell. Header views in table view does "stick". But since you are adding static cells (UITableViewController), even if you tried to add a header view to the table view it won't apply the sticking behavior.
As a workaround you might need to add a new UIViewController contains a view on the top (the header view) and a container view, as follows:
The one hackish solution which pops to my mind is:
Declare header in your VC, or hold the reference:
private var header: UIView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 40))
Add it as a subview of tableView and set content inset equal to height of the header.
tableView.addSubview(header)
tableView.contentInset.top = header.frame.height
If your header use autolayout you will need to call
view.layoutIfNeeded() before setting content inset
and then for header to stick always to the top of tableView:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
header.frame.origin.y = scrollView.contentOffset.y
}
I have a scrollview that contain some element (uiimage, webview ,...)
in buttom of scrollview add tableview (comments list). Problem: although tableview is part of scrollview, but scrollview scroll separate and tableview scrolling separate!
I want at the end of scrollview and start tableview scrollview scrolling tableview and tableview scroll disabled.
I used it code:
Swift:
override func intrinsicContentSize() -> CGSize {
self.layoutIfNeeded()
return CGSizeMake(UIViewNoIntrinsicMetric, contentSize.height)
}
Objective C:
-(CGSize)intrinsicContentSize{
[self layoutIfNeeded];
return CGSizeMake(UIViewNoIntrinsicMetric, contentSize.height)}
but don't work.
thanks for help
That happens because it is the behavior of having a table view inside a scroll view. That should be happening.
Solution: Destroy the scrollView, and implement a tableView with a header view, wish that header view it will be the view with uiimage, webview etc... and the tableView it will be your comments. This is the best way of implementing what you want, that is if i understood right what you actually want.
Adding a header to a table view example:
self.tableView.tableHeaderView = topView // where top view is the view wish contains your uimage, buttons etc...
Avoid bounce of ScrollView when we scroll the tableview. I have added the below line of code.It worked for me.
self.scrollView.delegate = self
scrollView.contentSize = CGSize(width: self.view.frame.width, height: 500)
scrollView.showsVerticalScrollIndicator = true
scrollView.tag = 1
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if scrollView.tag != 1 {
self.scrollView.bounces = false
}
}
Thanks