Change UIView height dynamically - ios

I'm trying to allow the height of the subview (the white box inside the view. The view controller swift file is a separate XIB file) depending on the amount of content in it. How do I do this?
This is what I have so far for it:
#IBOutlet weak var myScrollView: UIScrollView!
#IBOutlet weak var myContentView: UIView!
override func viewDidLayoutSubviews()
{
let scrollViewBounds = myScrollView.bounds
let containerViewBounds = //I am not sure how to do the rest
}

The best way to achieve this is to use autolayout. You have great tutorail here:
http://www.raywenderlich.com/50317/beginning-auto-layout-tutorial-in-ios-7-part-1
If you don't want to use it, set reference for your view inside your view controller for that view, and use various functions to calculate height. There are several ways for labels ( Adjust UILabel height to text ), text field( How to set UITextField height? ), etc.

Related

Clear placeholder text from storyboard or XIB outlets

In my XIB file and storyboards I have some UILabel's with placeholder text that I would like to clear out before the view loads.
Is there some function provided by the SDK for this purpose?
What is best practice for doing this?
You need to connect each UILabel to correspond IBOutlet variable in your code and change the text of it on early stage of view's lifecycle.
#IBOutlet weak var someLabel: UILabel! // connected in xib
override func viewDidLoad() {
someLabel.text = ""
}

Using a Custom xib in UISTackView

I'm trying to make my life easier by only building one xib to reuse rather than building three views to put into a stackView
I have created my custom xib file and connected it its own custom class:
The labels, and images are placed by constraints. I want the labels to be able to auto resize, up to three lines, so the height constraints for the labels are >=, as well as the Content View which also can scale in height (>=)
The UserReview code:
class UserReview: UIView {
#IBOutlet weak var userImage: UIImageView!
#IBOutlet weak var username: UILabel!
#IBOutlet weak var userRating: UILabel!
#IBOutlet weak var reviewText: UILabel!
#IBOutlet weak var prosText: UILabel!
#IBOutlet weak var consText: UILabel!
class func instanceFromNib() -> UIView {
return UINib(nibName: "UserReview", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! UIView
}
func setUp(review: Review){
// TODO set userImage
username.text = review.username!
// TODO add rating + color
reviewText.text = review.content!
if let pros = review.positive_points {
prosText.text = pros
} else {
prosText.text = "No Positive Points"
}
if let cons = review.negative_points {
consText.text = cons
} else {
consText.text = "No Negative Points"
}
}
}
The StackView where i am trying to add subViews to also has a height constraint of >= 200 (min one card) but does not seem to resize with more cards added. The Alignment is Fill and Distribution: Equal Spacing
I have tried playing around with the constraints and alignment properties for the StackView containing reviews but the closest i can come to is overlapping Views..
The way i create and add views to the stack view:
let review1 = UserReview.instanceFromNib() as! UserReview
let review2 = UserReview.instanceFromNib() as! UserReview
let review3 = UserReview.instanceFromNib() as! UserReview
self.reviewStack.addArrangedSubview(review1)
self.reviewStack.addArrangedSubview(review2)
self.reviewStack.addArrangedSubview(review3)
From what i understand from this stack question
The StackView has issues with the view height?
I have tried most of the suggested solutions but encountering different issues..
The result i am trying to get:
(The images are gone for some reason, will check that later.)
First of all remove height constraint from UIStackView because StackView always expands it's height based on the views inside it.
Set all the 4 sides constraints of StackView to it's superview and set intrinsic size as place holder.
Now add your UIView to stack view in the same manner you are doing it now. Do not set height constraint to any UIView label and the UIView itself. Just make sure yo have set top constraint of top most element and bottom constraint of bottom element. This ways auto layout understand how to increase height of all the elements based on their constraints and content.
For detailed understanding you can follow my answer at https://stackoverflow.com/a/57954517/3339966

Can UITableView scroll with UICollectionView inside it?

I have the structures below...
I wrap two of collection views into tableview
One is in tableview header(Collection1), another is in tableview 1st row(Collection2).
All the functions are good (Both collection view).
just...
When I scroll up in Collection2, Collection1 will Not scroll up together, because I'm only scrolling the collectionViews not the tableview.
It only scroll together when I scroll in Collection1.
Is it possible to make the header view scroll with user just like app store's index carousel header?
Or I just went to the wrong place, I should use other ways to approach.
Solution
When you keep CollectionView1 as a TableViewHeader, CollectionView1 will always on the top of TableView after it reaches top. If you want Collection1 and Collection2 scroll up together, you need to keep CollectionView1 in a cell, not a header.
Make sure CollectionView2 content height smaller or equal to TableViewCell's height. As I checked on App Store, they always make SubCollectionView content height equal to TableViewCell's height (If they use TableView).
Result
For more detail, you can take a look at my sample project
https://github.com/trungducc/stackoverflow/tree/app-store-header
Problem
1) Your tableview cell Collectionview (let's say collection2) , Collection 2 is scrollable. So when you scroll up tableview won't scroll up
Solution
1) Just simple and working solution would be height constant , You have to give height constant to the collection2 with >= relationship and 0 Constant value and 750 priority !!
Now the question is how to use this
You need to take IBOutlet of Height constant to your custom tableview cell and need to manage the collectionview height from there.
Here is example
class FooTableViewCell: UITableViewCell {
static let singleCellHeight = 88;
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var descriptionLabel: UILabel!
#IBOutlet weak var iconsCollectionView: IconsCollectionView!
#IBOutlet weak var const_Height_CollectionView: NSLayoutConstraint!
var delegateCollection : TableViewDelegate?
var bars:[Bar] = [] {
didSet {
self.iconsCollectionView.reloadData()
iconsCollectionView.setNeedsLayout()
self.layoutIfNeeded()
let items:CGFloat = CGFloat(bars.count + 1)
let value = (items / 3.0).rounded(.awayFromZero)
const_Height_CollectionView.constant = CGFloat((iconsCollectionView.collectionViewLayout as! UICollectionViewFlowLayout).itemSize.height * value)
self.layoutIfNeeded()
}
}
override func awakeFromNib() {
iconsCollectionView.translatesAutoresizingMaskIntoConstraints = false
iconsCollectionView.initFlowLayout(superviewWidth: self.frame.width)
iconsCollectionView.setNeedsLayout()
iconsCollectionView.dataSource = self
iconsCollectionView.delegate = self
const_Height_CollectionView.constant = iconsCollectionView.contentSize.height
self.layoutIfNeeded()
self.setNeedsLayout()
}
}
You can check my answer Making UITableView with embedded UICollectionView using UITableViewAutomaticDimension Very similar and 100% working
Another solution You can also take UICollectionView with sections which contain another horizontal collectionview , with this solution you don't need to manage contentsize for every cell
Hope it is helpful

Why do my UIImageView coordinates change when I update label value?

I want to move my UIImageView when a certain button is clicked. I have this code:
#IBOutlet weak var counter: UILabel!
#IBOutlet weak var indexCrow: UIImageView!
var crow = 0
#IBAction func plusButton(sender: UIButton) { // Plus Button
indexCrow.frame = CGRect(x: indexCrow.frame.origin.x + 20, y: indexCrow.frame.origin.y, width: indexCrow.frame.size.width, height: indexCrow.frame.size.height)
crow++
counter.text = String(crow)
}
If I remove the line counter.text = String(crow), my image view moves correctly, but my label does not update. If I write counter.text = String(crow) my label updates, but my image view does not move.
What I do wrong?
AutoLayout is running when you update the label and placing your image back to where it started. You have several options to deal with this. Choose one:
Turn off AutoLayout. Most don't choose this option because they want their layouts to work on multiple devices.
Create your imageView programmatically instead of in Interface Builder. If you do this, it won't be subject to AutoLayout and you can move it freely.
Place your imageView using AutoLayout constraints. Add IBOutlets to those constraints and update the constant values in code instead of modifying the frame.
When plusButton is called, store the new frame for your imageView in a property in your ViewController, and then put that frame in place in an override of viewDidLayoutSubviews which happens after AutoLayout runs.

NSLocalization + Storyboard using Swift

So this is very strange:
I created a small UIView in Storyboard, changed its color so we can see it.
I also created a button so I can make this view bigger.
What happens is it only works if I don't access NSLocalizedString. If I decomment the line it stops working.
Why is this?
class MasterViewController: UIViewController {
#IBOutlet weak var bar: UIView!
#IBOutlet weak var button: UIButton!
var integer : Int = 0
#IBAction func makeBarGrow(sender : AnyObject) {
self.integer++
//self.button.setTitle(NSLocalizedString("test \(integer)", comment : "test"), forState:UIControlState.Normal)
self.bar.frame = CGRectMake(self.bar.frame.origin.x,
self.bar.frame.origin.y,
self.bar.frame.size.width + 10,
self.bar.frame.size.height)
}
}
Thank you
When you set the label on your button, Auto Layout runs and sets the frame of your bar back to its initial value. When Auto Layout is enabled, you shouldn't adjust frame sizes. Instead, you should use size constraints like so:
Add an Auto Layout constraint on your bar that sets its width. To do this, select your bar view in Interface Builder and click the Auto Layout Pin icon |-[]-|, click the box next to Width, and set the constant to your desired initial value. Then click Add 1 Constraint at the bottom.
Add an IBOutlet to this constraint in your ViewController by Control dragging from the constraint in the Document Layout View to your code:
#IBOutlet weak var barWidth: NSLayoutConstraint!
In makeBarGrow, replace frame adjusting code with:
barWidth.constant += 10

Resources