swift: adding uistackView with UITextField of same height - swift

I have a vertical StackView with Distribution "Equal Spacing"
containing horizontal StackViews each containing a Switch and a label except the last one, which contains a Switch and a TextField.
Now, when the Switch of that last one is turned on, I want to add an additional horizontal StackView to the vertical one which looks like the last one:
#IBAction func onValueChange(_ sender: UISwitch) {
let parent = sender.superView as! UIStackView
let pparent = parent.superView as! UIStackView
let textField = parent.arragedSubviews[1] as TextField
let row = UIStackView
row.axis = UILayoutConstraintAxis.horizontal
row.spacing = 30
let swtch = UISwitch()
swtch.isOn = false
let input = UITextField()
input.borderStyle = textField.borderStyle
row.addArrangedSubView(swtch)
row.addArrangedSubView(input)
pparent.addArrangedSubView(row)
}
it works quite well, except the new row is smaller in height and therefore the textfield is also smaller in height, which looks stupid. I didn't put any restraints on the horizontal StackViews. What should I do?

Use .fillEqually instead of .equalSpacing to make sure that the rows in the stackView would equal in height.

Related

iOS - Constraint to UIImage with centrally aligned UILabel's text

I have UITableViewCell that has a UIlabel aligned center I'm setting image in default imageView property of the UITableViewCell but since text is aligned center there is a gap between text and the image.
I want image then little space then text all center to UITableViewCell I have tried following code,
cell.imageView?.image = image
cell.imageView?.translatesAutoresizingMaskIntoConstraints = false
cell.imageView?.centerYAnchor.constraint(equalTo: label.centerYAnchor).isActive = true
let rect: CGRect = label.textRect(forBounds: label.bounds, limitedToNumberOfLines: 1)
cell.imageView?.leadingAnchor.constraint(equalTo: label.leadingAnchor, constant: rect.origin.x - padding).isActive = true
That works for me but when I switch device from iPhone 11 Max Pro to iPhone 8 image overlaps the text because label.textRect always brings the same text irrespective of screen size
I have also tried using range of the first later and using it's rect but same problem of not being changed per screen size.
Can this be achieved without putting custom UIImageView in UITableViewCell?
You could use a stackView that you center inside your cell and add your imageView and your label as arranged subViews. Note that you would need to create a custom cell.
Create your stackView:
let stackView: UIStackView = {
let stackView = UIStackView()
stackView.axis = .horizontal
stackView.alignment = .center
stackView.distribution = .fill
stackView.spacing = 10 // You can set the spacing accordingly
return stackView
}()
Layout as follows:
contentView.addSubview(stackView)
// Swap these two lines if instead you want label then image
stackView.addArrangedSubview(image)
stackView.addArrangedSubview(label)
// StackView
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor).isActive = true
stackView.centerXAnchor.constraint(equalTo: self.contentView.centerXAnchor).isActive = true

UIStackView, Autolayout, Table Cells

I'm creating a UIStackView with an image and a label in a custom UIControl that will be in a custom UITableViewCell, except that my UIStackView has a height & width of 0 and XCode is complaining about breaking constraints. Only if I explicitly set a height and width does it show properly, which I don't want because the label text varies from cell to cell. (This is all happening programmatically.)
The Setup
In my UITableViewCell, I've got the following:
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(control)
NSLayoutConstraint.activate([
control.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
control.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
control.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
control.topAnchor.constraint(equalTo: contentView.topAnchor),
])
}
// empty coder init as well
private let control: MyControl = {
let control: MyControl = MyControl()
control.translatesAutoresizingMaskIntoConstraints = false
return control
}()
In MyControl, I just have the UIStackView, a UIImageView, and a UILabel. To not bore you with code...only the UIStackView (horizontal axis) is using constraints, pinning it to the four sides. The UIImageView (initiated with an image) is one arranged subview, the UILabel is the other (initiated with default text).
If you want to see the code:
class MyControl: UIControl {
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(stackView)
stackView.addArrangedSubview(icon)
stackView.addArrangedSubview(contentLabel)
NSLayoutConstraint.activate([
stackView.bottomAnchor.constraint(equalTo: bottomAnchor),
stackView.leadingAnchor.constraint(equalTo: leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: trailingAnchor),
stackView.topAnchor.constraint(equalTo: topAnchor),
])
}
// empty coder init as well
private let contentLabel: UILabel = {
let label: UILabel = UILabel()
label.text = "Initial text"
return label
}()
private let icon: UIImageView = {
let iv: UIImageView = UIImageView(image: UIImage(named: "placeholder_image")!)
iv.contentMode = .scaleAspectFit
return iv
}()
private let stackView: UIStackView = {
let stackView: UIStackView = UIStackView()
stackView.axis = .horizontal
stackView.translatesAutoresizingMaskIntoConstraints = false
return control
}()
}
What I'm Expecting
I'm expecting the UIControl to be the height of the image (because it's taller than the label text), and the width of the image + the label text. (And then display full table cell width because of that constraint pinning). And because these are set on initialization of these components, I'd expect them to have an intrinsic height and width to pass to the UIStackView.
What I'm Getting
A height and width of zero, and XCode complaints of broken constraints. If I remove all constraints, I get no complaints but nothing appears (as if the height & width are zero but XCode doesn't care because I didn't set any constraints).
What I've Tried
Literally every combination of layout constraints, including none on everything and as many as I can on everything. What I'd like is for the image + label text to set the height and width of the UIStackView which would then set the height and width of the UIControl, which would then set the height in the UITableViewCell (I know I have width 100% - that will change later).
Other Considerations
There's nothing else special about my UITableViewCell that would cause any issue here except that in my actual code, I have a multi-line label above MyControl which should (and does) cause my UITableViewCell to expand in height.
The problem with your question is that so much of the code you've shown is bogus that it's hard to guess what you might actually be doing. You claim that in your table view cell (I presume it's a table view cell subclass) you are saying
override init(frame: CGRect) {
super.init(frame: frame)
But that would never compile, as init(frame:) is not the designated initializer for a UITableViewCell. You have code like this:
private let contentLabel: UILabel = {
let label: UILabel = UILabel()
label.text = "Initial text"
return label
}
But that would never compile, as a function is not a label.
If we make allowances for all of that and fix your code, it's difficult to see what you would be doing wrong. I corrected your code so that it would compile, and I got this in my table view:
That might not be exactly what you were after, but the image view is certainly sizing the cells to its own height.
What you are doing is not at all how one makes and configures a table view cell (you should be doing the work in cellForRowAt, not hard coding the cell's image view and label contents in the cell's initializer), but given what you've shown, the image view does size the stack view which does size the cell (contrary to my own initial expectations).
Another issue is that you can't put an image view and a label into an autolayout situation without resolving the ambiguity as to which should predominate. I added this line to do that:
iv.setContentHuggingPriority(.defaultLow+1, for: .horizontal)

How to programmatically set the constraints of the subViews of a UIPageViewController?

I have contained the subViews of a UIPageViewController within a UIView so that my screen has a partial scrollView container. However, the subViewControllers extend beyond both, the UIView that is supposed to contain the (horizontal/swiping page style) scrollView and the screen of the device.
I have already tried to use autolayout constraints but the subViews still go beyond the device screen.
Here is the UIView that contains the subViews of the UIPVC:
let pagingContainer: UIView = {
let view = UIView()
view.backgroundColor = .white
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
and here is the set up within viewDidLoad():
let pageController = PageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal)
addChild(pageController)
pageController.didMove(toParent: self)
pagingContainer.addSubview(pageController.view)
In case I haven't articulated properly:
What I wish for to happen is that the bottom half of my screen is a horizontal-page-style swiping scrollView that contains x number of subViewControllers (under UIPVC), and the size of subViewControllers are limited to the size of the UIView(pagingContainer).
I think I might understand what you're asking.
It should be pretty simple, set your left/right/top/bottom constraints for the pageController.view to be equal to the pagingContainer
In my example, I'm using SnapKit, so I set the edges equal to superview (which is the paingContainer).
let pageController = PageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal)
self.addChild(pageController)
pageController.didMove(toParent: self)
pagingContainer.addSubview(pageController.view)
// I set up constraints with SnapKit (since I mostly use that pod)
pageController.view.snp.makeConstraints({ (make) in
make.edges.equalToSuperview()
})
// But if I remember correctly, you can also set it like so:
pageController.view.translatesAutoresizingMaskIntoConstraints = false
pageController.view.widthAnchor.constraint(equalTo: self.pagingContainer.widthAnchor).isActive = true
pageController.view.heightAnchor.constraint(equalTo: self.pagingContainer.heightAnchor).isActive = true
pageController.view.centerXAnchor.constraint(equalTo: self.pagingContainer.centerXAnchor).isActive = true
Here is a quick gif of what it looks like. Main view controller only has red background and a pagingContainer on the bottom half and inset of 30 on each side (to demonstrate the size of pageController being within the pagingContainer and not overflowing)

Snapkit centerY constraint centers item above the center Y axis

I'm trying to make a custom UICollectionView cell class. The cell consists of a content view and a label. I want the label to be in the center of the view, horizontally and vertically, but instead the label is placed above the content view's center y axis.
I've made sure that the constraints are set, no other constraints are being set, and that the issue affects all views in the content view (I added another view and set its center Y axis as a test, and that also didn't work). I also set the content view and the label's background colors to be contrasting, and have confirmed that the label is not lying on the content view's center y anchor.
Here is how I set the consraints:
label.snp.makeConstraints{make in
make.centerX.centerY.equalToSuperview()
}
Here is what I get instead. Clearly the label is not centered vertically. You can see the blue UIView, which I added as a test, is also not centered vertically.
I used to add my constraints programmatically in this way
self.view.addSubview(image)
image.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
image.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
image.heightAnchor.constraint(equalToConstant: 30).isActive = true
image.widthAnchor.constraint(equalToConstant: 30).isActive = true
and my image is declarated in this way
let image: UIImageView = {
let theImageView = UIImageView()
theImageView.image = UIImage(named: "ico_return")
theImageView.translatesAutoresizingMaskIntoConstraints = false
return theImageView
}()
Hope it helps
Can you try Following Code.
class FilterCollectionViewCell: UICollectionViewCell {
let labelTemp = UILabel()
override func awakeFromNib() {
labelTemp.backgroundColor = .white
labelTemp.textColor = .black
labelTemp.text = "testing"
self.contentView.addSubview(labelTemp)
labelTemp.snp.makeConstraints { (make) in
make.centerX.centerY.equalTo(self.contentView)
}
}
}
Fast and easy:
myLabel.snp.makeConstraints { (make) in
make.center.equalTo(self.topView.snp.center)
}

Add border to CollectionView

I have a collection view with multiple cells in it, I figured out how to add a border to each cell but still stuck with adding a border to the CollectionView (expected Result).
Currently, I'm placing the button outside the CollectionView but don't know how to make it looks like the expected result.
For set the collection view border you can follow this
collectionView.layer.borderColor = UIColor.gray.cgColor
collectionView.layer.borderWidth = 5
And for setting cell position to the middle you need to set the cell insect.
You can easily set the cell insect from storyboard from this. Update the Section Insects value that you want.
you can try like this:
#IBOutlet var CollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
CollectionView.delegate = self
CollectionView.dataSource = self
CollectionView.layer.borderColor = UIColor.gray.cgColor //change to required color
CollectionView.layer.borderWidth = 5 //change to required borderwidth
}