Is there any way to make a toast message in swift ?
I have tried in objective c but could not find solution in swift.
[self.view makeToast:@"Account created Successfully" duration:0.5 position:@"bottom"]; Is there any way to make a toast message in swift ?
I have tried in objective c but could not find solution in swift.
[self.view makeToast:@"Account created Successfully" duration:0.5 position:@"bottom"]; extension UIViewController { func showToast(message : String, font: UIFont) { let toastLabel = UILabel(frame: CGRect(x: self.view.frame.size.width/2 - 75, y: self.view.frame.size.height-100, width: 150, height: 35)) toastLabel.backgroundColor = UIColor.black.withAlphaComponent(0.6) toastLabel.textColor = UIColor.white toastLabel.font = font toastLabel.textAlignment = .center; toastLabel.text = message toastLabel.alpha = 1.0 toastLabel.layer.cornerRadius = 10; toastLabel.clipsToBounds = true self.view.addSubview(toastLabel) UIView.animate(withDuration: 4.0, delay: 0.1, options: .curveEaseOut, animations: { toastLabel.alpha = 0.0 }, completion: {(isCompleted) in toastLabel.removeFromSuperview() }) } } Use like this:
self.showToast(message: "Your Toast Message", font: .systemFont(ofSize: 12.0)) For Swift 4
My version of a Toast that uses layout constraints, with the advantage that it works for any text size, as is (based in the response of Tony Franzis):
Just call: Toast.show(message: "My message", myViewControllerName)
class Toast { static func show(message: String, controller: UIViewController) { let toastContainer = UIView(frame: CGRect()) toastContainer.backgroundColor = UIColor.black.withAlphaComponent(0.6) toastContainer.alpha = 0.0 toastContainer.layer.cornerRadius = 25; toastContainer.clipsToBounds = true let toastLabel = UILabel(frame: CGRect()) toastLabel.textColor = UIColor.white toastLabel.textAlignment = .center; toastLabel.font.withSize(12.0) toastLabel.text = message toastLabel.clipsToBounds = true toastLabel.numberOfLines = 0 toastContainer.addSubview(toastLabel) controller.view.addSubview(toastContainer) toastLabel.translatesAutoresizingMaskIntoConstraints = false toastContainer.translatesAutoresizingMaskIntoConstraints = false let a1 = NSLayoutConstraint(item: toastLabel, attribute: .leading, relatedBy: .equal, toItem: toastContainer, attribute: .leading, multiplier: 1, constant: 15) let a2 = NSLayoutConstraint(item: toastLabel, attribute: .trailing, relatedBy: .equal, toItem: toastContainer, attribute: .trailing, multiplier: 1, constant: -15) let a3 = NSLayoutConstraint(item: toastLabel, attribute: .bottom, relatedBy: .equal, toItem: toastContainer, attribute: .bottom, multiplier: 1, constant: -15) let a4 = NSLayoutConstraint(item: toastLabel, attribute: .top, relatedBy: .equal, toItem: toastContainer, attribute: .top, multiplier: 1, constant: 15) toastContainer.addConstraints([a1, a2, a3, a4]) let c1 = NSLayoutConstraint(item: toastContainer, attribute: .leading, relatedBy: .equal, toItem: controller.view, attribute: .leading, multiplier: 1, constant: 65) let c2 = NSLayoutConstraint(item: toastContainer, attribute: .trailing, relatedBy: .equal, toItem: controller.view, attribute: .trailing, multiplier: 1, constant: -65) let c3 = NSLayoutConstraint(item: toastContainer, attribute: .bottom, relatedBy: .equal, toItem: controller.view, attribute: .bottom, multiplier: 1, constant: -75) controller.view.addConstraints([c1, c2, c3]) UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseIn, animations: { toastContainer.alpha = 1.0 }, completion: { _ in UIView.animate(withDuration: 0.5, delay: 1.5, options: .curveEaseOut, animations: { toastContainer.alpha = 0.0 }, completion: {_ in toastContainer.removeFromSuperview() }) }) } } Toast.show(message: "My message", controller: self) I also had to change the c3 constraint to -150toItem: controller.view.safeAreaLayoutGuide then use the constant attribute to space it further away from tab or navigation bar. Thanks!!There is a 3rd party library that supports customizable toast notification with single line of code. Here is a simple example of it:
import Toast_Swift ... // basic usage self.view.makeToast("This is a piece of toast") // toast with a specific duration and position self.view.makeToast("This is a piece of toast", duration: 3.0, position: .top) https://github.com/scalessec/Toast-Swift
(Updated for Swift 3/4+)
I have two more solutions on Swift 5:
Best solution (in my opinion)
Advantage:
Disadvantages:
UILabel class to add indents. One could do without this by placing the UILabel in the UIVIew.Code:
class ToastLabel: UILabel { var textInsets = UIEdgeInsets.zero { didSet { invalidateIntrinsicContentSize() } } override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect { let insetRect = bounds.inset(by: textInsets) let textRect = super.textRect(forBounds: insetRect, limitedToNumberOfLines: numberOfLines) let invertedInsets = UIEdgeInsets(top: -textInsets.top, left: -textInsets.left, bottom: -textInsets.bottom, right: -textInsets.right) return textRect.inset(by: invertedInsets) } override func drawText(in rect: CGRect) { super.drawText(in: rect.inset(by: textInsets)) } } extension UIViewController { static let DELAY_SHORT = 1.5 static let DELAY_LONG = 3.0 func showToast(_ text: String, delay: TimeInterval = DELAY_LONG) { let label = ToastLabel() label.backgroundColor = UIColor(white: 0, alpha: 0.5) label.textColor = .white label.textAlignment = .center label.font = UIFont.systemFont(ofSize: 15) label.alpha = 0 label.text = text label.clipsToBounds = true label.layer.cornerRadius = 20 label.numberOfLines = 0 label.textInsets = UIEdgeInsets(top: 10, left: 15, bottom: 10, right: 15) label.translatesAutoresizingMaskIntoConstraints = false view.addSubview(label) let saveArea = view.safeAreaLayoutGuide label.centerXAnchor.constraint(equalTo: saveArea.centerXAnchor, constant: 0).isActive = true label.leadingAnchor.constraint(greaterThanOrEqualTo: saveArea.leadingAnchor, constant: 15).isActive = true label.trailingAnchor.constraint(lessThanOrEqualTo: saveArea.trailingAnchor, constant: -15).isActive = true label.bottomAnchor.constraint(equalTo: saveArea.bottomAnchor, constant: -30).isActive = true UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseIn, animations: { label.alpha = 1 }, completion: { _ in UIView.animate(withDuration: 0.5, delay: delay, options: .curveEaseOut, animations: { label.alpha = 0 }, completion: {_ in label.removeFromSuperview() }) }) } } How to use:
class MyController: UIViewController { override func viewDidLoad() { super.viewDidLoad() showToast("Message") } } Other solution
Advantage:
UIViewControllerDisadvantages:
Code:
class Helper { static let DELAY_SHORT = 1.5 static let DELAY_LONG = 3.0 static func showToast(_ text: String, delay: TimeInterval = DELAY_LONG) { guard let window = UIApplication.shared.keyWindow else { return } let label = BaseLabel() label.backgroundColor = UIColor(white: 0, alpha: 0.5) label.textColor = .white label.textAlignment = .center label.font = UIFont.systemFont(ofSize: 15) label.alpha = 0 label.text = text label.numberOfLines = 0 var vertical: CGFloat = 0 var size = label.intrinsicContentSize var width = min(size.width, window.frame.width - 60) if width != size.width { vertical = 10 label.textAlignment = .justified } label.textInsets = UIEdgeInsets(top: vertical, left: 15, bottom: vertical, right: 15) size = label.intrinsicContentSize width = min(size.width, window.frame.width - 60) label.frame = CGRect(x: 20, y: window.frame.height - 90, width: width, height: size.height + 20) label.center.x = window.center.x label.layer.cornerRadius = min(label.frame.height/2, 25) label.layer.masksToBounds = true window.addSubview(label) UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseIn, animations: { label.alpha = 1 }, completion: { _ in UIView.animate(withDuration: 0.5, delay: delay, options: .curveEaseOut, animations: { label.alpha = 0 }, completion: {_ in label.removeFromSuperview() }) }) } } How to use:
Helper.showToast("Message") label.heightAnchor.constraint(equalToConstant: 35).active = true to set the view height so the label will leave spacing above and below the text.TimeInterval does not exist, etc.Just add the method below. This will show message in different colors with animation (message appearing from left to right & disappear).
Swift 3.0 -
class Toast { class private func showAlert(backgroundColor:UIColor, textColor:UIColor, message:String) { let appDelegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate let label = UILabel(frame: CGRect.zero) label.textAlignment = NSTextAlignment.center label.text = message label.font = UIFont(name: "", size: 15) label.adjustsFontSizeToFitWidth = true label.backgroundColor = backgroundColor //UIColor.whiteColor() label.textColor = textColor //TEXT COLOR label.sizeToFit() label.numberOfLines = 4 label.layer.shadowColor = UIColor.gray.cgColor label.layer.shadowOffset = CGSize(width: 4, height: 3) label.layer.shadowOpacity = 0.3 label.frame = CGRect(x: appDelegate.window!.frame.size.width, y: 64, width: appDelegate.window!.frame.size.width, height: 44) label.alpha = 1 appDelegate.window!.addSubview(label) var basketTopFrame: CGRect = label.frame; basketTopFrame.origin.x = 0; UIView.animate(withDuration :2.0, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.1, options: UIViewAnimationOptions.curveEaseOut, animations: { () -> Void in label.frame = basketTopFrame }, completion: { (value: Bool) in UIView.animate(withDuration:2.0, delay: 2.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.1, options: UIViewAnimationOptions.curveEaseIn, animations: { () -> Void in label.alpha = 0 }, completion: { (value: Bool) in label.removeFromSuperview() }) }) } class func showPositiveMessage(message:String) { showAlert(backgroundColor: UIColor.green, textColor: UIColor.white, message: message) } class func showNegativeMessage(message:String) { showAlert(backgroundColor: UIColor.red, textColor: UIColor.white, message: message) } } Swift 5. If you want a simple toast implementation, please find the code below.
extension UIViewController{ func showToast(message : String, seconds: Double){ let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert) alert.view.backgroundColor = .black alert.view.alpha = 0.5 alert.view.layer.cornerRadius = 15 self.present(alert, animated: true) DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + seconds) { alert.dismiss(animated: true) } } } Call It from UIViewController
self.showToast(message: "Updating...", seconds: 1.0) What exactly you need is https://github.com/Rannie/Toast-Swift/blob/master/SwiftToastDemo/Toast/HRToast%2BUIView.swift .
Download the HRToast + UIView.swift class and drag and drop to project. Make sure you check 'copy items if needed' on dialogue box.
//Usage: self.view.makeToast(message: "Simple Toast") self.view.makeToast(message: "Simple Toast", duration: 2.0, position:HRToastPositionTop) self.view.makeToast(message: "Simple Toast", duration: 2.0, position: HRToastPositionCenter, image: UIImage(named: "ic_120x120")!) self.view.makeToast(message: "It is just awesome", duration: 2.0, position: HRToastPositionDefault, title: "Simple Toast") self.view.makeToast(message: "It is just awesome", duration: 2.0, position: HRToastPositionCenter, title: "Simple Toast", image: UIImage(named: "ic_120x120")!) self.view.makeToastActivity() self.view.makeToastActivity(position: HRToastPositionCenter) self.view.makeToastActivity(position: HRToastPositionDefault, message: "Loading") self.view.makeToastActivityWithMessage(message: "Loading") self.view.hr_setToastThemeColor(color: #ThemeColor) it is giving errorI have been using this extension when ever i need toast-message like android.. Just copy the extension to you project and then in your UIViewController class, call the function like
self.toastMessage("Downloading...") // Extention is below extension UIViewController { func toastMessage(_ message: String){ guard let window = UIApplication.shared.keyWindow else {return} let messageLbl = UILabel() messageLbl.text = message messageLbl.textAlignment = .center messageLbl.font = UIFont.systemFont(ofSize: 12) messageLbl.textColor = .white messageLbl.backgroundColor = UIColor(white: 0, alpha: 0.5) let textSize:CGSize = messageLbl.intrinsicContentSize let labelWidth = min(textSize.width, window.frame.width - 40) messageLbl.frame = CGRect(x: 20, y: window.frame.height - 90, width: labelWidth + 30, height: textSize.height + 20) messageLbl.center.x = window.center.x messageLbl.layer.cornerRadius = messageLbl.frame.height/2 messageLbl.layer.masksToBounds = true window.addSubview(messageLbl) DispatchQueue.main.asyncAfter(deadline: .now() + 1) { UIView.animate(withDuration: 1, animations: { messageLbl.alpha = 0 }) { (_) in messageLbl.removeFromSuperview() } } }} If the need is for a simple Toast message without fancy customization of font, alignment, text color, etc. then the following would do just fine
let messageVC = UIAlertController(title: "Message Title", message: "Account Created successfully" , preferredStyle: .actionSheet) present(messageVC, animated: true) { Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false, block: { (_) in messageVC.dismiss(animated: true, completion: nil)})} .actionSheet presents the alert from Bottom of the screen and the Timer takes care of the display duration. You can add this as an extension to UIViewController and then call it from anywhere.
if makeToast:duration:position: is defined in objective-c and can be called, then the swift code will be
self.view.makeToast("Acount created Successfully", duration: 0.5, position: "bottom") You may need to use a bridging header to gain access to those method in your swift code though.
@mr-bean code updated to latest Swift version (3.x)
let toastLabel = UILabel(frame: CGRect(x: self.view.frame.size.width/2 - 150, y: self.view.frame.size.height-100, width: 300, height: 35)) toastLabel.backgroundColor = UIColor.black toastLabel.textColor = UIColor.white toastLabel.textAlignment = NSTextAlignment.center self.view.addSubview(toastLabel) toastLabel.text = message toastLabel.alpha = 1.0 toastLabel.layer.cornerRadius = 10; toastLabel.clipsToBounds = true UIView.animate(withDuration: 4.0, animations: { toastLabel.alpha = 0.0 }) I have modified the @samo's answer with:
Proper variables name's
Leading and Trailing constraints changed to center constraint.
Now message will adjust its width according to message and it will be centred.
extension UIViewController { func showToast(message: String) { let toastContainer = UIView(frame: CGRect()) toastContainer.backgroundColor = UIColor.black.withAlphaComponent(0.6) toastContainer.alpha = 0.0 toastContainer.layer.cornerRadius = 20; toastContainer.clipsToBounds = true let toastLabel = UILabel(frame: CGRect()) toastLabel.textColor = UIColor.white toastLabel.textAlignment = .center; toastLabel.font.withSize(12.0) toastLabel.text = message toastLabel.clipsToBounds = true toastLabel.numberOfLines = 0 toastContainer.addSubview(toastLabel) self.view.addSubview(toastContainer) toastLabel.translatesAutoresizingMaskIntoConstraints = false toastContainer.translatesAutoresizingMaskIntoConstraints = false let centerX = NSLayoutConstraint(item: toastLabel, attribute: .centerX, relatedBy: .equal, toItem: toastContainer, attribute: .centerXWithinMargins, multiplier: 1, constant: 0) let lableBottom = NSLayoutConstraint(item: toastLabel, attribute: .bottom, relatedBy: .equal, toItem: toastContainer, attribute: .bottom, multiplier: 1, constant: -15) let lableTop = NSLayoutConstraint(item: toastLabel, attribute: .top, relatedBy: .equal, toItem: toastContainer, attribute: .top, multiplier: 1, constant: 15) toastContainer.addConstraints([centerX, lableBottom, lableTop]) let containerCenterX = NSLayoutConstraint(item: toastContainer, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1, constant: 0) let containerTrailing = NSLayoutConstraint(item: toastContainer, attribute: .width, relatedBy: .equal, toItem: toastLabel, attribute: .width, multiplier: 1.1, constant: 0) let containerBottom = NSLayoutConstraint(item: toastContainer, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1, constant: -75) self.view.addConstraints([containerCenterX,containerTrailing, containerBottom]) UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseIn, animations: { toastContainer.alpha = 1.0 }, completion: { _ in UIView.animate(withDuration: 0.5, delay: 1.5, options: .curveEaseOut, animations: { toastContainer.alpha = 0.0 }, completion: {_ in toastContainer.removeFromSuperview() }) }) } } extension UIViewController { func showToast(message:String,color:UIColor) { DispatchQueue.main.async { let toastLbl = UILabel(frame: CGRect(x: 20, y: self.view.frame.size.height - 100, width: self.view.frame.width - 40 , height: 30)) toastLbl.layer.cornerRadius = 8; toastLbl.clipsToBounds = true toastLbl.textColor = .white toastLbl.font = .systemFont(ofSize: 15) toastLbl.textAlignment = .center; toastLbl.text = message self.view.addSubview(toastLbl) toastLbl.backgroundColor = color UIView.animate(withDuration: 2.0, delay: 0, options: .transitionCurlDown, animations: { }, completion: {(isCompleted) in toastLbl.removeFromSuperview() }) } } } self.view.showToast(message: "Toast Shown", color: .green) I know there are accepted answers but they all seem to have a big flaw - if you show several toasts in a short period of time they will show on top of each other. Here is my implementation which takes this problem into consideration:
class Toast: UILabel { private let BOTTOM_MARGIN: CGFloat = 16 private let SIDE_MARGIN: CGFloat = 16 private let HEIGHT: CGFloat = 35 private let SHOW_TIME_SECONDS = TimeInterval(3) private let BACKGROUND_COLOR = UIColor.darkGray.withAlphaComponent(0.7).cgColor private let TEXT_COLOR = UIColor.white private let ANIMATION_DURATION_SEC = 0.33 private static var queue: [ToastHolder] = [] private static var showing: Toast? init(_ text: String) { super.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0)) self.text = text self.textColor = TEXT_COLOR textAlignment = .center self.layer.backgroundColor = BACKGROUND_COLOR self.layer.cornerRadius = 5 } public func show(_ parent: UIViewController) { frame = CGRect(x: SIDE_MARGIN, y: UIScreen.main.bounds.height - BOTTOM_MARGIN - HEIGHT, width: UIScreen.main.bounds.width - 2 * SIDE_MARGIN, height: HEIGHT) if Toast.showing == nil { Log.d("showing \(String(describing: text))") Toast.showing = self alpha = 0 parent.view.addSubview(self) UIView.animate(withDuration: ANIMATION_DURATION_SEC, animations: { self.alpha = 1 }, completion: { (completed) in Timer.scheduledTimer(timeInterval: self.SHOW_TIME_SECONDS, target: self, selector: #selector(self.onTimeout), userInfo: nil, repeats: false) }) } else { Toast.queue.append(ToastHolder(self, parent)) } } @objc func onTimeout() { UIView.animate(withDuration: ANIMATION_DURATION_SEC, animations: { self.alpha = 0 }, completion: { (completed) in Toast.showing = nil self.removeFromSuperview() if !Toast.queue.isEmpty { let holder = Toast.queue.removeFirst() holder.toast.show(holder.parent) } }) } required init?(coder aDecoder: NSCoder) { fatalError("this initializer is not supported") } private class ToastHolder { let toast: Toast let parent: UIViewController init(_ t: Toast, _ p: UIViewController) { toast = t parent = p } } } Usage:
Toast("my message").show(self) Hope it helps someone.
How about use Toaster
At a Glance
Toast(text: "Hello, world!").show() Setting delay and duration
Toast(text: "Hello, world!", duration: Delay.long) Toast(text: "Hello, world!", delay: Delay.short, duration: Delay.long) Removing Toast
let toast = Toast(text: "Hello") toast.show() toast.cancel() // remove toast immediately Customizing Appearance
Instead of using UILabel using UITextView gets better results.
func showToast(message: String) { let toastLabel = UITextView(frame: CGRect(x: self.view.frame.size.width/16, y: self.view.frame.size.height-150, width: self.view.frame.size.width * 7/8, height: 35)) toastLabel.backgroundColor = UIColor.black.withAlphaComponent(0.6) toastLabel.textColor = UIColor.white toastLabel.textAlignment = .center; toastLabel.text = " \(message) " toastLabel.alpha = 1.0 toastLabel.layer.cornerRadius = 10; toastLabel.clipsToBounds = true toastLabel.font = UIFont(name: (toastLabel.font?.fontName)!, size: 16) toastLabel.layoutEdgeInsets.left = 8 toastLabel.layoutEdgeInsets.right = 8 toastLabel.center.x = self.view.frame.size.width/2 self.view.addSubview(toastLabel) UIView.animate(withDuration: 5.0, delay: 0.1, options: .curveEaseOut, animations: { toastLabel.alpha = 0.0 }, completion: {(isCompleted) in toastLabel.removeFromSuperview() }) } Space is added with message to provide good spacing at the both ends so that it looks good. Modified version of answer of Mr.Bean
Step 1: Create a new Swift file for your custom toast view:
class ToastView: UIView { private var messageLabel: UILabel! init(message: String) { super.init(frame: CGRect.zero) configureUI(message: message) } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } private func configureUI(message: String) { // Customize your toast view's appearance backgroundColor = UIColor.black.withAlphaComponent(0.8) layer.cornerRadius = 10 clipsToBounds = true messageLabel = UILabel(frame: CGRect.zero) messageLabel.text = message messageLabel.textColor = UIColor.white messageLabel.numberOfLines = 0 messageLabel.textAlignment = .center messageLabel.font = UIFont.systemFont(ofSize: 15) addSubview(messageLabel) messageLabel.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ messageLabel.topAnchor.constraint(equalTo: topAnchor, constant: 8), messageLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16), messageLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16), messageLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8) ]) } } Step 2: To show the toast message, add the following extension to UIViewController:
extension UIViewController { func showToast(message: String, duration: TimeInterval = 2.0) { let toastView = ToastView(message: message) view.addSubview(toastView) toastView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ toastView.centerXAnchor.constraint(equalTo: view.centerXAnchor), toastView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -50), toastView.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor, constant: 20), toastView.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor, constant: -20) ]) DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + duration) { UIView.animate(withDuration: 0.3, animations: { toastView.alpha = 0 }, completion: { _ in toastView.removeFromSuperview() }) } } } Step 3: Now, in your view controller, you can use the showToast method to display the toast message:
// Example usage in your UIViewController: class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Call the showToast method to display a toast message showToast(message: "Hello, this is a toast message!") } } static func popUp(context ctx: UIViewController, msg: String) { let toast = UILabel(frame: CGRect(x: 16, y: ctx.view.frame.size.height / 2, width: ctx.view.frame.size.width - 32, height: 100)) toast.backgroundColor = UIColor.lightGray toast.textColor = UIColor.white toast.textAlignment = .center; toast.numberOfLines = 3 toast.font = UIFont.systemFont(ofSize: 20) toast.layer.cornerRadius = 12; toast.clipsToBounds = true toast.text = msg ctx.view.addSubview(toast) UIView.animate(withDuration: 5.0, delay: 0.2, options: .curveEaseOut, animations: { toast.alpha = 0.0 }, completion: {(isCompleted) in toast.removeFromSuperview() }) } Then just call it from UIViewController
popUp(context: self, msg: "Your message") Let me add this to this chain of answers: This library does what you need DCToastView allowing you to provide toast messages from the top or bottom side of the screen:
You will just need to add the pod
pod 'DCToastView'
Import it where you want to use it.
import DCToastView
And use it
ToastPresenter.shared.show(in: self.view, message: "This is a toast")
You can pass the following properties to the show method:
This will help for you it will make the toast at the center with proper padding
func showToast(message:String,view:UIView){ let toastLabel = PaddingLabel() toastLabel.frame = CGRect(x:0, y: view.frame.size.height-100, width: view.frame.width-50, height: 0) toastLabel.backgroundColor = UIColor.black.withAlphaComponent(0.6) toastLabel.textColor = UIColor.white toastLabel.textAlignment = .center; toastLabel.font = UIFont(name: "Montserrat-Light", size: 12.0) toastLabel.text = message toastLabel.alpha = 1.0 toastLabel.layer.cornerRadius = 10; toastLabel.clipsToBounds = true toastLabel.sizeToFit() toastLabel.frame.origin.x=(view.frame.width/2)-(toastLabel.frame.width/2) view.addSubview(toastLabel) UIView.animate(withDuration: 4.0, delay: 0.1, options: .curveEaseOut, animations: { toastLabel.alpha = 0.0 }, completion: {(isCompleted) in toastLabel.removeFromSuperview() }) } And add this PaddingLabel file for label padding
import Foundation import UIKit class PaddingLabel: UILabel { let padding=UIEdgeInsetsMake(5, 10, 5,10) override func drawText(in rect: CGRect) { super.drawText(in: UIEdgeInsetsInsetRect(rect, padding)) } override func sizeThatFits(_ size: CGSize) -> CGSize { let superSizeThatFits=super.sizeThatFits(size) let width=superSizeThatFits.width+padding.left+padding.right let height=superSizeThatFits.height+padding.top+padding.bottom return CGSize(width: width, height: height) } } Mr. Beans answer works well. However, his answer uses a small width & isn't multi-line friendly. Use this instead.
func showToastFaded(message : String) { let toastLabel = UILabel(frame: CGRect(x: self.view.frame.size.width/2 - 125, y: self.view.frame.size.height-100, width: 250, height: 35)) toastLabel.numberOfLines = 0 toastLabel.backgroundColor = UIColor.black.withAlphaComponent(0.6) toastLabel.textColor = UIColor.white toastLabel.textAlignment = .center; toastLabel.text = message toastLabel.alpha = 1.0 toastLabel.layer.cornerRadius = 10; toastLabel.clipsToBounds = true toastLabel.sizeToFit() toastLabel.frame = CGRect( x: toastLabel.frame.minX, y: toastLabel.frame.minY,width: toastLabel.frame.width + 20, height: toastLabel.frame.height + 8) self.view.addSubview(toastLabel) UIView.animate(withDuration: 4.0, delay: 0.1, options: .curveEaseOut, animations: { toastLabel.alpha = 0.0 }, completion: {(isCompleted) in toastLabel.removeFromSuperview() }) } The best and easiest way to add a toast on an iOS app is using this library called Loafjet. The library is really small(27kb), won't make much difference to your project. Try it!
I changed @Samo answer. Here it is, mine, quite simple. This is also landscape and long text friendly.
Toast.show(message: "Hello Toast", on: view) ..
class Toast { static func show(message: String, on baseView: UIView) { let containerView = UIView() containerView.backgroundColor = .black.withAlphaComponent(0.6) containerView.alpha = 0 containerView.layer.cornerRadius = 25 containerView.clipsToBounds = true let toastLabel = UILabel() toastLabel.textColor = .white toastLabel.textAlignment = .center toastLabel.font.withSize(12.0) toastLabel.text = message toastLabel.clipsToBounds = true toastLabel.numberOfLines = 0 baseView.addSubview(containerView) containerView.translatesAutoresizingMaskIntoConstraints = false containerView.leadingAnchor.constraint(greaterThanOrEqualTo: baseView.leadingAnchor, constant: 65).isActive = true containerView.trailingAnchor.constraint(lessThanOrEqualTo: baseView.trailingAnchor, constant: -65).isActive = true containerView.bottomAnchor.constraint(equalTo: baseView.safeAreaLayoutGuide.bottomAnchor, constant: -10).isActive = true containerView.centerXAnchor.constraint(equalTo: baseView.centerXAnchor).isActive = true containerView.addSubview(toastLabel) toastLabel.translatesAutoresizingMaskIntoConstraints = false toastLabel.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 15).isActive = true toastLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 15).isActive = true toastLabel.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -15).isActive = true toastLabel.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: -15).isActive = true UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseIn, animations: { containerView.alpha = 1 }, completion: { _ in UIView.animate(withDuration: 0.5, delay: 1.5, options: .curveEaseOut, animations: { containerView.alpha = 0 }, completion: { _ in containerView.removeFromSuperview() }) }) } } This is another way to do it.
func showToast(viewController: UIViewController?, message: String) { let alertDisapperTimeInSeconds = 3.0 let toastLabel = UILabel(frame: CGRect(x: self.view.frame.size.width/2 - 75, y: self.view.frame.size.height-100, width: 150, height: 35)) toastLabel.backgroundColor = UIColor.black.withAlphaComponent(0.6) toastLabel.textColor = UIColor.white toastLabel.font = .systemFont(ofSize: 14) toastLabel.textAlignment = .center; toastLabel.text = message toastLabel.alpha = 1.0 toastLabel.layer.cornerRadius = 10; toastLabel.clipsToBounds = true viewController?.view.addSubview(toastLabel) DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + alertDisapperTimeInSeconds) { toastLabel.alpha = 0.0 toastLabel.removeFromSuperview() } } How to access function
self.showToast(viewController: self, message: "I am a Toast Message") Swift 4.2 Very easy and super way
let toastLabel = UILabel() toastLabel.lineBreakMode = .byWordWrapping toastLabel.numberOfLines = 0 toastLabel.text = "Type your message you want to show in toast" toastLabel.sizeToFit() //MARK Resize the Label Frame toastLabel.frame = CGRect(x: toastLabel.frame.origin.x, y: toastLabel.frame.origin.y, width: toastLabel.frame.size.width + 40, height: toastLabel.frame.size.height + 40) self.view.addSubview(toastLabel) Here is my solution. Hope it helps for someone..
class Toasty { static let DELAY_SHORT = 2.0 static let DELAY_LONG = 4.0 static let BG_OPACITY: Double = 0.9 static let TOAST_HEIGHT = 20 static let TOAST_WIDTH = 24 static let TOAST_ADJUSTMENT = 96 static let FONT_SIZE = 16 enum Gravity { case bottom case center case top } enum Delay { case short case long } static func showToast(_ message: String, _ txtColor: UIColor, _ bgColor: UIColor, _ position: Gravity, _ delay: Delay) { guard let window = UIApplication.shared.keyWindow else { return } let label = ToastyLabel() label.textColor = txtColor label.backgroundColor = bgColor label.textAlignment = .center label.font = UIFont.systemFont(ofSize: CGFloat(FONT_SIZE)) label.alpha = 0 label.text = message label.numberOfLines = 0 var vertical: CGFloat = 0 var size = label.intrinsicContentSize var width = min(size.width, window.frame.width - 60) if width != size.width { vertical = 1000 label.textAlignment = .justified } label.textInsets = UIEdgeInsets(top: vertical, left: 15, bottom: vertical, right: 15) size = label.intrinsicContentSize width = min(size.width, window.frame.width - 60) if (position == Gravity.bottom) { label.frame = CGRect(x: CGFloat(TOAST_WIDTH), y: window.frame.height - CGFloat(TOAST_ADJUSTMENT), width: width, height: size.height + CGFloat(TOAST_HEIGHT)) } else if (position == Gravity.center) { label.frame = CGRect(x: CGFloat(TOAST_WIDTH), y: window.frame.height / 2, width: width, height: size.height + CGFloat(TOAST_HEIGHT)) } else if (position == Gravity.top) { label.frame = CGRect(x: CGFloat(TOAST_WIDTH), y: CGFloat(TOAST_ADJUSTMENT), width: width, height: size.height + CGFloat(TOAST_HEIGHT)) } label.center.x = window.center.x label.layer.cornerRadius = min(label.frame.height / 2, 32) label.layer.masksToBounds = true window.addSubview(label) UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseIn, animations: { label.alpha = 1 }, completion: { _ in UIView.animate(withDuration: 0.5, delay: delay == Delay.long ? DELAY_LONG : DELAY_SHORT, options: .curveEaseOut, animations: { label.alpha = 0 }, completion: {_ in label.removeFromSuperview() }) }) } class func regular(msg: String, position: Gravity, delay: Delay) { showToast(msg, UIColor(.white), UIColor(.black.opacity(BG_OPACITY)), position, delay) } class func info(msg: String, position: Gravity, delay: Delay) { showToast(String("\u{24D8}")+" "+msg, UIColor.white, UIColor(Color(red: 0/255, green: 100/255, blue: 225/255).opacity(BG_OPACITY)), position, delay) } class func alert(msg: String, position: Gravity, delay: Delay) { showToast(String("\u{26A0}")+" "+msg, UIColor.black, UIColor(Color(red: 255/255, green: 175/255, blue: 0/255).opacity(BG_OPACITY)), position, delay) } class func success(msg: String, position: Gravity, delay: Delay) { showToast(String("\u{2705}")+" "+msg, UIColor.white, UIColor(Color(red: 0/255, green: 150/255, blue: 0/255).opacity(BG_OPACITY)), position, delay) } class func error(msg: String, position: Gravity, delay: Delay) {//2757 showToast(String("\u{274C}")+" "+msg, UIColor.white, UIColor(Color(red: 175/255, green: 0/255, blue: 0/255).opacity(BG_OPACITY)), position, delay) } } class ToastyLabel: UILabel { var textInsets = UIEdgeInsets.zero { didSet { invalidateIntrinsicContentSize() } } override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect { let insetRect = bounds.inset(by: textInsets) let textRect = super.textRect(forBounds: insetRect, limitedToNumberOfLines: numberOfLines) let invertedInsets = UIEdgeInsets(top: -textInsets.top, left: -textInsets.left, bottom: -textInsets.bottom, right: -textInsets.right) return textRect.inset(by: invertedInsets) } override func drawText(in rect: CGRect) { super.drawText(in: rect.inset(by: textInsets)) } } Usage:
@State var increment = 0 ZStack { Button(action: { increment += 1 if increment == 1 { Toasty.info(msg: "Info Toasty", position: .bottom, delay: .short) } else if increment == 2 { Toasty.alert(msg: "Alert Toasty", position: .top, delay: .short) } else if increment == 3 { Toasty.success(msg: "Success Toasty", position: .center, delay: .short) } else if increment == 4 { Toasty.error(msg: "Error Toasty", position: .bottom, delay: .short) } else if increment == 5 { Toasty.regular(msg: "Regular Toasty", position: .top, delay: .short) increment = 0 } }, label: { Text("Show Toasty") .padding(12) .background(RoundedRectangle(cornerRadius: 8) .stroke(Color.blue, lineWidth: 1)) })} ToastLabel? It's used in your code, but has no definition. I guess should be ToastyLabel, right?ToastyLabel (typo error) and import SwiftUI to work on it. Sorry and Thank you for point out.