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
}
Related
I'm having a bit of trouble figuring out how to make the UIButton title transparent such that it's color is the color of the superview's gradient background.
I've seen a thread about rendering the button as an image, but it was in objective-c with the old CG API and I'm wondering if anyone can give advice on a better way to solve this problem.
Any advice would be appreciated!
This is what I have so far:
import UIKit
import Foundation
class MainViewController: UIViewController {
let headingLabel: UILabel = {
let label = UILabel()
label.text = "Hello, World"
label.font = label.font.withSize(30)
label.textColor = .white
label.textAlignment = .center
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let continueButton: UIButton = {
let button = UIButton()
button.setTitleColor(.black, for: .normal)
button.setTitle("Continue", for: .normal)
button.layer.cornerRadius = 10
button.backgroundColor = .white
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let gradientLayer: CAGradientLayer = {
let layer = CAGradientLayer()
layer.colors = [
UIColor(red: 96/255, green: 165/255, blue: 238/255, alpha: 1.0).cgColor,
UIColor(red: 233/255, green: 97/255, blue: 99/255, alpha: 1.0).cgColor,
]
layer.startPoint = CGPoint(x: 0.0, y: 0.0)
layer.endPoint = CGPoint(x: 1.0, y: 1.0)
return layer
}()
override func viewDidLoad() {
super.viewDidLoad()
setupView()
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
override func viewDidAppear(_ animated: Bool) {
navigationController?.navigationBar.isHidden = true
}
func setupView() {
// root view
gradientLayer.frame = view.frame
view.layer.addSublayer(gradientLayer)
view.addSubview(headingLabel)
view.addSubview(continueButton)
// constraints
let views: [String: UIView] = [
"headingLabel": headingLabel,
"continueButton": continueButton,
"superview": view
]
var constraints: [NSLayoutConstraint] = []
let verticalHeadingLabelConstraint = NSLayoutConstraint.constraints(withVisualFormat:
"V:|-100-[headingLabel(30)]",
options: [],
metrics: nil,
views: views)
constraints += verticalHeadingLabelConstraint
let horizontalHeadingLabelConstraint = NSLayoutConstraint.constraints(withVisualFormat:
"H:|-[headingLabel]-|",
options: .alignAllCenterX,
metrics: nil,
views: views)
constraints += horizontalHeadingLabelConstraint
let verticalContinueButtonConstraint = NSLayoutConstraint.constraints(withVisualFormat:
"V:[continueButton(50)]-100-|",
options: [],
metrics: nil,
views: views)
constraints += verticalContinueButtonConstraint
let horizontalContinueButtonConstraint = NSLayoutConstraint.constraints(withVisualFormat:
"H:|-100-[continueButton]-100-|",
options: [],
metrics: nil,
views: views)
constraints += horizontalContinueButtonConstraint
view.addConstraints(constraints)
}
}
If you want to do this is better that you think about a mask.
To do that you must write the text into a bitmap context and use it as a mask on a solid color.
If found something that can help you here.
In few steps:
You create an image context
You set white color text to be used as as a mask
You draw the text inside the context
You create the mask
You create another image based on the solid color
You clip them
If you are using the storyboard builder. There is a colored box next to text color. Press that and there is a slider called opacity.
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)
}
}
I a have an overlay with a table in and I'd like to add a Tap gesture recogniser to the background to dismiss the view and also addTarget to a button within the overlay which does the same thing.
The overlay displays fine as expected, however whenever I tap the black background or the cancel button, nothing happens. I've searched for an answer here but nothing found has worked. My code is as follows, followed by a screenshot of the overlay:
class importedFileView: NSObject {
let blackView = UIView()
let importedFileContainerView: UIView = {
let importedFileContainerView = UIView(frame: .zero)
importedFileContainerView.backgroundColor = .white
importedFileContainerView.layer.cornerRadius = 10
importedFileContainerView.layer.masksToBounds = true
return importedFileContainerView
}()
let headerLabel: UILabel = {
let headerLabel = UILabel()
headerLabel.translatesAutoresizingMaskIntoConstraints = false
headerLabel.font = UIFont(name: "HelveticaNeue-Thin" , size: 24)
headerLabel.text = "Attach file"
headerLabel.textColor = .darkGray
headerLabel.adjustsFontSizeToFitWidth = true
return headerLabel
}()
let fileTableView: UITableView = {
let fileTableView = UITableView()
return fileTableView
}()
let updateDetailsButton: UIButton = {
let updateDetailsButton = UIButton()
updateDetailsButton.translatesAutoresizingMaskIntoConstraints = false
updateDetailsButton.backgroundColor = UIColor(r:40, g:86, b:131)
updateDetailsButton.setTitleColor(UIColor.white, for: .normal)
updateDetailsButton.setTitle("Attach selected files", for: .normal)
updateDetailsButton.titleLabel!.font = UIFont(name: "HelveticaNeue-Light" , size: 18)
updateDetailsButton.layer.cornerRadius = 2
return updateDetailsButton
}()
let cancelButton: UIButton = {
let cancelButton = UIButton()
cancelButton.translatesAutoresizingMaskIntoConstraints = false
cancelButton.backgroundColor = UIColor.white
cancelButton.setTitleColor(UIColor(r:40, g:86, b:131), for: .normal)
cancelButton.setTitle("Cancel", for: .normal)
cancelButton.titleLabel!.font = UIFont(name: "HelveticaNeue-Light" , size: 18)
cancelButton.layer.cornerRadius = 2
return cancelButton
}()
let frameHeight: CGFloat = 450
func showFormView(){
if let window = UIApplication.shared.keyWindow {
blackView.backgroundColor = UIColor(white: 0, alpha: 0.5)
window.addSubview(blackView)
window.addSubview(importedFileContainerView)
importedFileContainerView.addSubview(headerLabel)
importedFileContainerView.addSubview(fileTableView)
importedFileContainerView.addSubview(updateDetailsButton)
importedFileContainerView.addSubview(cancelButton)
cancelButton.addTarget(self, action: #selector(handleDismiss), for: .touchUpInside)
blackView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleDismiss)))
layoutViews()
fileTableView.frame = CGRect(x: 30, y: window.frame.height, width: window.frame.width - 60, height: 230)
let frameY = (window.frame.height - frameHeight) / 2
importedFileContainerView.frame = CGRect(x: 20, y: window.frame.height, width: window.frame.width - 40, height: self.frameHeight)
blackView.frame = window.frame
blackView.alpha = 0
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
self.blackView.alpha = 1
self.importedFileContainerView.frame = CGRect(x: 20, y: frameY, width: window.frame.width - 40, height: self.frameHeight)
}, completion: nil
)
}
}
func layoutViews(){
let views = ["v0" : headerLabel, "v1": fileTableView, "v2": updateDetailsButton, "v3": cancelButton]
let leftSpace = NSLayoutConstraint.constraints(withVisualFormat: "H:|-20.0-[v0]-20.0-|", options: NSLayoutFormatOptions(), metrics: nil, views: views)
let leftSpace1 = NSLayoutConstraint.constraints(withVisualFormat: "H:|-20.0-[v1]-20.0-|", options: NSLayoutFormatOptions(), metrics: nil, views: views)
let leftSpace2 = NSLayoutConstraint.constraints(withVisualFormat: "H:|-20.0-[v2]-20.0-|", options: NSLayoutFormatOptions(), metrics: nil, views: views)
let leftSpace3 = NSLayoutConstraint.constraints(withVisualFormat: "H:|-20.0-[v3]-20.0-|", options: NSLayoutFormatOptions(), metrics: nil, views: views)
let topSpacing = NSLayoutConstraint.constraints(withVisualFormat: "V:|-20.0-[v0(40)]-20.0-[v1(230)]-20.0-[v2(50)]-10.0-[v3(50)]-10.0-|", options: NSLayoutFormatOptions(), metrics: nil, views: views)
importedFileContainerView.addConstraints(topSpacing)
importedFileContainerView.addConstraints(leftSpace)
importedFileContainerView.addConstraints(leftSpace1)
importedFileContainerView.addConstraints(leftSpace2)
importedFileContainerView.addConstraints(leftSpace3)
}
func handleDismiss() {
UIView.animate(withDuration: 0.5,
delay: 0.0,
options: .curveEaseInOut,
animations: {
self.blackView.alpha = 0
if let window = UIApplication.shared.keyWindow {
self.importedFileContainerView.frame = CGRect(x: 20, y: window.frame.height, width: window.frame.width - 40, height: self.frameHeight)
}
},
completion: { [weak self] finished in
self?.blackView.removeFromSuperview()
self?.importedFileContainerView.removeFromSuperview()
})
}
override init() {
super.init()
}
}
self.blackView.isUserInteractionEnabled = true;
is all you need to add to the blackView (UIView).
Without that, the view doesn't have any interactions enabled and so the gesture recognizer's target/action isn't triggered.
Events are ignored.
https://developer.apple.com/reference/uikit/uiview/1622577-isuserinteractionenabled
You might also want to disable it during animations.
Are you keeping a strong reference to the instance of your importedFileView while your overlays are visible? As far as I tested, all actions are silently ignored when the target is lost.
For example, this does not work:
#IBAction func someAction(_ sender: Any) {
let ifv = importedFileView()
ifv.showFormView()
//`ifv` is released at the end of this method, then your overlays are shown...
}
This works:
let ifv = importedFileView() //keep the instance as a property of your ViewController.
#IBAction func someAction(_ sender: Any) {
ifv.showFormView()
}
Programmatically generated UIViews isUserInteractionEnabled is default to true. You have no need to explicitly set it to true.
By the way, you'd better not name your non-UIView class as ...View, and better make your type names start with capital letter, which makes your code more readable to experienced Swift programmers.
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
}
I have a UIButton in a uitableviewcell associated to a target:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as! ProCell
cell.btn.tag = indexPath.row
cell.btn.addTarget(self, action: "buttonClicked:", forControlEvents: UIControlEvents.TouchUpInside)
return cell
}
This is the buttonClicked function:
func buttonClicked(sender:UIButton) {
let boton = sender as UIButton
let index = boton.tag
let buttonPosition: CGPoint = boton.convertPoint(CGPointZero, toView: self.tableView)
var indexPath: NSIndexPath = self.tableView.indexPathForRowAtPoint(buttonPosition)!
let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! ProductoCell
cell.btn.setImage(UIImage (named: "rotacion-Null"), forState: UIControlState.Normal)
let indicador = UIActivityIndicatorView()
indicador.frame = CGRect(x: 0, y: 0, width: 25, height: 25)
indicador.color = UIColor(red: 153.0/255.0, green: 0.0, blue: 0.0, alpha: 1.0)
indicador.startAnimating()
cell.btn.addSubview(indicador)
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
let datosEd = ed.search(product)
dispatch_async(dispatch_get_main_queue(), {
//update UI in main thread once the loading is completed.
indicador.stopAnimating()
indicador.hidesWhenStopped = true
let label2 = UILabel(frame: CGRect(x: 15 , y: -5, width: 16, height: 16))
label2.textAlignment = NSTextAlignment.Center
label2.font = UIFont.boldSystemFontOfSize(13.0)
label2.backgroundColor = UIColor (red: 0.85, green: 0.20, blue: 0.33, alpha: 1.0)
label2.textColor = UIColor.whiteColor()
label2.layer.masksToBounds = true
label2.layer.cornerRadius = 8
let rowData = datosEd[0] as! NSDictionary
if rowData["art"] as! String == "No Results" {
label2.text = "0"
cell.contentView.addSubview(label2)
cell.btn.setImage(UIImage (named: "ed-25G"), forState: UIControlState.Normal)
} else {
label2.text = String(datosEd.count)
cell.btn.addSubview(label2)
cell.btn.setImage(UIImage (named: "ed-25R"), forState: UIControlState.Normal)
}
});
})
}
The problem is when I scroll down and scroll up back again, the subview(label2) is repeated in some cells.
Reading some responses think it has to do with the reuse of the cells, but I do not how to make the subviews are not repeated.
Some help, please... :-)