Est-il possible de faire passer un message à Toast dans Swift?
J'ai essayé dans l'Objectif C mais je n'ai pas trouvé de solution dans Swift.
[self.view makeToast:@"Account created Successfully"
duration:0.5
position:@"bottom"];
extension UIViewController {
func showToast(message : String) {
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.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
self.view.addSubview(toastLabel)
UIView.animate(withDuration: 4.0, delay: 0.1, options: .curveEaseOut, animations: {
toastLabel.alpha = 0.0
}, completion: {(isCompleted) in
toastLabel.removeFromSuperview()
})
} }
Pour Swift 4
Ma version d'un Toast qui utilise des contraintes de présentation, avec l'avantage de fonctionner pour n'importe quelle taille de texte, telle quelle (basée sur la réponse de Tony Franzis):
Il suffit d'appeler: 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()
})
})
}
}
Ajoutez juste la méthode ci-dessous. Ceci affichera un message de différentes couleurs avec animation (le message apparaît de gauche à droite et disparaît).
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)
}
}
Ce dont vous avez exactement besoin est https://github.com/Rannie/Toast-Swift/blob/master/SwiftToastDemo/Toast/HRToast%2BUIView.Swift .
Téléchargez la classe HRToast + UIView.Swift et faites-la glisser pour la projeter. Assurez-vous de cocher "Copier les éléments si nécessaire" dans la boîte de dialogue.
//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")
Swift 4
func showToast(message : String) {
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.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
self.view.addSubview(toastLabel)
UIView.animate(withDuration: 4.0, delay: 0.1, options: .curveEaseOut, animations: {
toastLabel.alpha = 0.0
}, completion: {(isCompleted) in
toastLabel.removeFromSuperview()
})
}
Appelez la fonction comme
self.showToast(message: "Data Save.")
Il existe une bibliothèque tierce qui prend en charge la notification de pain grillé personnalisable avec une seule ligne de code. En voici un exemple simple:
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
(Mise à jour pour Swift 3/4 +)
si makeToast:duration:position:
est défini dans objective-c et peut être appelé, le code Swift sera alors
self.view.makeToast("Acount created Successfully", duration: 0.5, position: "bottom")
Vous devrez peut-être utiliser un en-tête bridging pour accéder à ces méthodes dans votre code Swift.
@ mr-bean code mis à jour vers la dernière version de Swift (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
})
J'utilise cette extension chaque fois que j'ai besoin d'un toast-message comme Android .. Copiez simplement l'extension dans votre projet, puis dans votre classe UIViewController, appelez la fonction comme
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()
}
}
}}
Si vous avez besoin d’un simple message Toast sans personnalisation sophistiquée de la police, de l’alignement, de la couleur du texte, etc.
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
présente l'alerte depuis le bas de l'écran et le minuteur se charge de la durée d'affichage. Vous pouvez l'ajouter comme extension à UIViewController, puis l'appeler de n'importe où.
J'ai deux autres solutions sur Swift 5:
meilleure solution (à mon avis)
Avantage:
Inconvénients:
UILabel
pour ajouter des retraits. On pourrait s'en passer en plaçant la UILabel
dans la 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()
})
})
}
}
Comment utiliser:
class MyController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
showToast("Message")
}
}
Autre solution
Avantage:
UIViewController
Inconvénients:
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()
})
})
}
}
Comment utiliser:
Helper.showToast("Message")
Je sais qu'il existe des réponses acceptées, mais elles semblent toutes présenter un gros défaut: si vous montrez plusieurs toasts sur une courte période, ils apparaîtront l'un sur l'autre. Voici ma mise en œuvre qui prend en compte ce problème:
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)
J'espère que ça aide quelqu'un.
Au lieu d'utiliser UILabel
, l'utilisation de UITextView
permet d'obtenir de meilleurs résultats.
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()
})
}
L'espace est ajouté avec un message pour fournir un bon espacement aux deux extrémités afin qu'il soit beau . Version modifiée de la réponse de Mr.Bean
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()
})
}
Puis appelez-le simplement depuis UIViewController
popUp(context: self, msg: "Your message")
Cela vous aidera à faire le pain au centre avec un rembourrage approprié
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()
})
}
Et ajoutez ce fichier PaddingLabel pour le remplissage des étiquettes
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)
}
}