ios 快速自定义警报 (UIAlertView)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25379559/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 01:55:37  来源:igfitidea点击:

Custom Alert (UIAlertView) with swift

iosswiftuialertview

提问by Pedro Manfredi

How can i create a custom alert with Swift? I try translating a guide from Objective c but loads a full screen layout

如何使用 Swift 创建自定义警报?我尝试从 Objective c 翻译指南,但加载了全屏布局

for do it easy i can load a new layout with the transparent background i try this:

为了简单起见,我可以加载一个带有透明背景的新布局,我试试这个:

    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)

in the animation it's transparent but when the animation ends it's opaque... and i turn off opaque option in the view... what i'm doing wrong?

在动画中它是透明的,但是当动画结束时它是不透明的......我关闭了视图中的不透明选项......我做错了什么?

回答by Suragch

Code tested in Swift 5 and Xcode 10

在 Swift 5 和 Xcode 10 中测试的代码

How to make your own custom Alert

如何制作自己的自定义警报

I was wanting to do something similar. First of all, UIAlertViewis deprecated in favor of UIAlertController. See this answer for the standard way to display an alert:

我想做类似的事情。首先,UIAlertView不赞成使用UIAlertController. 有关显示警报的标准方式,请参阅此答案:

And both UIAlertViewand UIAlertControllerdo not really allow much customization. One option is to use some third party code. However, I discovered that it isn't that difficult to create your own Alert by displaying another view controller modaly.

两者UIAlertViewUIAlertController没有真正让多少定制。一种选择是使用一些第三方代码。但是,我发现通过显示另一个视图控制器模式来创建自己的警报并不难。

The example here is just a proof-of-concept. You can design your alert any way you want.

这里的例子只是一个概念验证。您可以按照自己的意愿设计警报。

enter image description here

在此处输入图片说明

Storyboard

故事板

You should have two View Controllers. Your second view controller will be your alert. Set the class name to AlertViewContollerand the Storyboard ID to alert. (Both of these are names that we defined ourselves in the code below, nothing special about them. You can add the code first if you want. It might actually be easier if you add the code first.)

你应该有两个视图控制器。您的第二个视图控制器将成为您的警报。将类名设置为AlertViewContoller,将故事板 ID 设置为alert。(这两个都是我们在下面的代码中自己定义的名字,没有什么特别之处。如果你愿意,你可以先添加代码。如果你先添加代码,实际上可能会更容易一些。)

enter image description here

在此处输入图片说明

Set the background color for the root view (in your Alert View Controller) to clear (or translucent black is nice for an alert). Add another UIViewand center it with constraints. Use that as your alert background and put whatever you want inside. For my example, I added a UIButton.

将根视图的背景颜色(在您的警报视图控制器中)设置为清除(或半透明黑色适合警报)。添加另一个UIView并使用约束将其居中。使用它作为你的警报背景,并把你想要的放在里面。对于我的示例,我添加了一个UIButton.

enter image description here

在此处输入图片说明

Code

代码

ViewController.swift

视图控制器.swift

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

AlertViewController.swift

import UIKit
class AlertViewController: UIViewController {

    @IBAction func dismissButtonTapped(_ sender: UIButton) {
        self.dismiss(animated: true, completion: nil)
    }
}

Don't forget to hook up the outlets.

不要忘记连接插座。

You can add an onTouchUpevent listener to the background view to dismiss the popup when the user clicks outside of it.

您可以onTouchUp向背景视图添加一个事件侦听器,以在用户在其外部单击时关闭弹出窗口。

That's it. You should be able to make any sort of alert that you can imagine now. No need for third party code.

就是这样。您应该能够发出您现在可以想象的任何类型的警报。无需第三方代码。

Here is another custom alert I made. Still ugly, but it shows more things you can do.

这是我制作的另一个自定义警报。仍然很丑,但它表明你可以做更多的事情。

enter image description here

在此处输入图片说明

Other options

其他选项

Sometimes there is no need to reinvent the wheel, though. I'm impressed with the third party project SDCAlertView(MIT license). It is written in Swift but you can use it with Objective-C projects as well. It offers a wide range of customability.

不过,有时没有必要重新发明轮子。我对第三方项目SDCAlertView(MIT 许可证)印象深刻。它是用 Swift 编写的,但你也可以在 Objective-C 项目中使用它。它提供了广泛的可定制性。

回答by fs_tigre

Here is the Swift 3code. Thanks a lot @Suragch for the awesome approach to create a custom AlertView.

这是Swift 3代码。非常感谢@Suragch 为创建自定义 AlertView 提供了很棒的方法。

ViewController.swift

视图控制器.swift

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

AlertViewController.swift

import UIKit
class AlertViewController: UIViewController {

    @IBAction func dismissButtonTapped(sender: UIButton) {
        self.dismiss(animated: true, completion: nil)
    }
}

To make it a little more interesting or to make the default effect in iOS, you could add either a VisualEffectView or change the color of the main UIView to a dark color and set its alpha to 70%. I prefer the second approach since the blur effect is not as smooth as the one with the view with 70 alpha.

为了使它更有趣或在 iOS 中设置默认效果,您可以添加 VisualEffectView 或将主 UIView 的颜色更改为深色并将其 alpha 设置为 70%。我更喜欢第二种方法,因为模糊效果不如使用 70 alpha 的视图平滑。

Effect with VisualEffectView:

VisualEffectView 效果:

enter image description here

在此处输入图片说明

Effect using a UIView with 70 Alpha:

使用 70 Alpha 的 UIView 效果:

enter image description here

在此处输入图片说明

回答by Shantaram Kokate

Use https://github.com/shantaramk/Custom-Alert-View

使用https://github.com/shantaramk/Custom-Alert-View

It is effortless to implement this. Follow the steps below:

实现这一点毫不费力。请按照以下步骤操作:

  1. Drag down the AlertView folder in project directory

  2. Show AlertView Popup

  1. 将项目目录下的AlertView文件夹往下拉

  2. 显示 AlertView 弹出窗口

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)
}


回答by matt

Nowadays, an alert is merely a simple presented view controller. You can write a presented view controller that behaves similarly to an alert — that is, it pops onto the screen and dims whatever is behind it — but it's yourview controller and you are free to give it any interface you like.

如今,警报只是一个简单的呈现视图控制器。你可以编写一个呈现的视图控制器,它的行为类似于警报——也就是说,它弹出到屏幕上并使后面的任何东西变暗——但它是你的视图控制器,你可以自由地给它任何你喜欢的界面。

To get you started, I've written a github projectthat you can download and run, and modify to suit your actual needs.

为了让您开始,我编写了一个github 项目,您可以下载和运行该项目,并根据您的实际需要进行修改。

I'll show the key part of the code. The "alert" view controller, in its initializers, sets its own modal presentation style as customand sets a transitioning delegate:

我将展示代码的关键部分。“警报”视图控制器在其初始值设定项中将其自己的模式呈现样式custom设置为并设置转换委托:

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")
    }
}

All the work is done by the transitioning delegate:

所有工作都由过渡委托完成:

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)
            }
        }

    }
}

It looks like a lot of code, and I suppose it is, but it's almost entire confined to a single class, which is entirely boilerplate; just copy and paste. All youhave to do is write the internal interface and behavior of your "alert" view controller, giving it buttons and text and whatever else you want, just as you would do for any other view controller.

它看起来像很多代码,我想是的,但它几乎完全局限于一个类,完全是样板;只需复制和粘贴。所有所要做的就是写你的“警报”视图控制器的内部接口和行为,给它的按钮和文本和其他任何你想要的,就像你对任何其他视图控制器做。

回答by Praveen Reddy

Custom Alert UIView Class in swift 4. And Usage ##

swift 4 中的自定义警报 UIView 类。和用法##

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()
    }
    }

strong text
## Usage Of Custom Alert with Tabbar.

强文本
##使用 Tabbar 自定义警报

    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!)
            }
            }