add constraint to programmatically created button - ios

Hello I have showing UIButton in tableView footer programmatically. The problem is it is not showing correctly in smaller phones like 5s. The button title is going right on the smaller screens.
You can see in the image that button title is not in the center
This is how I am showing the button
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView(frame: CGRectMake(0, 0, tableView.frame.size.width, tableView.frame.size.height))
nextButton = UIButton(type: UIButtonType.System) as UIButton
nextButton!.frame = CGRectMake(0, 0, 414, 65)
nextButton!.setTitle("NEXT", forState: UIControlState.Normal)
nextButton!.setTitleColor(UIColor.whiteColor(), forState:UIControlState.Normal)
nextButton!.titleLabel?.font = UIFont(name: Variables.MONTESERRAT_REGULAR, size: 20.0)
nextButton!.backgroundColor = UIColor().blueColor() //top
nextButton!.titleEdgeInsets = UIEdgeInsetsMake(0.0,10.0, 10.0, 0.0)
nextButton!.addTarget(self, action: "nextButtonClicked:", forControlEvents: UIControlEvents.TouchUpInside)
footerView.addSubview(nextButton!)
return footerView
}
override func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 50.0
}

Use auto layout(VFL) instead of setting some random static frame,
let containerView = UIView()
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.backgroundColor = UIColor.greenColor()
let buttonNext = UIButton(type: UIButtonType.System)
buttonNext.translatesAutoresizingMaskIntoConstraints = false
buttonNext.setTitle("NEXT", forState: UIControlState.Normal)
//buttonNext.backgroundColor = UIColor.blueColor()
containerView.addSubview(buttonNext)
self.view.addSubview(containerView)
var verticalConstraint = NSLayoutConstraint.constraintsWithVisualFormat("V:|[containerView]|", options: [], metrics: nil, views: ["containerView": containerView])
var horizontalConstraint = NSLayoutConstraint.constraintsWithVisualFormat("H:|[containerView]|", options: [], metrics: nil, views: ["containerView": containerView])
self.view.addConstraints(verticalConstraint)
self.view.addConstraints(horizontalConstraint)
verticalConstraint = NSLayoutConstraint.constraintsWithVisualFormat("V:|[buttonNext]|", options: [], metrics: nil, views: ["buttonNext": buttonNext])
horizontalConstraint = NSLayoutConstraint.constraintsWithVisualFormat("H:|[buttonNext]|", options: [], metrics: nil, views: ["buttonNext": buttonNext])
self.view.addConstraints(verticalConstraint)
self.view.addConstraints(horizontalConstraint)
You can set the title alignment if you want any specific.
Hope this helps you.
Edit/Update:
func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView?
let footerView = UIView()
footerView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 50)
footerView.backgroundColor = UIColor.redColor()
let buttonNext = UIButton(type: UIButtonType.System)
buttonNext.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 50)
buttonNext.translatesAutoresizingMaskIntoConstraints = false
buttonNext.setTitle("NEXT", forState: UIControlState.Normal)
buttonNext.backgroundColor = UIColor.blueColor()
footerView.addSubview(buttonNext)
footerView.layoutIfNeeded()
return footerView
}
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 50
}

Related

Swift 3 - NSLayoutConstraint CollectionView Attaching to another view

I am using this code Swift 3 - CollectionView data source did not return a valid cell
UPDATED FROM TERENCE ANSWER:
In viewDidLoad I put
collectionView?.translatesAutoresizingMaskIntoConstraints = false
messageInputContainerView.translatesAutoresizingMaskIntoConstraints = false
view.addConstraintsWithFormat(format: "H:|-0-[v0]-0-|", views: messageInputContainerView)
view.addConstraintsWithFormat(format: "H:|-0-[v0]-0-|", views: collectionView!)
let constraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[v1]-0-[v0(48)]", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":messageInputContainerView, "v1": collectionView!])
constraints[2].identifier = "heightConstraint"
view.addConstraints(constraints)
bottomConstraint = NSLayoutConstraint(item: messageInputContainerView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0)
view.addConstraint(bottomConstraint!)
with bottomconstraint I modify the messageInputContainerView to goes up when the keyboard appear
messageInputContainerView.addConstraintsWithFormat(format: "H:|-8-[v0(30)]-8-[v1][v2(60)]|", views: sendPicButton, inputTextView, sendTextButton)
messageInputContainerView.addConstraintsWithFormat(format: "V:|-6-[v0]|", views: inputTextView)
messageInputContainerView.addConstraintsWithFormat(format: "V:[v0]-6-|", views: sendTextButton)
messageInputContainerView.addConstraintsWithFormat(format: "V:[v0]-14-|", views: sendPicButton)
messageInputContainerView.addConstraintsWithFormat(format: "H:|[v0]|", views: topBorderView)
messageInputContainerView.addConstraintsWithFormat(format: "V:|[v0(0.5)]", views: topBorderView)
On the first screen I have space between last message and messageInputContainerView. How to fix it?
On the second screen messageInputContainerView is already over the collection view
I am modifying constraints[2].identifier = "heightConstraint" in textViewDidChange method to change the position of the messageInputContainerView when keyboard appear
How to fix it to be attached, because now its over the mesagess(collectionView) ?
Maybe you can try this: container add these "V:|-0-[collectionView]-0-[inputview(>=48)]-0-|" and "H:|-0-[collectionView]-0-|" with "H:|-0-[inputview]-0-|"
where container does not necessary set auto resizing mask false unless your container also need it. But both collection view and input view need to set it false to make auto constraints work.
One approach would be to change the ChatLogController from a subclass of UICollectionViewController to a plain UIViewController, and then add the CollectionView as a subview, add the MessageInputContainerView as a subview, and then pin the bottom of the Collection view to the top of the Input view.
Here is a modified version of the ChatLogViewController.swift class... it's from the code at Step 7 (https://www.letsbuildthatapp.com/course_video?id=152) of that sample app. You should be able to drop it into your project pretty much as-is... just change the loading line from:
let controller = ChatLogController(collectionViewLayout: layout)
to
let controller = MyChatLogController()
Also note: this does not have the variable-height textfield... but if you implement it in the same way as you did in your version, it should work just fine (remember, the bottom of the Collection view will now be "pinned" to the top of the Input container view).
Edit: I made a few changes since my original post - this now supports the auto-height-adjusting input field.
import UIKit
class MyChatLogController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UITextViewDelegate {
fileprivate var collectionView: UICollectionView?
fileprivate let cellId = "cellId"
var friend: Friend? {
didSet {
navigationItem.title = friend?.name
messages = friend?.messages?.allObjects as? [Message]
messages = messages?.sorted(by: {$0.date!.compare($1.date! as Date) == .orderedAscending})
}
}
var messages: [Message]?
let messageInputContainerView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.white
return view
}()
let inputTextView: UITextView = {
let textView = UITextView()
textView.font = UIFont.systemFont(ofSize: 18)
return textView
}()
let sendButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Send", for: UIControlState())
let titleColor = UIColor(red: 0, green: 137/255, blue: 249/255, alpha: 1)
button.setTitleColor(titleColor, for: UIControlState())
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
return button
}()
var bottomConstraint: NSLayoutConstraint?
var heightConstraint: NSLayoutConstraint?
override func viewDidLoad() {
super.viewDidLoad()
tabBarController?.tabBar.isHidden = true
let layout = UICollectionViewFlowLayout()
collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
// make sure collectionView creation was successful
guard let cv = collectionView else {
return
}
cv.delegate = self
cv.dataSource = self
cv.translatesAutoresizingMaskIntoConstraints = false
cv.backgroundColor = UIColor.white
view.addSubview(cv)
cv.register(MyChatLogMessageCell.self, forCellWithReuseIdentifier: cellId)
view.addSubview(messageInputContainerView)
view.addConstraintsWithFormat("H:|[v0]|", views: messageInputContainerView)
view.addConstraintsWithFormat("H:|[v0]|", views: cv)
view.addConstraintsWithFormat("V:|[v0]-(-32)-[v1]", views: cv, messageInputContainerView)
bottomConstraint = NSLayoutConstraint(item: messageInputContainerView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0)
view.addConstraint(bottomConstraint!)
heightConstraint = NSLayoutConstraint(item: messageInputContainerView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 60)
view.addConstraint(heightConstraint!)
setupInputComponents()
inputTextView.delegate = self
inputTextView.isScrollEnabled = false
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let indexPath = IndexPath(item: self.messages!.count - 1, section: 0)
self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true)
}
func handleKeyboardNotification(_ notification: Notification) {
if let userInfo = notification.userInfo {
let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as AnyObject).cgRectValue
let isKeyboardShowing = notification.name == NSNotification.Name.UIKeyboardWillShow
bottomConstraint?.constant = isKeyboardShowing ? -keyboardFrame!.height : 0
UIView.animate(withDuration: 0, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: {
self.view.layoutIfNeeded()
}, completion: { (completed) in
if isKeyboardShowing {
let indexPath = IndexPath(item: self.messages!.count - 1, section: 0)
self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true)
}
})
}
}
func textViewDidChange(_ textView: UITextView) { //Handle the text changes here
let sz = textView.sizeThatFits(CGSize(width: textView.frame.size.width, height: CGFloat.greatestFiniteMagnitude))
heightConstraint?.constant = max(60, sz.height)
UIView.animate(withDuration: 0, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: {
self.view.layoutIfNeeded()
}, completion: { (completed) in
let indexPath = IndexPath(item: self.messages!.count - 1, section: 0)
self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true)
})
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
inputTextView.endEditing(true)
}
fileprivate func setupInputComponents() {
let topBorderView = UIView()
topBorderView.backgroundColor = UIColor(white: 0.75, alpha: 1.0)
messageInputContainerView.addSubview(inputTextView)
messageInputContainerView.addSubview(sendButton)
messageInputContainerView.addSubview(topBorderView)
messageInputContainerView.addConstraintsWithFormat("H:|-8-[v0][v1(60)]|", views: inputTextView, sendButton)
messageInputContainerView.addConstraintsWithFormat("V:|[v0]|", views: inputTextView)
messageInputContainerView.addConstraintsWithFormat("V:|[v0]|", views: sendButton)
messageInputContainerView.addConstraintsWithFormat("H:|[v0]|", views: topBorderView)
messageInputContainerView.addConstraintsWithFormat("V:|[v0(0.5)]", views: topBorderView)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if let count = messages?.count {
return count
}
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! MyChatLogMessageCell
cell.messageTextView.text = messages?[indexPath.item].text
if let message = messages?[indexPath.item], let messageText = message.text, let profileImageName = message.friend?.profileImageName {
cell.profileImageView.image = UIImage(named: profileImageName)
let size = CGSize(width: 250, height: 1000)
let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
let estimatedFrame = NSString(string: messageText).boundingRect(with: size, options: options, attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 18)], context: nil)
if message.isSender == nil || !message.isSender!.boolValue {
cell.messageTextView.frame = CGRect(x: 48 + 8, y: 0, width: estimatedFrame.width + 16, height: estimatedFrame.height + 20)
cell.textBubbleView.frame = CGRect(x: 48 - 10, y: -4, width: estimatedFrame.width + 16 + 8 + 16, height: estimatedFrame.height + 20 + 6)
cell.profileImageView.isHidden = false
// cell.textBubbleView.backgroundColor = UIColor(white: 0.95, alpha: 1)
cell.bubbleImageView.image = MyChatLogMessageCell.grayBubbleImage
cell.bubbleImageView.tintColor = UIColor(white: 0.95, alpha: 1)
cell.messageTextView.textColor = UIColor.black
} else {
//outgoing sending message
cell.messageTextView.frame = CGRect(x: view.frame.width - estimatedFrame.width - 16 - 16 - 8, y: 0, width: estimatedFrame.width + 16, height: estimatedFrame.height + 20)
cell.textBubbleView.frame = CGRect(x: view.frame.width - estimatedFrame.width - 16 - 8 - 16 - 10, y: -4, width: estimatedFrame.width + 16 + 8 + 10, height: estimatedFrame.height + 20 + 6)
cell.profileImageView.isHidden = true
// cell.textBubbleView.backgroundColor = UIColor(red: 0, green: 137/255, blue: 249/255, alpha: 1)
cell.bubbleImageView.image = MyChatLogMessageCell.blueBubbleImage
cell.bubbleImageView.tintColor = UIColor(red: 0, green: 137/255, blue: 249/255, alpha: 1)
cell.messageTextView.textColor = UIColor.white
}
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if let messageText = messages?[indexPath.item].text {
let size = CGSize(width: 250, height: 1000)
let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
let estimatedFrame = NSString(string: messageText).boundingRect(with: size, options: options, attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 18)], context: nil)
return CGSize(width: view.frame.width, height: estimatedFrame.height + 20)
}
return CGSize(width: view.frame.width, height: 100)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsetsMake(8, 0, 0, 0)
}
}
class MyChatLogMessageCell: BaseCell {
let messageTextView: UITextView = {
let textView = UITextView()
textView.font = UIFont.systemFont(ofSize: 18)
textView.text = "Sample message"
textView.backgroundColor = UIColor.clear
return textView
}()
let textBubbleView: UIView = {
let view = UIView()
view.layer.cornerRadius = 15
view.layer.masksToBounds = true
return view
}()
let profileImageView: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFill
imageView.layer.cornerRadius = 15
imageView.layer.masksToBounds = true
return imageView
}()
static let grayBubbleImage = UIImage(named: "bubble_gray")!.resizableImage(withCapInsets: UIEdgeInsetsMake(22, 26, 22, 26)).withRenderingMode(.alwaysTemplate)
static let blueBubbleImage = UIImage(named: "bubble_blue")!.resizableImage(withCapInsets: UIEdgeInsetsMake(22, 26, 22, 26)).withRenderingMode(.alwaysTemplate)
let bubbleImageView: UIImageView = {
let imageView = UIImageView()
imageView.image = MyChatLogMessageCell.grayBubbleImage
imageView.tintColor = UIColor(white: 0.90, alpha: 1)
return imageView
}()
override func setupViews() {
super.setupViews()
addSubview(textBubbleView)
addSubview(messageTextView)
addSubview(profileImageView)
addConstraintsWithFormat("H:|-8-[v0(30)]", views: profileImageView)
addConstraintsWithFormat("V:[v0(30)]|", views: profileImageView)
profileImageView.backgroundColor = UIColor.red
textBubbleView.addSubview(bubbleImageView)
textBubbleView.addConstraintsWithFormat("H:|[v0]|", views: bubbleImageView)
textBubbleView.addConstraintsWithFormat("V:|[v0]|", views: bubbleImageView)
}
}

addSubview not working after converting

I upgraded xcode from 7.3.1 to 8 and converted to swift 2.2, other than the storyboard being a mess everything worked except adding a UIView programatically.
This was working fine before, now nothing shows up at all and there are no errors. Any ideas?
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
//create view
let vw = UIView()
vw.backgroundColor = UIColor(red: 0.9137, green: 0.9176, blue: 0.9216, alpha: 1.0) /* #e9eaeb */
//create label inside view
let label: UILabel = UILabel()
label.frame = CGRectMake(0, 0, 200, 28)
label.textAlignment = NSTextAlignment.Left
label.textColor = UIColor.grayColor()
label.font = label.font.fontWithSize(13)
if !clearSearch {
label.text = " Recent Searches"
} else {
label.text = " Search Results"
}
vw.addSubview(label)
//create button inside view
let button: UIButton = UIButton()
button.frame = CGRectMake(self.view.frame.size.width - 45, 0, 40, 28)
button.titleLabel?.font = UIFont.systemFontOfSize(13)
button.setTitle("Clear", forState: UIControlState.Normal)
button.addTarget(self, action: #selector(deleteSearches), forControlEvents: UIControlEvents.TouchUpInside)
button.setTitleColor(UIColor(red: 0.3216, green: 0.7176, blue: 0.5333, alpha: 1.0), forState: UIControlState.Normal)
vw.addSubview(button)
return vw
}
Thanks for any help.
Looks like this is now required.
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 28
}

Add two buttons in footer in the same row

hello I want to add two buttons on my ViewController programmatically like this
What I have done is this
func createButton(buttonTitle: String,buttonAction: Selector) -> UIButton{
let button = UIButton(type: UIButtonType.System) as UIButton
button.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame)/2, 48)
// button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle(buttonTitle, forState: UIControlState.Normal)
button.addTarget(self, action:buttonAction, forControlEvents: UIControlEvents.TouchUpInside)
button.setTitleColor(UIColor.whiteColor(), forState:UIControlState.Normal)
button.titleLabel?.font = UIFont(name: Variables.MONTESERRAT_REGULAR, size: 20.0)
button.backgroundColor = UIColor().blueColor() //top
button.titleEdgeInsets = UIEdgeInsetsMake(0.0,10.0, 10.0, 0.0)
return button
}
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView()
footerView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 48)
bottomButton = createButton("PUBLISH", buttonAction: "Publish")
footerView.addSubview(bottomButton!)
return footerView
}
At the moment it only prints one button. for second button I am doing this
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView()
footerView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 48)
bottomButton = createButton("PUBLISH", buttonAction: "Publish")
bottomButton2 = createButton("Delete", buttonAction: "Delete")
footerView.addSubview(bottomButton!)
footerView.addSubview(bottomButton2!)
return footerView
}
This code is not printing two buttons. just printing only one
I think the problem is that both buttons have the same position, so one is showing above the other.
Try this:
func createButton(buttonTitle: String,buttonAction: Selector, buttonNumber : Int) -> UIButton{
let backgroundColor = buttonNumber == 0 ? UIColor.blueColor() : UIColor.orangeColor()
let space : CGFloat = 5
let button = UIButton(type: UIButtonType.System) as UIButton
let width = (CGRectGetWidth(self.view.frame) - space)/2
let xPos = buttonNumber == 0 ? 0 : width + space
button.frame = CGRectMake(xPos, 0, width, 48)
// button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle(buttonTitle, forState: UIControlState.Normal)
button.addTarget(self, action:buttonAction, forControlEvents: UIControlEvents.TouchUpInside)
button.setTitleColor(UIColor.whiteColor(), forState:UIControlState.Normal)
// button.titleLabel?.font = UIFont(name: Variables.MONTESERRAT_REGULAR, size: 20.0)
button.backgroundColor = backgroundColor
button.titleEdgeInsets = UIEdgeInsetsMake(0.0,10.0, 10.0, 0.0)
return button
}
And then add it like so:
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = UIView()
footerView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 48)
bottomButton = createButton("PUBLISH", buttonAction: "Publish", buttonNumber: 0)
bottomButton2 = createButton("Delete", buttonAction: "Delete", buttonNumber: 1)
footerView.addSubview(bottomButton!)
footerView.addSubview(bottomButton2!)
return footerView
}

set button on bottom of static tableView

hello I want to set the programmatically created button at bottom of static tableView. The problem I am having is the botton stays at the bottom on smaller phones(5s) which is completely fine. But on 6s Plus it shows white area underneath the button. Meaning the button is slightly above from the ground or above from edge of the bottom.
This is how I am setting the button
func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView?
let footerView = UIView()
footerView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 50)
footerView.backgroundColor = UIColor.redColor()
let buttonNext = UIButton(type: UIButtonType.System)
buttonNext.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 50)
buttonNext.translatesAutoresizingMaskIntoConstraints = false
buttonNext.setTitle("NEXT", forState: UIControlState.Normal)
buttonNext.backgroundColor = UIColor.blueColor()
footerView.addSubview(buttonNext)
footerView.layoutIfNeeded()
return footerView
}
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 50
}
It sounds like you want a footer at the bottom of the table, rather than at the end of the section. In this case you should use the table's tableFooterView property. You could do this with the following code in viewDidLoad (or elsewhere):
let footerView = UIView()
footerView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 50)
footerView.backgroundColor = UIColor.redColor()
let buttonNext = UIButton(type: UIButtonType.System)
buttonNext.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 50)
buttonNext.translatesAutoresizingMaskIntoConstraints = false
buttonNext.setTitle("NEXT", forState: UIControlState.Normal)
buttonNext.backgroundColor = UIColor.blueColor()
tableView.tableFooterView = footerView

make button in tableview section header float/align right programmatically // Swift

I trying to align of float a UIButton to the right in the section header of a TableView universally.
So far I only managed to add constraints for one screen size...
Here is my code so far:
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
var headerFrame:CGRect = tableView.frame
let titelArr: NSArray = ["1", "2", "3", "4", "5", "6"]
var title = UILabel(frame: CGRectMake(10, 10, 100, 30))
title.font = UIFont.boldSystemFontOfSize(20.0)
title.text = titelArr.objectAtIndex(section) as? String
title.textColor = UIColor.whiteColor()
var headBttn:UIButton = UIButton.buttonWithType(UIButtonType.ContactAdd) as UIButton
headBttn.frame = CGRectMake(320, 10, 30, 30)
headBttn.enabled = true
headBttn.titleLabel?.text = title.text
headBttn.tag = titelArr.indexOfObject(titelArr.objectAtIndex(section))
headBttn.addTarget(self, action: "addItem:", forControlEvents: UIControlEvents.TouchUpInside)
var headerView:UIView = UIView(frame: CGRectMake(0, 0, headerFrame.size.width, headerFrame.size.height))
headerView.backgroundColor = UIColor(red: 108/255, green: 185/255, blue: 0/255, alpha: 0.9)
headerView.addSubview(title)
headerView.addSubview(headBttn)
return headerView
}
How can I make the button float right? The rest of the constraints can stay as they are...
THX for your help!
//Seb
Thx to #rdelmar and some research here is the answer if anybody should be interessted ;-)
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
var headerFrame = tableView.frame
var headerView:UIView = UIView(frame: CGRectMake(0, 0, headerFrame.size.width, headerFrame.size.height))
headerView.backgroundColor = UIColor(red: 108/255, green: 185/255, blue: 0/255, alpha: 0.9)
var title = UILabel()
title.setTranslatesAutoresizingMaskIntoConstraints(false)
title.font = UIFont.boldSystemFontOfSize(20.0)
title.text = titelArr.objectAtIndex(section) as? String
title.textColor = UIColor.whiteColor()
headerView.addSubview(title)
var headBttn:UIButton = UIButton.buttonWithType(UIButtonType.System) as UIButton
headBttn.setTranslatesAutoresizingMaskIntoConstraints(false)
headBttn.enabled = true
headBttn.titleLabel?.text = title.text
headBttn.tag = titelArr.indexOfObject(titelArr.objectAtIndex(section))
headBttn.addTarget(self, action: "addItem:", forControlEvents: UIControlEvents.TouchUpInside)
headerView.addSubview(headBttn)
var viewsDict = Dictionary <String, UIView>()
viewsDict["title"] = title
viewsDict["headBttn"] = headBttn
headerView.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"H:|-10-[title]-[headBttn]-15-|", options: nil, metrics: nil, views: viewsDict))
headerView.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"V:|-[title]-|", options: nil, metrics: nil, views: viewsDict))
headerView.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"V:|-[headBttn]-|", options: nil, metrics: nil, views: viewsDict))
return headerView
}
Thnx for sharing the amazing answer #Seb. Since there have been some changes made in Swift, which affects your answer. I'll provide an example of how to do the same in Swift 3 and 4:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: tableView.frame.size.height))
headerView.backgroundColor = UIColor.lightGray
let title = UILabel()
title.translatesAutoresizingMaskIntoConstraints = false
title.text = "myTitle"
headerView.addSubview(title)
let button = UIButton(type: .system)
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle("myButton", for: .normal)
headerView.addSubview(button)
var headerViews = Dictionary<String, UIView>()
headerViews["title"] = title
headerViews["button"] = button
headerView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[title]-[button]-15-|", options: [], metrics: nil, views: headerViews))
headerView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[title]-|", options: [], metrics: nil, views: headerViews))
headerView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[button]-|", options: [], metrics: nil, views: headerViews))
return headerView
}

Resources