AutoLayout constraints for programmatically added buttons in a scrollView - ios

I'm struggling with making autolayout work for a horizontal scrollview populated with an unknown number of buttons (in this case the number is stored in sceneCount).
I've tried to approach the problem in other ways as well, but this seems to be the closest I could get to a result (no contradictory constraints). Unfortunately I only get a white screen at runtime with no errors.
This is how I wish my scrollView would look like.
Hope you guys can spot the problem!
import UIKit
class ViewController: UIViewController {
let sceneCount = 4
var button = UIButton.buttonWithType(UIButtonType.System) as! UIButton
var buttons: [UIButton] = [UIButton]()
func makeLayout(){
//Make the content view
let view1 = UIScrollView()
view1.setTranslatesAutoresizingMaskIntoConstraints(false)
view1.backgroundColor = UIColor.redColor()
//Make the scroll view
let view2 = UIScrollView()
view2.setTranslatesAutoresizingMaskIntoConstraints(false)
view2.backgroundColor = UIColor(red: 0.75, green: 0.75, blue: 0.1, alpha: 1.0)
view.addSubview(view1)
view2.addSubview(view1)
//Create the buttons
for i in 0...(sceneCount-1) {
button.setTranslatesAutoresizingMaskIntoConstraints(false)
button.addTarget(self, action: Selector("scene\(i)Pressed"), forControlEvents: UIControlEvents.TouchUpInside)
button.setBackgroundImage(UIImage(named: "Scene\(i+1)"), forState: UIControlState.Normal)
button.sizeThatFits(CGSizeMake(40, 40))
buttons.append(button)
view1.addSubview(button)
}
//set horizontal spacing between the buttons
for i in 1...(sceneCount-2) {
var button1 = UIButton.buttonWithType(UIButtonType.System) as! UIButton
var button2 = UIButton.buttonWithType(UIButtonType.System) as! UIButton
button1 = buttons[i - 1]
button2 = buttons[i]
var dictionary1 = [String: UIButton]()
dictionary1.updateValue(button1, forKey: "scene1")
dictionary1.updateValue(button2, forKey: "scene2")
view1.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[scene1]-[scene2]", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary1) as [AnyObject])
}
//set vertical spacing for all buttons
for i in 0...(sceneCount-1) {
var button1 = UIButton.buttonWithType(UIButtonType.System) as! UIButton
button1 = buttons[i]
var dictionary2 = [String: UIButton]()
dictionary2.updateValue(button1, forKey: "button1")
view1.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[button1]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary2) as [AnyObject])
}
//set horizontal distance to container for first button
if sceneCount > 0 {
var buttonFirst: UIButton = buttons[0]
var dictionary3 = [String: UIButton]()
dictionary3.updateValue(buttonFirst, forKey: "buttonFirst")
view1.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[buttonFirst]", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary3) as [AnyObject])
}
//set horizontal distance to container for last button
if sceneCount > 0 {
var buttonLast: UIButton = buttons[sceneCount-1]
var dictionary4 = [String: UIButton]()
dictionary4.updateValue(buttonLast, forKey: "buttonLast")
view1.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[buttonLast]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary4) as [AnyObject])
}
}
override func viewDidLoad() {
super.viewDidLoad()
makeLayout()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}

I managed to make your code work with three major changes as follows:
1 - Your content view needs to be of type UIView
let view1 = UIView()
This view will hold a UIScrollView (view2) and they have to have their constraints set. On view1 you will be able to set the size of the scroll view, that's why I made view 2 with 0 distance from the super view.
view1.addSubview(view2)
var dictionary = [String: UIView]()
dictionary.updateValue(view1, forKey: "view1")
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[view1]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary) as [AnyObject])
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[view1]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary) as [AnyObject])
dictionary = [String: UIView]()
dictionary.updateValue(view2, forKey: "view2")
view1.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[view2]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary) as [AnyObject])
view1.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[view2]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary) as [AnyObject])
2 - As you were using the same reference to create new buttons, the final array would have the same button in every position.
I moved the initialization of each button inside the for that creates buttons.
var button = UIButton.buttonWithType(UIButtonType.System) as! UIButton
view2.addSubview(button)
3- After that I just updated your constraints to be inserted between the buttons and the scroll view (view2).
And here is the final code:
import UIKit
class ViewController: UIViewController {
let sceneCount = 4
var buttons: [UIButton] = [UIButton]()
func makeLayout(){
//Make the content view
let view1 = UIView()
view1.setTranslatesAutoresizingMaskIntoConstraints(false)
view1.backgroundColor = UIColor.redColor()
//Make the scroll view
let view2 = UIScrollView()
view2.setTranslatesAutoresizingMaskIntoConstraints(false)
view2.backgroundColor = UIColor(red: 0.75, green: 0.75, blue: 0.1, alpha: 1.0)
view.addSubview(view1)
view1.addSubview(view2)
var dictionary = [String: UIView]()
dictionary.updateValue(view1, forKey: "view1")
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[view1]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary) as [AnyObject])
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[view1]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary) as [AnyObject])
dictionary = [String: UIView]()
dictionary.updateValue(view2, forKey: "view2")
view1.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[view2]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary) as [AnyObject])
view1.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[view2]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary) as [AnyObject])
//Create the buttons
for i in 0...(sceneCount-1) {
var button = UIButton.buttonWithType(UIButtonType.System) as! UIButton
button.setTranslatesAutoresizingMaskIntoConstraints(false)
button.addTarget(self, action: Selector("scene\(i)Pressed"), forControlEvents: UIControlEvents.TouchUpInside)
button.setBackgroundImage(UIImage(named: "Scene\(i+1)"), forState: UIControlState.Normal)
button.sizeThatFits(CGSizeMake(40, 40))
buttons.append(button)
view2.addSubview(button)
}
//set vertical spacing for all buttons
for i in 0...(sceneCount-1) {
var button1 = buttons[i]
var dictionary2 = [String: UIButton]()
dictionary2.updateValue(button1, forKey: "button1")
view2.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[button1]-0-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary2) as [AnyObject])
}
//set horizontal distance to container for first button
if sceneCount > 0 {
var buttonFirst: UIButton = buttons[0]
var dictionary3 = [String: UIButton]()
dictionary3.updateValue(buttonFirst, forKey: "buttonFirst")
view2.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[buttonFirst]", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary3) as [AnyObject])
}
//set horizontal spacing between the buttons
for i in 1...(sceneCount-1) {
var button1 = buttons[i - 1]
var button2 = buttons[i]
var dictionary1 = [String: UIButton]()
dictionary1.updateValue(button1, forKey: "scene1")
dictionary1.updateValue(button2, forKey: "scene2")
view2.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[scene1]-[scene2]", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary1) as [AnyObject])
}
//set horizontal distance to container for last button
if sceneCount > 0 {
var buttonLast: UIButton = buttons[sceneCount-1]
var dictionary4 = [String: UIButton]()
dictionary4.updateValue(buttonLast, forKey: "buttonLast")
view2.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[buttonLast]-|", options: NSLayoutFormatOptions(0), metrics: nil, views: dictionary4) as [AnyObject])
}
}
override func viewDidLoad() {
super.viewDidLoad()
makeLayout()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}

Related

UIButton inside a UIView subclass is not working, Swift

I've seen similar SO questions, the most promising ones advised to set .isUserInteractionEnabled = true and .bringSubview(toFront: subView) however both these don't seem to work in my case (not sure if I am using it correctly). I am neither able to set the backgroundColor and border for the view.
Please advise where I am going wrong.
I would like to call a function on click of a editButton which is inside a subview.
This is what I get when I run the code:
Here is the code:
class ProfilePhotoView: UIView{
var profileImage = UIImageView()
var editButton = UIButton()
var currentViewController : UIViewController
init(frame: CGRect, viewController : UIViewController){
self.currentViewController = viewController
super.init(frame: frame)
self.isUserInteractionEnabled = true
setup()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setup(){
profileImage.image = #imageLiteral(resourceName: "profilePlaceHolder")
editButton.setTitle("edit", for: .normal)
editButton.setTitleColor(Colors.curieBlue, for: .normal)
editButton.isUserInteractionEnabled = true
editButton.addTarget(self, action: #selector(editPhoto), for: .touchUpInside)
profileImage.translatesAutoresizingMaskIntoConstraints = false
editButton.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(profileImage)
self.addSubview(editButton)
let viewsDict = [ "profileImage" : profileImage,
"editButton" : editButton
] as [String : Any]
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[profileImage]", options: [], metrics: nil, views: viewsDict))
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-10-[profileImage]", options: [], metrics: nil, views: viewsDict))
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[editButton]", options: [], metrics: nil, views: viewsDict))
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[profileImage]-10-[editButton]", options: [], metrics: nil, views: viewsDict))
}
func editPhoto(){
Utils.showSimpleAlertOnVC(targetVC: currentViewController, title: "Edit Button Clicked", message: "")
}
}
ViewController using ProfilePhotoView
class ProfilePhotoViewVC: UIViewController {
var profilePhotoView : ProfilePhotoView!
//let imagePickerController = UIImagePickerController() // Initializing imagePicker
//var imagePickerDelegate = ProfilePhotoDelegate()
override func viewDidLoad() {
super.viewDidLoad()
let profilePhotoFrame = CGRect(x: 0, y: 0, width: 300, height: 800)
profilePhotoView = ProfilePhotoView(frame: profilePhotoFrame, viewController: self)
profilePhotoView.isOpaque = false
profilePhotoView.backgroundColor = Colors.lightGrey
profilePhotoView.layer.borderWidth = 1
profilePhotoView.layer.borderColor = Colors.iOSBlue.cgColor
profilePhotoView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(profilePhotoView)
view.bringSubview(toFront: profilePhotoView)
view.isUserInteractionEnabled = true
let viewsDict = [ "profilePhotoView" : profilePhotoView] as [String : Any]
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[profilePhotoView]", options: [], metrics: nil, views: viewsDict))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-10-[profilePhotoView]", options: [], metrics: nil, views: viewsDict))
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
As soon as you set this:
profilePhotoView.translatesAutoresizingMaskIntoConstraints = false
your profilePhotoView's width and height get set to 0, and you need to specify them with constraints. Add (==300) and (==800) to your visual formats to set them:
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[profilePhotoView(==300)]", options: [], metrics: nil, views: viewsDict))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-10-[profilePhotoView(==800)]", options: [], metrics: nil, views: viewsDict))
Also, consider using NSLayoutConstraint.activate() to activate the constraints instead of adding them to the view. iOS will add the constraints to the correct views for you. Also, options has a default value of [], so you can leave that off:
NSLayoutConstraint.activate(NSLayoutConstraint.constraints(
withVisualFormat: "H:|-10-[profilePhotoView(==300)]",
metrics: nil, views: viewsDict)
)
NSLayoutConstraint.activate(NSLayoutConstraint.constraints(
withVisualFormat: "V:|-10-[profilePhotoView(==800)]",
metrics: nil, views: viewsDict)
)

I want to add list of buttons in the same line in Swift 3.0

What I want is to add list of buttons (the number come from the service) to a uiview programmatically, so I think is I have to check if the space between the last button and the end of UIView is enough to add button or I have to go to the next line? Right?
Could you please help me on that?
Thanks,
Here you go. Button added with auto layout constraints so it will work the same in all size classes :)
var lastButton : UIButton? = nil
for i in 0...5 {
let button = UIButton()
button.backgroundColor = UIColor.green
button.setTitle("Button \(i)", for: .normal)
button.sizeToFit()
button.translatesAutoresizingMaskIntoConstraints = false
if i == 0 {
let viewComponents : [String : Any] = ["button" : button]
self.view.addSubview(button)
let horizontalConstraint = NSLayoutConstraint.constraints(withVisualFormat: "H:|-(20)-[button]", options: [], metrics: nil, views: viewComponents)
let verticalConstraint = NSLayoutConstraint.constraints(withVisualFormat: "V:|-(8)-[button]", options: [], metrics: nil, views: viewComponents)
self.view.addConstraints(horizontalConstraint)
self.view.addConstraints(verticalConstraint)
self.view.layoutIfNeeded()
lastButton = button
}
else {
if (lastButton != nil) {
self.view.addSubview(button)
let viewComponents : [String : Any] = ["button" : button, "lastButton" : lastButton!]
if (lastButton!.frame.maxX + 8 + button.bounds.size.width) > self.view.bounds.size.width {
let horizontalConstraint = NSLayoutConstraint.constraints(withVisualFormat: "|-(8)-[button]", options: [], metrics: nil, views: viewComponents)
let verticalConstraint = NSLayoutConstraint.constraints(withVisualFormat: "V:[lastButton]-(8)-[button]", options: [], metrics: nil, views: viewComponents)
self.view.addConstraints(horizontalConstraint)
self.view.addConstraints(verticalConstraint)
self.view.layoutIfNeeded()
lastButton = button
}
else {
self.view.addSubview(button)
let horizontalConstraint = NSLayoutConstraint.constraints(withVisualFormat: "[lastButton]-(8)-[button]", options: [.alignAllTop], metrics: nil, views: viewComponents)
self.view.addConstraints(horizontalConstraint)
self.view.layoutIfNeeded()
lastButton = button
}
}
}
}
The idea is using UICollectionView. You can implement it with following:
Subclass UICollectionViewCell to make your own cell which has the button
Subclass UICollectionViewFlowLayout, override
layoutAttributesForItem(at indexPath: IndexPath) which provides the attributes for each cell. You may need to pre-calculate the frame of button or cell in function prepare()
Create UICollectionView instance with the collectionviewLayout you just subclassed.

Add constraints with visual format doesn't work (Swift 3.0)

I'm trying to add simple red view on my UITableViewController by adding constraints with visual format. Here is my code (calling in viewDidLoad):
private func setupMenuBar() {
let myView = UIView()
myView.backgroundColor = UIColor.red
view.addSubview(myView)
view.addConstraintsWithFormat(format: "H:|[v0]|", views: myView)
view.addConstraintsWithFormat(format: "V:|[v0]|", views: myView)
Here is my extension to UIView class:
extension UIView {
func addConstraintsWithFormat(format: String, views: UIView...) {
var viewsDictionary = [String: UIView]()
for (index, view) in views.enumerated() {
let key = "v\(index)"
view.translatesAutoresizingMaskIntoConstraints = false
viewsDictionary[key] = view
}
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutFormatOptions(), metrics: nil, views: viewsDictionary))
}
Works fine on my another empty testViewController:UIViewController without any subviews.
As you can see on the picture, here's no any red views:
App hierarchy
And at the end of the function i have zero frame:
Console

images in UICollectionViewCell of UICollectionView created programatically overlap after scrolling

enter code hereI tried creating a UICollectionView programatically in swift, Then added some images to the UICollectionViewCell (s). The display works fine but when i scroll down the view and come back up again the cells start showing images superimposed on one another(the newer ones overlap on the older ones). I read that recycling of the views happen which causes this problem. I tried a lot but could not find a solution.
I request you all to please help me find a solution
thanks
(this code can be run by adding some images with the names)
//
// ViewController1.swift
// Gridtest
import UIKit
class ViewController1: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
var collectionView: UICollectionView!
var tapStatusHolderArray: Array<Bool> = [Bool]()
var cellCaptureArray: Array<UICollectionViewCell> = [UICollectionViewCell]()
var accountsIdHohderArray: Array<Int16> = [Int16]()
var accountsNameHolderArray: Array<String> = [String]()
var providerNameHolderArray: Array<String> = [String]()
var accountStatusHolderArray: Array<String> = [String]()
var accountsImageNameHolder: Array<String> = [String]()
override func viewDidLoad() {
super.viewDidLoad()
//data loader open
tapStatusHolderArray.append(false)
accountsIdHohderArray.append(100)
accountsNameHolderArray.append("account 1")
providerNameHolderArray.append("twitter")
accountStatusHolderArray.append("enabled")
accountsImageNameHolder.append("default_user_image")
tapStatusHolderArray.append(false)
accountsIdHohderArray.append(101)
accountsNameHolderArray.append("account 2")
providerNameHolderArray.append("facebook")
accountStatusHolderArray.append("enabled")
accountsImageNameHolder.append("default_user_image")
tapStatusHolderArray.append(false)
accountsIdHohderArray.append(102)
accountsNameHolderArray.append("account 3")
providerNameHolderArray.append("linkedin")
accountStatusHolderArray.append("enabled")
accountsImageNameHolder.append("default_user_image")
tapStatusHolderArray.append(false)
accountsIdHohderArray.append(100)
accountsNameHolderArray.append("account 1")
providerNameHolderArray.append("twitter")
accountStatusHolderArray.append("enabled")
accountsImageNameHolder.append("default_user_image")
tapStatusHolderArray.append(false)
accountsIdHohderArray.append(101)
accountsNameHolderArray.append("account 2")
providerNameHolderArray.append("facebook")
accountStatusHolderArray.append("enabled")
accountsImageNameHolder.append("default_user_image")
tapStatusHolderArray.append(false)
accountsIdHohderArray.append(102)
accountsNameHolderArray.append("account 3")
providerNameHolderArray.append("linkedin")
accountStatusHolderArray.append("enabled")
accountsImageNameHolder.append("default_user_image")
tapStatusHolderArray.append(false)
accountsIdHohderArray.append(100)
accountsNameHolderArray.append("account 1")
providerNameHolderArray.append("twitter")
accountStatusHolderArray.append("enabled")
accountsImageNameHolder.append("default_user_image")
tapStatusHolderArray.append(false)
accountsIdHohderArray.append(101)
accountsNameHolderArray.append("account 2")
providerNameHolderArray.append("facebook")
accountStatusHolderArray.append("enabled")
accountsImageNameHolder.append("default_user_image")
tapStatusHolderArray.append(false)
accountsIdHohderArray.append(102)
accountsNameHolderArray.append("account 3")
providerNameHolderArray.append("linkedin")
accountStatusHolderArray.append("enabled")
accountsImageNameHolder.append("default_user_image")
//data loader close
// Do any additional setup after loading the view.
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
layout.itemSize = CGSize(width: 70, height: 70)
collectionView = UICollectionView(frame: CGRect(x: self.view.frame.origin.x, y: self.view.frame.origin.y, width: 200, height: 200), collectionViewLayout: layout)
collectionView.dataSource = self
collectionView.delegate = self
collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
collectionView.backgroundColor = UIColor.whiteColor()
self.view.addSubview(collectionView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.tapStatusHolderArray.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell: UICollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! UICollectionViewCell
cell.backgroundColor = UIColor.yellowColor()
//create views here
let accountsImageView = UIImageView()
accountsImageView.setTranslatesAutoresizingMaskIntoConstraints(false)
accountsImageView.image = UIImage(named: "default_user_image")
//tap listener for the accounts image view
let tapAccountsImageView = UITapGestureRecognizer(target: self, action: Selector("tapGesture:"))
accountsImageView.tag = indexPath.row
accountsImageView.addGestureRecognizer(tapAccountsImageView)
accountsImageView.userInteractionEnabled = true
let providerImageView = UIImageView()
providerImageView.setTranslatesAutoresizingMaskIntoConstraints(false)
providerImageView.image = UIImage(named: translateProviderNameToImageName(providerNameHolderArray[indexPath.row]))
let checkboxImageView = UIImageView()
checkboxImageView.setTranslatesAutoresizingMaskIntoConstraints(false)
checkboxImageView.image = UIImage(named: "checkbox_unchecked")
//tap listener for the checkbox image view
let tapCheckbox = UITapGestureRecognizer(target: self, action: Selector("tapGesture:"))
checkboxImageView.tag = indexPath.row
checkboxImageView.addGestureRecognizer(tapCheckbox)
checkboxImageView.userInteractionEnabled = true
/************************************************************/
//add subviews here
cell.addSubview(accountsImageView)
cell.addSubview(providerImageView)
cell.addSubview(checkboxImageView)
/************************************************************/
//view dictionary
let viewsDictionary = [
"accountsImageView":accountsImageView,
"providerImageView":providerImageView,
"checkboxImageView":checkboxImageView
]
/************************************************************/
//apply size constraints
//accountsImageView
//1
let accountsImageView_constraint_H = NSLayoutConstraint.constraintsWithVisualFormat(
"H:[accountsImageView(50)]",
options: NSLayoutFormatOptions(rawValue:0),
metrics: nil,
views: viewsDictionary)
let accountsImageView_constraint_V = NSLayoutConstraint.constraintsWithVisualFormat(
"V:[accountsImageView(50)]",
options: NSLayoutFormatOptions(rawValue:0),
metrics: nil, views: viewsDictionary)
accountsImageView.addConstraints(accountsImageView_constraint_H)
accountsImageView.addConstraints(accountsImageView_constraint_V)
//2
let providerImageView_constraint_H = NSLayoutConstraint.constraintsWithVisualFormat(
"H:[providerImageView(20)]",
options: NSLayoutFormatOptions(rawValue:0),
metrics: nil,
views: viewsDictionary)
let providerImageView_constraint_V = NSLayoutConstraint.constraintsWithVisualFormat(
"V:[providerImageView(20)]",
options: NSLayoutFormatOptions(rawValue:0),
metrics: nil, views: viewsDictionary)
providerImageView.addConstraints(providerImageView_constraint_H)
providerImageView.addConstraints(providerImageView_constraint_V)
//3
let checkboxImageView_constraint_H = NSLayoutConstraint.constraintsWithVisualFormat(
"H:[checkboxImageView(20)]",
options: NSLayoutFormatOptions(rawValue:0),
metrics: nil,
views: viewsDictionary)
let checkboxImageView_constraint_V = NSLayoutConstraint.constraintsWithVisualFormat(
"V:[checkboxImageView(20)]",
options: NSLayoutFormatOptions(rawValue:0),
metrics: nil, views: viewsDictionary)
checkboxImageView.addConstraints(checkboxImageView_constraint_H)
checkboxImageView.addConstraints(checkboxImageView_constraint_V)
/**************************************************************/
//position constraints
//views
//1
let view_constraint_H = NSLayoutConstraint.constraintsWithVisualFormat(
"H:|-[accountsImageView]",
options: NSLayoutFormatOptions(rawValue:0),
metrics: nil, views: viewsDictionary)
let view_constraint_V = NSLayoutConstraint.constraintsWithVisualFormat(
"V:|-[accountsImageView]",
options: NSLayoutFormatOptions.AlignAllLeading,
metrics: nil, views: viewsDictionary)
cell.addConstraints(view_constraint_H)
cell.addConstraints(view_constraint_V)
//2
let view_constraint_H1 = NSLayoutConstraint.constraintsWithVisualFormat(
"H:|-45-[providerImageView]",
options: NSLayoutFormatOptions(rawValue:0),
metrics: nil, views: viewsDictionary)
let view_constraint_V1 = NSLayoutConstraint.constraintsWithVisualFormat(
"V:[providerImageView]-50-|",
options: NSLayoutFormatOptions.AlignAllLeading,
metrics: nil, views: viewsDictionary)
cell.addConstraints(view_constraint_H1)
cell.addConstraints(view_constraint_V1)
//3
let view_constraint_H2 = NSLayoutConstraint.constraintsWithVisualFormat(
"H:|-0-[checkboxImageView]",
options: NSLayoutFormatOptions(rawValue:0),
metrics: nil, views: viewsDictionary)
let view_constraint_V2 = NSLayoutConstraint.constraintsWithVisualFormat(
"V:[checkboxImageView]-5-|",
options: NSLayoutFormatOptions.AlignAllLeading,
metrics: nil, views: viewsDictionary)
cell.addConstraints(view_constraint_H2)
cell.addConstraints(view_constraint_V2)
/***************************************************************/
//set initial status for the cell checkbox
if(tapStatusHolderArray[indexPath.row] == true){
//set the checkbox as checked
checkboxImageView.image = UIImage(named: "checked_checkbox")
}else{
//set checkbox as unchecked
checkboxImageView.image = UIImage(named: "checkbox_unchecked")
}
//load the cell into the array
cellCaptureArray.append(cell)
return cell
}
func tapGesture(sender: UITapGestureRecognizer)
{
/*var index: Int = sender.view!.tag
if(checkedStatusHolderArray[index] == false){
checkedStatusHolderArray[index] = true
(sender.view as! UIImageView).image = UIImage(named: "checked_checkbox")
}else{
checkedStatusHolderArray[index] = false
(sender.view as! UIImageView).image = UIImage(named: "checkbox_unchecked")
}*///old code
/*
this code extracts the index from the tag attached to the sender
In this case the sender could be either the checkboxIV or the accountIV
both have the same tag. The tag is the indexpath.row for the corresponding cell.
The indexpath.row is used to signal the tap gesture recognizer about the view being tapped.
The tap gesture recognizer is asigned to both the views checkboxIV and the accountIV
so that the user can tap on either to allow check and uncheck the checkbox. Both the tap
gestures reconizers do the same function.
The cell inflated are saved inside the checkedStatusHolderArray so that using the index
extracted above we can change the status of the checkboxIV of the corresponding cell.
*/
var index: Int = sender.view!.tag
var cell: UICollectionViewCell = cellCaptureArray[index]
if(tapStatusHolderArray[index] == false){
tapStatusHolderArray[index] = true
let subViews = cell.subviews
//assuming that the order in which the views were added will be maintained
let checkboxIV = subViews[3] as! UIImageView
checkboxIV.image = UIImage(named: "checked_checkbox")
}else{
tapStatusHolderArray[index] = false
let subViews = cell.subviews
//assuming that the order in which the views were added will be maintained
let checkboxIV = subViews[3] as! UIImageView
checkboxIV.image = UIImage(named: "checkbox_unchecked")
}
/*the reson for choosing [3] for the subvies is that at
index 0 the superview is present
index 1 the accountsImageView is present
index 2 the providerImageView is present
index 3 the checkboxImageView is present*/
}
func translateProviderNameToImageName(var provider: String) -> String{
switch provider{
case "twitter":
return "twitter_transparent"
case "facebook":
return "facebook_transparent"
case "linkedin":
return "linkedin-follow"
default:
return "twitter_transparent"
}
}
}
first reset imageview and then try to load
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
cell.imageView.image = nil;
cell.imageView.image = [UIImage imagewithNamed:#"imagename"];

Swift NSLayout uneven alignment

I am trying to mess around with autolayout programmatically in Swift. However I have one problem. I want my view1 (red box) to have a the regular spaced alignment with the superview (H:|-[view1]-|)". This works for the right alignment but not the left. I want the left side of the view to have the same spacing as the right side. The view seems to want to align itself horizontally with the button below. Does anyone know how to fix this or what I am doing wrong?
override func viewDidLoad() {
super.viewDidLoad()
self.title = "yolo"
let frame = UIScreen.mainScreen().bounds
var b = UIButton.buttonWithType(UIButtonType.System) as! UIButton
b.frame = CGRectMake(frame.minX + 50, frame.minY + 100, frame.width * 0.8, frame.height * 0.2)
b.backgroundColor = UIColor.purpleColor()
b.addTarget(self, action: "buttonClicked:", forControlEvents: UIControlEvents.TouchUpInside)
b.layer.cornerRadius = 17
b.setTitle("hello", forState: UIControlState.Normal)
b.setTranslatesAutoresizingMaskIntoConstraints(false)
// Do any additional setup after loading the view, typically from a nib.
let view1 = UIView()
view1.setTranslatesAutoresizingMaskIntoConstraints(false)
view1.backgroundColor = UIColor.redColor()
let view2 = UIView()
view2.setTranslatesAutoresizingMaskIntoConstraints(false)
view2.backgroundColor = UIColor.yellowColor()
self.view.addSubview(b)
self.view.addSubview(view1)
// dictionary for views
let viewsDictionary = ["view1":view1,"view2":view2, "b":b]
let button_constraint_H:Array = NSLayoutConstraint.constraintsWithVisualFormat("H:[b(>=200)]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
let button_constraint_V:Array = NSLayoutConstraint.constraintsWithVisualFormat("V:[b(>=200)]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
b.addConstraints(button_constraint_H as [AnyObject])
b.addConstraints(button_constraint_V as [AnyObject])
//view1
let view1_constraint_H:Array = NSLayoutConstraint.constraintsWithVisualFormat("H:[view1(50)]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
let view1_constraint_V:Array = NSLayoutConstraint.constraintsWithVisualFormat("V:[view1(50)]", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
view1.addConstraints(view1_constraint_H as [AnyObject])
view1.addConstraints(view1_constraint_V as [AnyObject])
let view_constraint_H:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("H:|-[view1]-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
let view_constraint_V:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("V:|-90-[view1]-[b]-0-|", options: NSLayoutFormatOptions.AlignAllLeading, metrics: nil, views: viewsDictionary)
let view_constraint_H2:NSArray = NSLayoutConstraint.constraintsWithVisualFormat("H:|[b]|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
view.addConstraints(view_constraint_H2 as [AnyObject])
view.addConstraints(view_constraint_V as [AnyObject])
view.addConstraints(view_constraint_H as [AnyObject])
}
The problem is that your constraints make no sense. You are saying this:
"H:[view1(50)]"
"H:|-[view1]-|"
So on the one hand you want view1 to be aligned with the margins of its superview (this is what - means), but on the other hand you want view1 to be exactly 50 points wide (that is what (50) means). You can't have both!

Resources