Custom Alert (UIAlertView) with swift
如何使用Swift创建自定义警报? 我尝试翻译来自Objective c的指南,但加载全屏布局
为了容易,我可以加载具有透明背景的新布局,我尝试这样做:
1 2 3 4 5 6 7 8 9 10 | listaalertviewcontroller.view.backgroundColor = UIColor.clearColor() let purple = UIColor.purpleColor() // 1.0 alpha let semi = purple.colorWithAlphaComponent(0.5) listaalertviewcontroller.view.backgroundColor = semi presentingViewController.modalPresentationStyle = UIModalPresentationStyle.CurrentContext self.presentViewController(listaalertviewcontroller, animated: true, completion: nil) |
在动画中它是透明的,但是当动画结束时它是不透明的...而我在视图中关闭了不透明选项...我在做什么错?
在Swift 5和Xcode 10中经过测试的代码
如何制作自己的自定义提醒
我想做类似的事情。首先,不推荐使用
- 如何在Swift中创建UIAlertView?
而且
这里的例子只是一个概念证明。您可以根据需要设计警报。
故事板
您应该有两个View Controller。您的第二个视图控制器将成为您的警报。将类名称设置为
将根视图的背景色(在"警报视图控制器"中)设置为清除(或半透明的黑色对于警报而言是不错的选择)。添加另一个
码
ViewController.swift
1 2 3 4 5 6 7 8 9 10 11 12 | import UIKit class ViewController: UIViewController { @IBAction func showAlertButtonTapped(_ sender: UIButton) { let storyboard = UIStoryboard(name:"Main", bundle: nil) let myAlert = storyboard.instantiateViewController(withIdentifier:"alert") myAlert.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext myAlert.modalTransitionStyle = UIModalTransitionStyle.crossDissolve self.present(myAlert, animated: true, completion: nil) } } |
AlertViewController.swift
1 2 3 4 5 6 7 | import UIKit class AlertViewController: UIViewController { @IBAction func dismissButtonTapped(_ sender: UIButton) { self.dismiss(animated: true, completion: nil) } } |
不要忘记挂上插座。
您可以将
而已。您应该能够发出现在可以想象的任何警报。无需第三方代码。
这是我制作的另一个自定义提醒。仍然很难看,但是它显示了您可以做的更多事情。
其他选择
但是,有时不需要重新发明轮子。第三方项目SDCAlertView(MIT许可证)给我留下了深刻的印象。它是用Swift编写的,但是您也可以将它用于Objective-C项目。它提供了广泛的可定制性。
这是Swift 3代码。非常感谢@Suragch提供了一种很棒的方法来创建自定义AlertView。
ViewController.swift
1 2 3 4 5 6 7 8 9 10 11 12 | import UIKit class ViewController: UIViewController { @IBAction func showAlertButtonTapped(sender: UIButton) { let storyboard = UIStoryboard(name:"Main", bundle: nil) let myAlert = storyboard.instantiateViewController(withIdentifier:"storyboardID") myAlert.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext myAlert.modalTransitionStyle = UIModalTransitionStyle.crossDissolve self.present(myAlert, animated: true, completion: nil) } |
AlertViewController.swift
1 2 3 4 5 6 7 | import UIKit class AlertViewController: UIViewController { @IBAction func dismissButtonTapped(sender: UIButton) { self.dismiss(animated: true, completion: nil) } } |
为了使其更加有趣或在iOS中设置默认效果,您可以添加VisualEffectView或将主UIView的颜色更改为深色,并将其alpha设置为70%。我喜欢第二种方法,因为模糊效果不如使用70 Alpha的视图平滑。
使用VisualEffectView的效果:
使用带有70 Alpha的UIView的效果:
Swift 4中的自定义Alert UIView类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | import UIKit class Dialouge: UIView { @IBOutlet weak var lblTitle: UILabel! @IBOutlet weak var lblDescription: UILabel! @IBOutlet weak var btnLeft: UIButton! @IBOutlet weak var btnRight: UIButton! @IBOutlet weak var viewBg: UIButton! var leftAction = {} var rightAction = {} override func draw(_ rect: CGRect) { self.btnRight.layer.cornerRadius = self.btnRight.frame.height/2 self.btnLeft.layer.cornerRadius = self.btnLeft.frame.height/2 self.btnLeft.layer.borderWidth = 1.0 self.btnLeft.layer.borderColor = #colorLiteral(red: 0.267678082, green: 0.2990377247, blue: 0.7881471515, alpha: 1) } @IBAction func leftAction(_ sender: Any) { leftAction() } @IBAction func rightAction(_ sender: Any) { rightAction() } @IBAction func bgTapped(_ sender: Any) { self.removeFromSuperview() } } |
强文本
##使用Tabbar的自定义警报。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | let custView = Bundle.main.loadNibNamed("Dialouge", owner: self, options: nil)![0] as? Dialouge custView?.lblDescription.text ="Are you sure you want to delete post?" custView?.lblTitle.text ="Delete Post" custView?.btnLeft.setTitle("Yes", for: .normal) custView?.btnRight.setTitle("No", for: .normal) custView?.leftAction = { self.deletePost(postId: self.curr_post.id,completion: { custView?.removeFromSuperview() }) } custView?.rightAction = { custView?.removeFromSuperview() } if let tbc = self.parentt?.tabBarController { custView?.frame = tbc.view.frame DispatchQueue.main.async { tbc.view.addSubview(custView!) } }else if let tbc = self.parView?.parenttprof { custView?.frame = tbc.view.frame DispatchQueue.main.async { tbc.view.addSubview(custView!) } } else { custView?.frame = self.parView?.view.frame ?? CGRect.zero DispatchQueue.main.async { self.parView?.view.addSubview(custView!) } } |
如今,警报仅仅是一个简单的呈现视图控制器。您可以编写一个呈现的视图控制器,其行为类似于警报-即它弹出到屏幕上并使背后的任何内容变暗-但它是您的视图控制器,您可以随意提供任何喜欢的界面。
为使您入门,我编写了一个github项目,您可以下载并运行该项目,并对其进行修改以适合您的实际需求。
我将展示代码的关键部分。"警报"视图控制器在其初始值设定项中将其自身的模式表示样式设置为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class CustomAlertViewController : UIViewController { let transitioner = CAVTransitioner() override init(nibName: String?, bundle: Bundle?) { super.init(nibName: nibName, bundle: bundle) self.modalPresentationStyle = .custom self.transitioningDelegate = self.transitioner } convenience init() { self.init(nibName:nil, bundle:nil) } required init?(coder: NSCoder) { fatalError("NSCoding not supported") } } |
所有工作均由过渡的代表完成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | class CAVTransitioner : NSObject, UIViewControllerTransitioningDelegate { func presentationController( forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? { return MyPresentationController( presentedViewController: presented, presenting: presenting) } } class MyPresentationController : UIPresentationController { func decorateView(_ v:UIView) { // iOS 8 doesn't have this // v.layer.borderColor = UIColor.blue.cgColor // v.layer.borderWidth = 2 v.layer.cornerRadius = 8 let m1 = UIInterpolatingMotionEffect( keyPath:"center.x", type:.tiltAlongHorizontalAxis) m1.maximumRelativeValue = 10.0 m1.minimumRelativeValue = -10.0 let m2 = UIInterpolatingMotionEffect( keyPath:"center.y", type:.tiltAlongVerticalAxis) m2.maximumRelativeValue = 10.0 m2.minimumRelativeValue = -10.0 let g = UIMotionEffectGroup() g.motionEffects = [m1,m2] v.addMotionEffect(g) } override func presentationTransitionWillBegin() { self.decorateView(self.presentedView!) let vc = self.presentingViewController let v = vc.view! let con = self.containerView! let shadow = UIView(frame:con.bounds) shadow.backgroundColor = UIColor(white:0, alpha:0.4) shadow.alpha = 0 con.insertSubview(shadow, at: 0) shadow.autoresizingMask = [.flexibleWidth, .flexibleHeight] let tc = vc.transitionCoordinator! tc.animate(alongsideTransition: { _ in shadow.alpha = 1 }) { _ in v.tintAdjustmentMode = .dimmed } } override func dismissalTransitionWillBegin() { let vc = self.presentingViewController let v = vc.view! let con = self.containerView! let shadow = con.subviews[0] let tc = vc.transitionCoordinator! tc.animate(alongsideTransition: { _ in shadow.alpha = 0 }) { _ in v.tintAdjustmentMode = .automatic } } override var frameOfPresentedViewInContainerView : CGRect { // we want to center the presented view at its"native" size // I can think of a lot of ways to do this, // but here we just assume that it *is* its native size let v = self.presentedView! let con = self.containerView! v.center = CGPoint(x: con.bounds.midX, y: con.bounds.midY) return v.frame.integral } override func containerViewWillLayoutSubviews() { // deal with future rotation // again, I can think of more than one approach let v = self.presentedView! v.autoresizingMask = [ .flexibleTopMargin, .flexibleBottomMargin, .flexibleLeftMargin, .flexibleRightMargin ] v.translatesAutoresizingMaskIntoConstraints = true } } extension CAVTransitioner { // UIViewControllerTransitioningDelegate func animationController( forPresented presented:UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { return self } func animationController( forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { return self } } extension CAVTransitioner : UIViewControllerAnimatedTransitioning { func transitionDuration( using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 0.25 } func animateTransition( using transitionContext: UIViewControllerContextTransitioning) { let con = transitionContext.containerView let v1 = transitionContext.view(forKey: .from) let v2 = transitionContext.view(forKey: .to) // we are using the same object (self) as animation controller // for both presentation and dismissal // so we have to distinguish the two cases if let v2 = v2 { // presenting con.addSubview(v2) let scale = CGAffineTransform(scaleX: 1.6, y: 1.6) v2.transform = scale v2.alpha = 0 UIView.animate(withDuration: 0.25, animations: { v2.alpha = 1 v2.transform = .identity }) { _ in transitionContext.completeTransition(true) } } else if let v1 = v1 { // dismissing UIView.animate(withDuration: 0.25, animations: { v1.alpha = 0 }) { _ in transitionContext.completeTransition(true) } } } } |
它看起来像很多代码,我想是的,但是几乎全部都局限于一个类,它完全是样板。只需复制并粘贴。您所要做的就是编写"警报"视图控制器的内部界面和行为,为它提供按钮和文本以及您想要的任何其他内容,就像对其他任何视图控制器所做的一样。
使用https://github.com/shantaramk/Custom-Alert-View
毫不费力地实现这一点。只需按照以下步骤操作:
向下拖动项目目录中的AlertView文件夹
显示AlertView弹出窗口
1 2 3 4 5 6 7 | func showUpdateProfilePopup(_ message: String) { let alertView = AlertView(title: AlertMessage.success, message: message, okButtonText: LocalizedStrings.okay, cancelButtonText:"") { (_, button) in if button == .other { self.navigationController?.popViewController(animated: true) } } alertView.show(animated: true) |
}