【问题标题】:Displaying a message in iOS which has the same functionality as Toast in Android在 iOS 中显示与 Android 中的 Toast 具有相同功能的消息
【发布时间】:2013-09-11 22:02:32
【问题描述】:

我需要知道 iOS 中是否有任何方法类似于 Android 中的 Toast 消息。也就是说,我需要显示几秒钟后自动关闭的消息。这类似于 Android 环境中 Toast 类的功能。

【问题讨论】:

标签: android ios


【解决方案1】:

您可以使用MBProgressHUD 项目。

使用 HUD 模式 MBProgressHUDModeText 进行类似 toast 的行为,

MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES];

// Configure for text only and offset down
hud.mode = MBProgressHUDModeText;
hud.label.text = @"Some message...";
hud.margin = 10.f;
hud.yOffset = 150.f;
hud.removeFromSuperViewOnHide = YES;

[hud hideAnimated:YES afterDelay:3];

【讨论】:

  • 对于 100% 类似 Android 的行为,我建议设置 hud.isUserInteractionEnabled = false,以便您可以在消息显示时与应用程序的其余部分进行交互。
  • @MattiaC。我无法为 hud.isUserInteractionEnabled = false 设置值,看起来只提供了 getter。
  • 它阻塞了 UI。它与 Android 的行为不同
  • 使用 hud.offset = CGPoint(x: 0, y: MBProgressMaxOffset) 将 HUD 定位在底部边缘。
【解决方案2】:
NSString *message = @"Some message...";

UIAlertView *toast = [[UIAlertView alloc] initWithTitle:nil
                                                message:message
                                               delegate:nil
                                      cancelButtonTitle:nil
                                      otherButtonTitles:nil, nil];
[toast show];
        
int duration = 1; // duration in seconds
        
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, duration * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    [toast dismissWithClickedButtonIndex:0 animated:YES];
});

在 iOS 9 或更高版本中使用 UIAlertViewController

NSString *message = @"Some message...";

UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil
                                                               message:message
                                                        preferredStyle:UIAlertControllerStyleAlert];

[self presentViewController:alert animated:YES completion:nil];

int duration = 1; // duration in seconds

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, duration * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
    [alert dismissViewControllerAnimated:YES completion:nil];
});

Swift 3.2

let message = "Some message..."
let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
self.present(alert, animated: true)
    
// duration in seconds
let duration: Double = 5
    
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + duration) {
    alert.dismiss(animated: true)
}

【讨论】:

  • 这与 toast 不完全相同 - 显示对话框时,用户与其他视图的交互被禁用。也许有一种方法可以删除“灰色”背景,增加与屏幕上其他视图交互的能力(比如我在警报后面的情况下的按钮或绘画画布)?
  • UIAlertView 在 iOS9 中已被弃用。有没有其他方法可以做到这一点?
  • 谢谢,但我可以使用 UIAlertController 来显示 toast 吗?
【解决方案3】:

在 Android 中,Toast 是一条短消息,会在屏幕上显示一小段时间,然后自动消失,而不会中断用户与应用的交互。

所以很多有 Android 背景的人都想知道 iOS 版本的 Toast 是什么。除了当前的问题,其他类似的问题可以找到hereherehere。答案是 iOS 中没有与 Toast 完全相同的功能。但是,已经提出了各种解决方法,包括

  • 使用 UIView 制作自己的 Toast(请参阅 herehereherehere
  • 导入模仿 Toast 的第三方项目(请参阅herehereherehere
  • 使用带有计时器的无按钮警报(请参阅here

不过,我的建议是坚持使用 iOS 已经提供的标准 UI 选项。不要试图让您的应用程序的外观和行为与 Android 版本完全相同。想想如何重新打包它,让它看起来和感觉就像一个 iOS 应用程序。有关一些选择,请参阅以下链接。

考虑以传达相同信息的方式重新设计 UI。或者,如果信息非常重要,那么Alert 可能就是答案。

【讨论】:

  • 说得很好,尤其是重新设计 UI 的概念。对于开发人员或设计师来说,这绝对不是最简单的答案,但 Toasts 很容易成为另一个移动 UX 的“垃圾抽屉”,经常被用作 1) 健谈和分散注意力的内容的垃圾场,或者 2) 真正有用的信息,以及因此,将应用程序的主要内容元素作为徽章、图标或内联状态消息在直接上下文中呈现会更好。
【解决方案4】:

斯威夫特 4

这个小技巧怎么样?

func showToast(controller: UIViewController, message : String, seconds: Double) {
    let alert = UIAlertController(title: nil, message: message, preferredStyle: .alert)
    alert.view.backgroundColor = UIColor.black
    alert.view.alpha = 0.6
    alert.view.layer.cornerRadius = 15

    controller.present(alert, animated: true)

    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + seconds) {
        alert.dismiss(animated: true)
    }
}

调用示例:

showToast(controller: self, message : "This is a test", seconds: 2.0)

输出:

【讨论】:

  • 看起来棒极了。谢谢!
  • 嗨 Sazzad,问题很明显,它需要一个 NavigationController。我只是想提出来。也许我的评论是错误的和过时的
  • 很高兴听到你修复了
  • 非常感谢,非常精确的解决方案
【解决方案5】:

斯威夫特 3

对于没有第三方代码的简单解决方案:

只需使用普通的 UIAlertController 但样式 = actionSheet(查看下面的代码)

let alertDisapperTimeInSeconds = 2.0
let alert = UIAlertController(title: nil, message: "Toast!", preferredStyle: .actionSheet)
self.present(alert, animated: true)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + alertDisapperTimeInSeconds) {
  alert.dismiss(animated: true)
}

此方案的优势:

  1. Android like Toast 消息
  2. 仍然是 iOS 外观

【讨论】:

  • 聪明人。我从来没有想过这个,谢谢:D
【解决方案6】:

对于 Swift 3 和 4

使用Toaster

Toast(text: "Hello, world!", duration: Delay.long)

对于 Swift 2

使用JLToast

【讨论】:

    【解决方案7】:

    如果你想要一个 iOS 风格的,从 Github 下载这个框架

    iOS Toast Alert View Framework

    一旦你导入了框架,这个例子就可以在你的 UIViewController 上运行。

    示例 1:

    //Manual 
    let tav = ToastAlertView()
    tav.message = "Hey!"
    tav.image = UIImage(named: "img1")!
    tav.show()
    //tav.dismiss() to Hide
    

    示例 2:

    //Toast Alert View with Time Dissmis Only
    self.showToastAlert("5 Seconds",
                    image: UIImage(named: "img1")!,
                    hideWithTap: false,
                    hideWithTime: true,
                    hideTime: 5.0)
    

    决赛:

    【讨论】:

      【解决方案8】:

      斯威夫特 4.0:

      制作一个新的 swift 文件。 (文件-新建-文件-空 Swift 文件)。将其命名为 UIViewToast。添加以下代码。

      import UIKit
      
      func /(lhs: CGFloat, rhs: Int) -> CGFloat {
      return lhs / CGFloat(rhs)
      }
      
      let HRToastDefaultDuration  =   2.0
      let HRToastFadeDuration     =   0.2
      let HRToastHorizontalMargin : CGFloat  =   10.0
      let HRToastVerticalMargin   : CGFloat  =   10.0
      
      let HRToastPositionDefault  =   "bottom"
      let HRToastPositionTop      =   "top"
      let HRToastPositionCenter   =   "center"
      
      // activity
      let HRToastActivityWidth  :  CGFloat  = 100.0
      let HRToastActivityHeight :  CGFloat  = 100.0
      let HRToastActivityPositionDefault    = "center"
      
      // image size
      let HRToastImageViewWidth :  CGFloat  = 80.0
      let HRToastImageViewHeight:  CGFloat  = 80.0
      
      // label setting
      let HRToastMaxWidth       :  CGFloat  = 0.8;      // 80% of parent view width
      let HRToastMaxHeight      :  CGFloat  = 0.8;
      let HRToastFontSize       :  CGFloat  = 16.0
      let HRToastMaxTitleLines              = 0
      let HRToastMaxMessageLines            = 0
      
      // shadow appearance
      let HRToastShadowOpacity  : CGFloat   = 0.8
      let HRToastShadowRadius   : CGFloat   = 6.0
      let HRToastShadowOffset   : CGSize    = CGSize(width: 4.0, height: 4.0)
      
      let HRToastOpacity        : CGFloat   = 0.5
      let HRToastCornerRadius   : CGFloat   = 10.0
      
      var HRToastActivityView: UnsafePointer<UIView>?
      var HRToastTimer: UnsafePointer<Timer>?
      var HRToastView: UnsafePointer<UIView>?
      
      
      // Color Scheme
      let HRAppColor:UIColor = UIColor.black//UIappViewController().appUIColor
      let HRAppColor_2:UIColor = UIColor.white
      
      
      let HRToastHidesOnTap       =   true
      let HRToastDisplayShadow    =   false
      
      //HRToast (UIView + Toast using Swift)
      
      extension UIView {
      
      //public methods
      func makeToast(message msg: String) {
          self.makeToast(message: msg, duration: HRToastDefaultDuration, position: HRToastPositionDefault as AnyObject)
      }
      
      func makeToast(message msg: String, duration: Double, position: AnyObject) {
          let toast = self.viewForMessage(msg: msg, title: nil, image: nil)
          self.showToast(toast: toast!, duration: duration, position: position)
      }
      
      func makeToast(message msg: String, duration: Double, position: AnyObject, title: String) {
          let toast = self.viewForMessage(msg: msg, title: title, image: nil)
          self.showToast(toast: toast!, duration: duration, position: position)
      }
      
      func makeToast(message msg: String, duration: Double, position: AnyObject, image: UIImage) {
          let toast = self.viewForMessage(msg: msg, title: nil, image: image)
          self.showToast(toast: toast!, duration: duration, position: position)
      }
      
      func makeToast(message msg: String, duration: Double, position: AnyObject, title: String, image: UIImage) {
          let toast = self.viewForMessage(msg: msg, title: title, image: image)
          self.showToast(toast: toast!, duration: duration, position: position)
      }
      
      func showToast(toast: UIView) {
          self.showToast(toast: toast, duration: HRToastDefaultDuration, position: HRToastPositionDefault as AnyObject)
      }
      
      func showToast(toast: UIView, duration: Double, position: AnyObject) {
          let existToast = objc_getAssociatedObject(self, &HRToastView) as! UIView?
          if existToast != nil {
              if let timer: Timer = objc_getAssociatedObject(existToast!, &HRToastTimer) as? Timer {
                  timer.invalidate();
              }
              self.hideToast(toast: existToast!, force: false);
          }
      
          toast.center = self.centerPointForPosition(position: position, toast: toast)
          toast.alpha = 0.0
      
          if HRToastHidesOnTap {
              let tapRecognizer = UITapGestureRecognizer(target: toast, action: #selector(handleToastTapped(recognizer:)))
              toast.addGestureRecognizer(tapRecognizer)
              toast.isUserInteractionEnabled = true;
              toast.isExclusiveTouch = true;
          }
      
          self.addSubview(toast)
          objc_setAssociatedObject(self, &HRToastView, toast, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
      
          UIView.animate(withDuration: HRToastFadeDuration,
                                     delay: 0.0, options: ([.curveEaseOut, .allowUserInteraction]),
                                     animations: {
                                      toast.alpha = 1.0
          },
                                     completion: { (finished: Bool) in
                                      let timer = Timer.scheduledTimer(timeInterval: duration, target: self, selector: #selector(self.toastTimerDidFinish(timer:)), userInfo: toast, repeats: false)
                                      objc_setAssociatedObject(toast, &HRToastTimer, timer, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
          })
      }
      
      func makeToastActivity() {
          self.makeToastActivity(position: HRToastActivityPositionDefault as AnyObject)
      }
      
      func showToastActivity() {
          self.isUserInteractionEnabled = false
          self.makeToastActivity()
      }
      
      func removeToastActivity() {
          self.isUserInteractionEnabled = true
          self.hideToastActivity()
      
      }
      
      func makeToastActivityWithMessage(message msg: String){
          self.makeToastActivity(position: HRToastActivityPositionDefault as AnyObject, message: msg)
      }
      func makeToastActivityWithMessage(message msg: String,addOverlay: Bool){
      
          self.makeToastActivity(position: HRToastActivityPositionDefault as AnyObject, message: msg,addOverlay: true)
      }
      
      func makeToastActivity(position pos: AnyObject, message msg: String = "",addOverlay overlay: Bool = false) {
          let existingActivityView: UIView? = objc_getAssociatedObject(self, &HRToastActivityView) as? UIView
          if existingActivityView != nil { return }
      
          let activityView = UIView(frame: CGRect(x:0, y:0, width: self.frame.width, height: self.frame.height))
          activityView.center = self.centerPointForPosition(position: pos, toast: activityView)
          activityView.alpha = 0.0
          activityView.autoresizingMask = ([.flexibleLeftMargin, .flexibleTopMargin, .flexibleRightMargin, .flexibleBottomMargin])
          activityView.layer.cornerRadius = HRToastCornerRadius
      
          if HRToastDisplayShadow {
              activityView.layer.shadowColor = UIColor.black.cgColor
              activityView.layer.shadowOpacity = Float(HRToastShadowOpacity)
              activityView.layer.shadowRadius = HRToastShadowRadius
              activityView.layer.shadowOffset = HRToastShadowOffset
          }
      
          let activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
          activityIndicatorView.center = CGPoint(x:activityView.bounds.size.width / 2, y: activityView.bounds.size.height / 2)
          activityIndicatorView.color = HRAppColor
          activityView.addSubview(activityIndicatorView)
          activityIndicatorView.startAnimating()
      
          if (!msg.isEmpty){
              activityIndicatorView.frame.origin.y -= 10
      
      
      
              let activityMessageLabel = UILabel(frame: CGRect(x: activityView.bounds.origin.x, y: (activityIndicatorView.frame.origin.y + activityIndicatorView.frame.size.height + 10), width: activityView.bounds.size.width, height: 20))
              activityMessageLabel.textColor = UIColor.white
              activityMessageLabel.font = (msg.count<=10) ? UIFont(name:activityMessageLabel.font.fontName, size: 16) : UIFont(name:activityMessageLabel.font.fontName, size: 16)
              activityMessageLabel.textAlignment = .center
              activityMessageLabel.text = msg + ".."
              if overlay {
                  activityMessageLabel.textColor = UIColor.white
                  activityView.backgroundColor = HRAppColor.withAlphaComponent(HRToastOpacity)
                  activityIndicatorView.color = UIColor.white
              }
              else {
                  activityMessageLabel.textColor = HRAppColor
                  activityView.backgroundColor = UIColor.clear
                  activityIndicatorView.color = HRAppColor
              }
      
              activityView.addSubview(activityMessageLabel)
      
          }
      
          self.addSubview(activityView)
      
          // associate activity view with self
          objc_setAssociatedObject(self, &HRToastActivityView, activityView, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
      
          UIView.animate(withDuration: HRToastFadeDuration,
                                     delay: 0.0,
                                     options: UIViewAnimationOptions.curveEaseOut,
                                     animations: {
                                      activityView.alpha = 1.0
          },
                                     completion: nil)
          self.isUserInteractionEnabled = false
      }
      
      func hideToastActivity() {
          self.isUserInteractionEnabled = true
          let existingActivityView = objc_getAssociatedObject(self, &HRToastActivityView) as! UIView?
          if existingActivityView == nil { return }
          UIView.animate(withDuration: HRToastFadeDuration,
                                     delay: 0.0,
                                     options: UIViewAnimationOptions.curveEaseOut,
                                     animations: {
                                      existingActivityView!.alpha = 0.0
          },
                                     completion: { (finished: Bool) in
                                      existingActivityView!.removeFromSuperview()
                                      objc_setAssociatedObject(self, &HRToastActivityView, nil, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
          })
      }
      
      /*
       *  private methods (helper)
       */
      func hideToast(toast: UIView) {
          self.isUserInteractionEnabled = true
          self.hideToast(toast: toast, force: false);
      }
      
      func hideToast(toast: UIView, force: Bool) {
          let completeClosure = { (finish: Bool) -> () in
              toast.removeFromSuperview()
              objc_setAssociatedObject(self, &HRToastTimer, nil, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
          }
      
          if force {
              completeClosure(true)
          } else {
              UIView.animate(withDuration: HRToastFadeDuration,
                                         delay: 0.0,
                                         options: ([.curveEaseIn, .beginFromCurrentState]),
                                         animations: {
                                          toast.alpha = 0.0
              },
                                         completion:completeClosure)
          }
      }
      
      @objc func toastTimerDidFinish(timer: Timer) {
          self.hideToast(toast: timer.userInfo as! UIView)
      }
      
      @objc func handleToastTapped(recognizer: UITapGestureRecognizer) {
      
          // var timer = objc_getAssociatedObject(self, &HRToastTimer) as! NSTimer
          // timer.invalidate()
      
          self.hideToast(toast: recognizer.view!)
      }
      
      func centerPointForPosition(position: AnyObject, toast: UIView) -> CGPoint {
          if position is String {
              let toastSize = toast.bounds.size
              let viewSize  = self.bounds.size
              if position.lowercased == HRToastPositionTop {
                  return CGPoint(x: viewSize.width/2, y: toastSize.height/2 + HRToastVerticalMargin)
      
              } else if position.lowercased == HRToastPositionDefault {
                  return CGPoint(x:viewSize.width/2, y:viewSize.height - toastSize.height - 15 - HRToastVerticalMargin)
              } else if position.lowercased == HRToastPositionCenter {
                  return CGPoint(x:viewSize.width/2, y:viewSize.height/2)
              }
          } else if position is NSValue {
              return position.cgPointValue
          }
      
          print("Warning: Invalid position for toast.")
          return self.centerPointForPosition(position: HRToastPositionDefault as AnyObject, toast: toast)
      }
      
      func viewForMessage(msg: String?, title: String?, image: UIImage?) -> UIView? {
          if msg == nil && title == nil && image == nil { return nil }
      
          var msgLabel: UILabel?
          var titleLabel: UILabel?
          var imageView: UIImageView?
      
          let wrapperView = UIView()
          wrapperView.autoresizingMask = ([.flexibleLeftMargin, .flexibleRightMargin, .flexibleTopMargin, .flexibleBottomMargin])
          wrapperView.layer.cornerRadius = HRToastCornerRadius
          wrapperView.backgroundColor = UIColor.black.withAlphaComponent(HRToastOpacity)
      
          if HRToastDisplayShadow {
              wrapperView.layer.shadowColor = UIColor.black.cgColor
              wrapperView.layer.shadowOpacity = Float(HRToastShadowOpacity)
              wrapperView.layer.shadowRadius = HRToastShadowRadius
              wrapperView.layer.shadowOffset = HRToastShadowOffset
          }
      
          if image != nil {
              imageView = UIImageView(image: image)
              imageView!.contentMode = .scaleAspectFit
              imageView!.frame = CGRect(x:HRToastHorizontalMargin, y: HRToastVerticalMargin, width: CGFloat(HRToastImageViewWidth), height: CGFloat(HRToastImageViewHeight))
          }
      
          var imageWidth: CGFloat, imageHeight: CGFloat, imageLeft: CGFloat
          if imageView != nil {
              imageWidth = imageView!.bounds.size.width
              imageHeight = imageView!.bounds.size.height
              imageLeft = HRToastHorizontalMargin
          } else {
              imageWidth  = 0.0; imageHeight = 0.0; imageLeft   = 0.0
          }
      
          if title != nil {
              titleLabel = UILabel()
              titleLabel!.numberOfLines = HRToastMaxTitleLines
              titleLabel!.font = UIFont.boldSystemFont(ofSize: HRToastFontSize)
              titleLabel!.textAlignment = .center
              titleLabel!.lineBreakMode = .byWordWrapping
              titleLabel!.textColor = UIColor.white
              titleLabel!.backgroundColor = UIColor.clear
              titleLabel!.alpha = 1.0
              titleLabel!.text = title
      
              // size the title label according to the length of the text
      
              let maxSizeTitle = CGSize(width: (self.bounds.size.width * HRToastMaxWidth) - imageWidth, height: self.bounds.size.height * HRToastMaxHeight)
      
              let expectedHeight = title!.stringHeightWithFontSize(fontSize: HRToastFontSize, width: maxSizeTitle.width)
              titleLabel!.frame = CGRect(x: 0.0, y: 0.0, width: maxSizeTitle.width, height: expectedHeight)
          }
      
          if msg != nil {
              msgLabel = UILabel();
              msgLabel!.numberOfLines = HRToastMaxMessageLines
              msgLabel!.font = UIFont.systemFont(ofSize: HRToastFontSize)
              msgLabel!.lineBreakMode = .byWordWrapping
              msgLabel!.textAlignment = .center
              msgLabel!.textColor = UIColor.white
              msgLabel!.backgroundColor = UIColor.clear
              msgLabel!.alpha = 1.0
              msgLabel!.text = msg
      
      
              let maxSizeMessage = CGSize(width: (self.bounds.size.width * HRToastMaxWidth) - imageWidth, height: self.bounds.size.height * HRToastMaxHeight)
              let expectedHeight = msg!.stringHeightWithFontSize(fontSize: HRToastFontSize, width: maxSizeMessage.width)
              msgLabel!.frame = CGRect(x: 0.0, y: 0.0, width: maxSizeMessage.width, height: expectedHeight)
          }
      
          var titleWidth: CGFloat, titleHeight: CGFloat, titleTop: CGFloat, titleLeft: CGFloat
          if titleLabel != nil {
              titleWidth = titleLabel!.bounds.size.width
              titleHeight = titleLabel!.bounds.size.height
              titleTop = HRToastVerticalMargin
              titleLeft = imageLeft + imageWidth + HRToastHorizontalMargin
          } else {
              titleWidth = 0.0; titleHeight = 0.0; titleTop = 0.0; titleLeft = 0.0
          }
      
          var msgWidth: CGFloat, msgHeight: CGFloat, msgTop: CGFloat, msgLeft: CGFloat
          if msgLabel != nil {
              msgWidth = msgLabel!.bounds.size.width
              msgHeight = msgLabel!.bounds.size.height
              msgTop = titleTop + titleHeight + HRToastVerticalMargin
              msgLeft = imageLeft + imageWidth + HRToastHorizontalMargin
          } else {
              msgWidth = 0.0; msgHeight = 0.0; msgTop = 0.0; msgLeft = 0.0
          }
      
          let largerWidth = max(titleWidth, msgWidth)
          let largerLeft  = max(titleLeft, msgLeft)
      
          // set wrapper view's frame
          let wrapperWidth  = max(imageWidth + HRToastHorizontalMargin * 2, largerLeft + largerWidth + HRToastHorizontalMargin)
          let wrapperHeight = max(msgTop + msgHeight + HRToastVerticalMargin, imageHeight + HRToastVerticalMargin * 2)
          wrapperView.frame = CGRect(x: 0.0, y: 0.0, width: wrapperWidth, height: wrapperHeight)
      
          // add subviews
          if titleLabel != nil {
              titleLabel!.frame = CGRect(x: titleLeft, y: titleTop, width: titleWidth, height: titleHeight)
              wrapperView.addSubview(titleLabel!)
          }
          if msgLabel != nil {
              msgLabel!.frame = CGRect(x: msgLeft, y: msgTop, width: msgWidth, height: msgHeight)
              wrapperView.addSubview(msgLabel!)
          }
          if imageView != nil {
              wrapperView.addSubview(imageView!)
          }
      
          return wrapperView
          }
      
          }
      
      extension String {
      
      func stringHeightWithFontSize(fontSize: CGFloat,width: CGFloat) -> CGFloat {
          let font = UIFont.systemFont(ofSize: fontSize)
          let size = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)
          let paragraphStyle = NSMutableParagraphStyle()
          paragraphStyle.lineBreakMode = .byWordWrapping;
          let attributes = [NSAttributedStringKey.font:font,
                            NSAttributedStringKey.paragraphStyle:paragraphStyle.copy()]
      
          let text = self as NSString
          let rect = text.boundingRect(with: size, options:.usesLineFragmentOrigin, attributes: attributes, context:nil)
          return rect.size.height
      }
      }
      

      用法:

        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")
      
        // Hide Toast
        self.view.hideToast(toast: self.view)
        self.view.hideToast(toast: self.view, force: true)
        self.view.hideToastActivity()
      

      【讨论】:

      • 这段代码中的错误太多.. .Center 到 center, whiteColor 到 white, animateWithDuration 到 animate(duration, 错误太多.. 请修复它..
      【解决方案9】:

      对于使用 Xamarin.IOS 的用户,您可以这样做:

      new UIAlertView(null, message, null, "OK", null).Show();
      

      使用 UIKit;是必需的。

      【讨论】:

        【解决方案10】:

        对我来说,这个解决方案很好用: https://github.com/cruffenach/CRToast

        使用示例:

            NSDictionary *options = @{
                                  kCRToastTextKey : @"Hello World!",
                                  kCRToastTextAlignmentKey : @(NSTextAlignmentCenter),
                                  kCRToastBackgroundColorKey : [UIColor redColor],
                                  kCRToastAnimationInTypeKey : @(CRToastAnimationTypeGravity),
                                  kCRToastAnimationOutTypeKey : @(CRToastAnimationTypeGravity),
                                  kCRToastAnimationInDirectionKey : @(CRToastAnimationDirectionLeft),
                                  kCRToastAnimationOutDirectionKey : @(CRToastAnimationDirectionRight)
                                  };
        [CRToastManager showNotificationWithOptions:options
                                    completionBlock:^{
                                        NSLog(@"Completed");
                                    }];
        

        【讨论】:

          【解决方案11】:

          用于 3 秒延迟的 Swift 4 语法:

          present(alertController, animated: true, completion: nil)
          
          DispatchQueue.main.asyncAfter(deadline: .now() + 3) {                 
              self.dismiss(animated: true, completion: nil)     
          } 
          

          【讨论】:

          • 哇。我遇到了这种问题,您的代码让我知道该怎么做。谢谢:)
          【解决方案12】:

          使用 3 秒后消散的 Alert 快速实现 Android Toast。

              func showAlertView(title: String?, message: String?) {
              let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
              let okAction = UIAlertAction(title: "OK", style: .Cancel, handler: nil)
              alertController.addAction(okAction)
              self.presentViewController(alertController, animated: true, completion: nil)
          
          
              let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(3 * Double(NSEC_PER_SEC)))
              dispatch_after(delayTime, dispatch_get_main_queue()) {
                  print("Bye. Lovvy")
                  alertController.dismissViewControllerAnimated(true, completion: nil)
              }
          }
          

          简单地说:

          self.showAlertView("Message sent...", message: nil)
          

          【讨论】:

            【解决方案13】:

            对于 Swift 2.0 并考虑 https://stackoverflow.com/a/5079536/6144027

                            //TOAST
                            let alertController = UIAlertController(title: "", message: "This is a Toast.LENGTH_SHORT", preferredStyle: .Alert)
                            self!.presentViewController(alertController, animated: true, completion: nil)
                            let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(2.0 * Double(NSEC_PER_SEC)))
                            dispatch_after(delayTime, dispatch_get_main_queue()) {
                                alertController.dismissViewControllerAnimated(true, completion: nil)
                            }
            

            【讨论】:

              【解决方案14】:

              这是您的解决方案:
              将下面的代码放入您的 Xcode 项目并享受,

              - (void)showMessage:(NSString*)message atPoint:(CGPoint)point {
              const CGFloat fontSize = 16;
              
              UILabel* label = [[UILabel alloc] initWithFrame:CGRectZero];
              label.backgroundColor = [UIColor clearColor];
              label.font = [UIFont fontWithName:@"Helvetica-Bold" size:fontSize];
              label.text = message;
              label.textColor = UIColorFromRGB(0x07575B);
              [label sizeToFit];
              
              label.center = point;
              
              [self.view addSubview:label];
              
              [UIView animateWithDuration:0.3 delay:1 options:0 animations:^{
                  label.alpha = 0;
              } completion:^(BOOL finished) {
                  label.hidden = YES;
                  [label removeFromSuperview];
              }];
              }
              

              如何使用?

              [self showMessage:@"Toast in iOS" atPoint:CGPointMake(160, 695)];
              

              【讨论】:

                【解决方案15】:

                再次,如果在 Xamarin 上使用 IOS,组件存储中有一个名为 BTProgressHUD 的新组件

                【讨论】:

                  【解决方案16】:

                  1) 从this link下载toast-notifications-ios

                  2) 转到 Targets -> Build Phases 并将 -fno-objc-arc 添加到相关文件的“compiler Sources”中

                  3) 做一个函数和#import "iToast.h"

                  -(void)showToast :(NSString *)strMessage {
                      iToast * objiTost = [iToast makeText:strMessage];
                      [objiTost setFontSize:11];
                      [objiTost setDuration:iToastDurationNormal];
                      [objiTost setGravity:iToastGravityBottom];
                      [objiTost show];
                  }
                  

                  4) 在需要显示 toast 消息的地方调用

                  [self showToast:@"This is example text."];
                  

                  【讨论】:

                    【解决方案17】:

                    我想出了一个简单的烤面包方法!使用不带按钮的 UIAlertController!我们使用按钮文本作为我们的信息!得到它? 见以下代码:

                    func alert(title: String?, message: String?, bdy:String) {
                        let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)
                        let okAction = UIAlertAction(title: bdy, style: .Cancel, handler: nil)
                        alertController.addAction(okAction)
                            self.presentViewController(alertController, animated: true, completion: nil)
                    
                    
                        let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(2 * Double(NSEC_PER_SEC)))
                        dispatch_after(delayTime, dispatch_get_main_queue()) {
                            //print("Bye. Lovvy")
                            alertController.dismissViewControllerAnimated(true, completion: nil) 
                        }    
                    }
                    

                    像这样使用它:

                    self.alert(nil,message:nil,bdy:"Simple Toast!") // toast
                    self.alert(nil,message:nil,bdy:"Alert") // alert with "Alert" button
                    

                    【讨论】:

                      【解决方案18】:

                      这就是我在 Swift 3.0 中所做的。我创建了 UIView 扩展并调用了 self.view.showToast(message: "Message Here", duration: 3.0)self.view.hideToast()

                      extension UIView{
                      var showToastTag :Int {return 999}
                      
                      //Generic Show toast
                      func showToast(message : String, duration:TimeInterval) {
                      
                          let toastLabel = UILabel(frame: CGRect(x:0, y:0, width: (self.frame.size.width)-60, height:64))
                      
                          toastLabel.backgroundColor = UIColor.gray
                          toastLabel.textColor = UIColor.black
                          toastLabel.numberOfLines = 0
                          toastLabel.layer.borderColor = UIColor.lightGray.cgColor
                          toastLabel.layer.borderWidth = 1.0
                          toastLabel.textAlignment = .center;
                          toastLabel.font = UIFont(name: "HelveticaNeue", size: 17.0)
                          toastLabel.text = message
                          toastLabel.center = self.center
                          toastLabel.isEnabled = true
                          toastLabel.alpha = 0.99
                          toastLabel.tag = showToastTag
                          toastLabel.layer.cornerRadius = 10;
                          toastLabel.clipsToBounds  =  true
                          self.addSubview(toastLabel)
                      
                          UIView.animate(withDuration: duration, delay: 0.1, options: .curveEaseOut, animations: {
                              toastLabel.alpha = 0.95
                          }, completion: {(isCompleted) in
                              toastLabel.removeFromSuperview()
                          })
                      }
                      
                      //Generic Hide toast
                      func hideToast(){
                          if let view = self.viewWithTag(self.showToastTag){
                              view.removeFromSuperview()
                          }
                        }
                      }
                      

                      【讨论】:

                        【解决方案19】:

                        如果您想要纯 Swift,我们发布了我们的内部文件。很简单

                        https://github.com/gglresearchanddevelopment/ios-toast

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2011-12-09
                          • 2014-07-04
                          • 1970-01-01
                          • 1970-01-01
                          • 2011-07-15
                          相关资源
                          最近更新 更多