【问题标题】:UIAlertController Action Sheet without Blurry View Effect没有模糊视图效果的 UIAlertController 操作表
【发布时间】:2017-10-05 00:29:56
【问题描述】:

我正在使用UIAlertController 执行某些操作。

但我不喜欢动作组视图中的模糊视图效果(见下面的截图)。

我正在尝试消除这种模糊效果。我在网上做了一些研究,在UIAlertController 中找不到任何可以消除这种模糊效果的API。另外,根据他们的苹果文档here

UIAlertController 类旨在按原样使用,不支持子类化。此类的视图层次结构是私有的,不得修改。

我看到 Instagram 也消除了这种模糊视图效果:

我能找到删除它的唯一方法是通过UIAlertController 的扩展自己更新视图层次结构。

extension UIAlertController {
    @discardableResult private func findAndRemoveBlurEffect(currentView: UIView) -> Bool {
        for childView in currentView.subviews {
            if childView is UIVisualEffectView {
                childView.removeFromSuperview()
                return true
            } else if String(describing: type(of: childView.self)) == "_UIInterfaceActionGroupHeaderScrollView" {
                // One background view is broken, we need to make sure it's white.
                if let brokenBackgroundView = childView.superview {
                    // Set broken brackground view to a darker white
                    brokenBackgroundView.backgroundColor = UIColor.colorRGB(red: 235, green: 235, blue: 235, alpha: 1)
                }
            }
            findAndRemoveBlurEffect(currentView: childView)
        }
        return false
    }
}

let actionSheetController = UIAlertController(title: title, message: nil, preferredStyle: .actionSheet)
actionSheetController.view.tintColor = .lightBlue
actionSheetController.removeBlurryView()

这很好,它消除了我的模糊视图效果:

我想知道...我的解决方案是实现这一目标的唯一方法吗?还是我缺少关于警报控制器外观的一些东西? 也许有一种更清洁的方法可以准确地完成这个结果?还有其他想法吗?

【问题讨论】:

  • 也许 instagram 仍在使用已弃用的 UIActionSheet。私下访问 alertcontroller 可能会导致您的应用被拒绝。

标签: ios objective-c swift uialertcontroller uivisualeffectview


【解决方案1】:

继承UIAlertController更容易。

这个想法是在每次调用viewDidLayoutSubviews 时遍历视图层次结构,删除UIVisualEffectView 的效果并更新它们的backgroundColor

class AlertController: UIAlertController {

    /// Buttons background color.
    var buttonBackgroundColor: UIColor = .darkGray {
        didSet {
            // Invalidate current colors on change.
            view.setNeedsLayout()
        }
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        // Traverse view hierarchy.
        view.allViews.forEach {
            // If there was any non-clear background color, update to custom background.
            if let color = $0.backgroundColor, color != .clear {
                $0.backgroundColor = buttonBackgroundColor
            }
            // If view is UIVisualEffectView, remove it's effect and customise color.
            if let visualEffectView = $0 as? UIVisualEffectView {
                visualEffectView.effect = nil
                visualEffectView.backgroundColor = buttonBackgroundColor
            }
        }

        // Update background color of popoverPresentationController (for iPads).
        popoverPresentationController?.backgroundColor = buttonBackgroundColor
    }

}


extension UIView {

    /// All child subviews in view hierarchy plus self.
    fileprivate var allViews: [UIView] {
        var views = [self]
        subviews.forEach {
            views.append(contentsOf: $0.allViews)
        }

        return views
    }

}

用法:

  1. 创建警报控制器。
  2. 设置按钮背景颜色: alertController.buttonBackgroundColor = .darkGray
  3. 自定义并显示控制器。

结果:

【讨论】:

    【解决方案2】:

    Vadim 的回答非常有效。

    我错过的(在 iOS 14.5 上测试)是缺少分隔符以及不可见的标题和消息值。

    所以我添加了为标签设置正确的 textColor 并跳过分隔符视觉效果视图以获得正确的外观。如果您的应用支持暗模式以相应地更新控件背景颜色,请记住覆盖 traitCollectionDidChange 方法

    override func viewDidLayoutSubviews() {
            super.viewDidLayoutSubviews()
    
            for subview in view.allViews {
                if let label = subview as? UILabel, label.textColor == .white {
                    label.textColor = .secondaryLabel
                }
                if let color = subview.backgroundColor, color != .clear {
                    subview.backgroundColor = buttonBackgroundColor
                }
                if let visualEffectView = subview as? UIVisualEffectView,
                   String(describing: subview).contains("Separator") == false {
                    visualEffectView.effect = nil
                    visualEffectView.contentView.backgroundColor = buttonBackgroundColor
                }
            }
    
            popoverPresentationController?.backgroundColor = buttonBackgroundColor
        }
    

    【讨论】:

      猜你喜欢
      • 2015-06-12
      • 2012-03-17
      • 2013-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-06
      相关资源
      最近更新 更多