Is there possible way to adjust table view width by width of biggest text that should be set in the cellTitle label?
iOS 8 , SWIFT
public override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Set the popover tableview width to be max compressed size (assumes all cells visible)
let maxWidth = tableView.visibleCells.reduce(0.0) { (currentMax, cell) -> CGFloat in
return max(currentMax, cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).width)
}
var contentSize = tableView.contentSize
contentSize.width = maxWidth
tableView.contentSize = contentSize
tableView.bounds.size = contentSize
}
Set a width auto-layout constraint to the table view.
Set an outlet from the constraint to your code (ctrl+drag, just like a view).
When you have the size of the label (if the label also has auto-layout then you will have it at viewDidLayoutSubviews) set the width to the table like so:
- (void)viewDidLayoutSubviews {
self.myTableWidthConstraint.constant = self.myLabel.frame.size.width;
[self.myTableView updateConstraints];
[self.myTableView layoutIfNeeded];
}
You should be able to do that in the size inspector.
Related
In my application I have a UITableViewController that allows preview of a photo and description to that photo, which are both contained in the UITableView's header. The description label needs to be multiline-compatible, so the lines amount is set to 0, obviously the next problem is to make the UITableView header dynamically resizable to adjust it's size to the amount of text in the description label.
The description label is set to fit it's content with self.descriptionLabel.sizeToFit()
The UITableView header view is also set to dynamically resize to fit it's contents via the widely accepted answer from this post:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let headerView = tableView.tableHeaderView {
let height = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height
var headerFrame = headerView.frame
//Comparison necessary to avoid infinite loop
if height != headerFrame.size.height {
headerFrame.size.height = height
headerView.frame = headerFrame
tableView.tableHeaderView = headerView
}
}
}
This solution resizes the UITableView header view, but for some reason gives my description label absolutely huge margins stretching up and down from the text. I highlighted my description label with self.descriptionLabel.backgroundColor = .red to be sure it's the description label that stretches and that indeed seems to be the case. I tried a multitude of other solutions, but this is the only one that actually at least resizes the UITableView header view, so I'm stuck with this at the moment.
The margins, however, are absolutely enormous and I can't find a solution to make them fit the description label text size. Any help will be greatly appreciated, because I can't get my head around it.
I added screenshots displaying the problem at the end of this post.
This is the top of the UITableView header, with the red displaying the UILabel beginning to stretch down
This is the actual text of the UILabel
And finally this is where the UILabel stretching finishes with the UIButton at the bottom. I am at a complete loss of how to fix this.
This is my header view UI in Interface Builder
And these are the detailed constraints of my description label in Interface Builder
I believe since the translatesAutoresizingMaskIntoConstraints ARE set to false for the headerView the layout is not auto adjusted once it's calculated in layoutSubviews method.
Try setting the translatesAutoresizingMaskIntoConstraints to true to set the headerView height properly as below:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let headerView = tableView.tableHeaderView {
let height = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height
var headerFrame = headerView.frame
//Comparison necessary to avoid infinite loop
if height != headerFrame.size.height {
headerFrame.size.height = height
headerView.frame = headerFrame
tableView.tableHeaderView = headerView
}
}
translatesAutoresizingMaskIntoConstraints = true
}
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
i have a scrollview which has a picture, text, button, label and then a collectionView whose number of rows is dynamic in nature. Its like collectionview will grow in height and hence the scrollview should assume collectionView height as well as other elements height to get a smooth scroll. How to achieve this using auto Layout in ios?
So my doubt is how to make a dynamic scrollview height based on a growing colelctionview or tableview height.
You can increase the height of CollectionView Height Constraint , connect Height contains to your ViewController and than .
how to connect constraint to outlet ?
let height = self.collectionView.contentSize.height;
self.heightConstraints = height;
self.scrollView.contentSize = CGSize.init(widht:self.scrollView.frame.size.width,height:height)
FOr Swift 4.2
override func viewDidLayoutSubviews() {
let heightFilterCOll = self.filterCollectionView.contentSize.height
self.filterCOllectionViewCOnstraintHeight.constant = heightFilterCOll
self.ScrollView.contentSize = CGSize(width:self.ScrollView.frame.size.width,height:heightFilterCOll + 77)
}
These methods didn't work for me. Try,
self.collectionView.reloadData()
DispatchQueue.main.async {
self.heightCollectionViewConstraint.constant = self.collectionViews.collectionViewLayout.collectionViewContentSize.height
}
I have simple UIScrollView with two subviews: UIView and UITableView set in vertical mode. Both of them have their own height constraint:
I set it like this:
tableViewHeightConstraint.constant = CGFloat(height) //height is calculated based on number of cells multiplied 130
calendarViewHeightConstraint.constant = UIApplication.shared.keyWindow!.rootViewController!.traitCollection.isIpad ? 630 : 470
But sometimes when I scroll to the bottom, and then add a new cell to the table view and recalculate height it seems that scroll of scroll view is locked, and I can bouncing but the scroll disappear and I can only bouncing, although I know that I can scroll to the content above or below the current view on the screen. What may be the reason?
I really have to do this like this. There is no possibility to put my view inside table view header view.
This is where I recalculate height:
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
tableView.endUpdates()
updateView()
updateTableViewHeight()
}
private func updateTableViewHeight() {
var height = goalFetchedResultsController.fetchedObjects!.count * 130
height += 45
if MyType.selected.hasMonthReport {
height += 130
}
if MyType.selected.hasAnnualReport {
height += 70
height += 130
}
tableViewHeightConstraint.constant = CGFloat(height)
}
New cell is added inside delegate of NSFetchedResultsController.
I'm thinking you need to change your calculation way of height of TableView like,
var height = tablView.contentSize.heigh // You can do + or - here
// your other stuff of calculation.
tableViewHeightConstraint.constant = CGFloat(height)
self.view.layoutIfNeeded() // You need to call after change constraint.
I want to set the width of custom UITableViewCell to 80% of the screen width but I know the size of the cell can be manipulated using "layoutSubviews()" methods but I don't know how.
Please help me.
The answer is too simple. Just change the frame of the cell in class.
class CustomCell: UITableViewCell {
override var frame: CGRect {
get {
return super.frame
}
set (newFrame) {
var frame = newFrame
let newWidth = frame.width * 0.80 // get 80% width here
let space = (frame.width - newWidth) / 2
frame.size.width = newWidth
frame.origin.x += space
super.frame = frame
}
}
}
class CustomTVC: UITableViewCell {
override var frame: CGRect {
get {
return super.frame
}
set (newFrame) {
var frame = newFrame
frame.size.width = UIScreen.mainScreen().bounds.width * 0.8
super.frame = frame
}
}
}
Drag and drop UIView to your content view of cell (i.e. in cell). Adjust it's height and width according to your need as you said 80% (so give padding like wise). The set top,bottom,leading and trailing constraints if you are using autolayout.
You can set your contentview's background color as clear color and cell's background as clear color as well or desired color you want. Likewise you can set your tableview's background color also!
One new available solution is to use the "inset grouped" style which Swift now offers for UITableViews. This creates an appearance with more narrow UITableViewCells like this