iOS dynamic tableview to have a border around it - ios

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)
}
}

Related

How to Dynamically increase height of Two Tableview in a Scrollview

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.

Scrolling with two UITableView in a single touch

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)
}}

UIScrollView not scrolling with UITableView

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

Set Height of UIView on the basis of the content inside

I am adding an OverlayView to a Controller. I have set all the constraints to my OverlayView except the bottom constraint. I have a button at the end of my view. I am setting the size of the OverlayView as button.frame.maxY + margin. But it's not setting up the right height.
override func layoutSubviews() {
sizeToFit()
var sizeThatFits: CGSize = bounds.size
sizeThatFits.width = UIScreen.main.bounds.size.width - popupSizeHorizontalMargin
sizeThatFits.height = getStartedButton.frame.maxY + popupBottomMargin
let newFrame = CGRect(x: popupOriginX, y: bounds.midY - sizeThatFits.height/2, width: sizeThatFits.width, height: sizeThatFits.height)
frame = newFrame
}
This can be accomplished according to this [inner elements are example]
OverlayView
-> label ------> top to overlayView ,left,right
-> button -----> top to label , left , right
-> label -----> top to button , left , right , bottom to overlayView
The overlay view or outer view can calculate its height based on the size of elements inside it and their intrinsic size. Instead of specifying height constraint for overlay view or bottom constraint, add bottom constraint of overlay view to the last element inside the overlay view. This will satisfy the constraints and your overlay view will expand based on its contents.
Simply ctrl drag from your overlay view to the last inner view and select Bottom Space to Container.
You need to override intrinsicContentSize in UIView and return your custom size:
class YourCustomView: UIView {
override var intrinsicContentSize: CGSize {
var someYourSize = CGSize()
// ... calculate your size
return someYourSize
}
}
It will automatically update YourCustomView size to your custom calculated size using autolayout or when you want to update size manually via code - call invalidateIntrinsicContentSize() on YourCustomView object

Swift: UITableView increments layoutSubviews() when scrolling

I have a table view with custom cell in Swift that contains a horizontal layout UIView. I have noticed that when scrolling the correctly positioned subview in the horizontal view starts to multiply. I guess this has something to do with layoutSubviews() being called when table scrolls and the fact tableview recycles its cells when hidden and shows them when needed, but ignores currently positioned subviews..
It looks something like this
There's already a similar question from before, but it has no good answer.
UIScrollview calling superviews layoutSubviews when scrolling?
Here's the code I'm using inside my custom cell for horizontal positioning:
class HorizontalLayout: UIView {
var xOffsets: [CGFloat] = []
override func layoutSubviews() {
var width: CGFloat = 0
for i in 0..<subviews.count {
var view = subviews[i] as UIView
view.layoutSubviews()
width += xOffsets[i]
view.frame.origin.x = width
width += view.frame.width
}
self.frame.size.width = width
}
override func addSubview(view: UIView) {
xOffsets.append(view.frame.origin.x)
super.addSubview(view)
}
func removeAll() {
for view in subviews {
view.removeFromSuperview()
}
xOffsets.removeAll(keepCapacity: false)
}
}
Taken from here: https://medium.com/swift-programming/dynamic-layouts-in-swift-b56cf8049b08
Using inside custom cell like so:
func loadStops(stops:[String]) {
for stop in stops {
// just testing purposes only
let view = UIView(frame: CGRectMake(10, 0, 40, 40))
view.backgroundColor = UIColor.redColor()
stopsView.addSubview(view)
}
}
Is there a way to fix this problem and prevent the subview of being multiplied when scrolling and perhaps a better way to position subviews horizontally in a tableview cell?

Resources