iOS:使用UINavigationController自定义应用程序范围的横幅

时间:2014-09-18 15:19:38

标签: ios iphone xamarin

我希望有一个应用程序范围的横幅来向用户显示自定义消息。此横幅并不总是存在,但可以显示在应用程序的任何屏幕上。显示时,它不会位于当前视图的顶部,而是强制当前视图在其下方调整大小。目标是仅实现一次自定义横幅,而不是在每个屏幕中实现。

我尝试过的方法是使用带有UINavigationController根的UIViewController和两个容器UIView(例如IB中的ContainerView)。然后,根视图控制器将具有自定义代码来控制两个容器视图的大小,具体取决于是否显示状态标志。

问题是在推送到UINavigationController时,它会用新的UIViewController替换两个容器视图。相反,我想只推入底部视图容器。可以UINavigationController配置为仅使用底部视图还是应该有更好的方法?

这是一个模型:

Navigation controller with custom banner

3 个答案:

答案 0 :(得分:0)

您最好的选择是子类UINavigationController并实现用于调整大小的逻辑,而不是在根视图控制器中。例如,实现如下方法:

- (void)setShowBanner:(BOOL)show {
    CGRect frame = [self frameForViewControllersWhenShowingBanner:show];

    for (UIViewController *vc in self.viewControllers) {
        vc.view.frame = frame;
    }
}

此子类导航控制器也会添加/删除横幅视图本身。当然,您可以通过将代码放在动画块中来使上面的方法动画化。

答案 1 :(得分:0)

这是非常高级的但是我会继承UIViewController(例如:BanneredViewController),然后将所有推送到导航控制器的视图控制器继承自BanneredViewController

BanneredViewController中,您可以控制此横幅的显示状态,触发布局和约束更新事件等....例如,您可能有以下方法:

-(void)showBannerWithMessage:(NSString *)message;
-(void)hideBanner;

在这些方法中,您可以更新布局约束,调整帧等,以获得所需的效果。根据您是否支持AutoLayout,您可以采用特定的方式执行此操作。使用这种方法,您可以将横幅布局代码保存在一个位置,并根据需要使用子类,并避免不得不使用UINavigationController的内部。

答案 2 :(得分:-1)

这是一款Swift 3 iOS 10解决方案。

创建UIView子类:

class NavigationBannerView: UIView {

    let iconImageView = UIImageView()
    let messageTextLabel = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)

        backgroundColor = .red

        let iconImage = UIImage(named: "YourImage")
        iconImageView.image = iconImage
        iconImageView.translatesAutoresizingMaskIntoConstraints = false
        iconImageView.contentMode = .scaleAspectFit
        addSubview(iconImageView)

        messageTextLabel.translatesAutoresizingMaskIntoConstraints = false
        messageTextLabel.numberOfLines = 0
        messageTextLabel.textColor = .white
        addSubview(messageTextLabel)

        iconImageView.leftAnchor.constraint(equalTo: leftAnchor, constant: 12).isActive = true
        iconImageView.topAnchor.constraint(equalTo: topAnchor, constant: 4).isActive = true
        iconImageView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -4).isActive = true
        iconImageView.widthAnchor.constraint(equalToConstant: 26).isActive = true

        messageTextLabel.leftAnchor.constraint(equalTo: iconImageView.rightAnchor, constant: 12).isActive = true
        messageTextLabel.topAnchor.constraint(equalTo: topAnchor, constant: 0).isActive = true
        messageTextLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0).isActive = true
        messageTextLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: 8).isActive = true
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    func fadeInfadeOut(for duration: TimeInterval) {
        UIView.animate(withDuration: 0.25, animations: {
            self.alpha = 1
        }) { (done) in
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + duration, execute: {
                UIView.animate(withDuration: 0.25, animations: {
                    self.alpha = 0
                })
            })
        }
    }
}

然后创建一个UINavigationController子类

class MyNavigationViewController: UINavigationController {

    var navigationBannerView: NavigationBannerView!

    override func viewDidLoad() {
        super.viewDidLoad()

        //BannerView
        navigationBannerView = NavigationBannerView(frame: .zero)
        view.addSubview(navigationBannerView)
        view.bringSubview(toFront: navigationBannerView)

        navigationBannerView.translatesAutoresizingMaskIntoConstraints = false
        navigationBannerView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
        navigationBannerView.topAnchor.constraint(equalTo: navigationBar.bottomAnchor, constant: 0).isActive = true
        navigationBannerView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
        navigationBannerView.heightAnchor.constraint(equalToConstant: 34).isActive = true
        navigationBannerView.alpha = 0
    }

    func showBanner(with text: String, duration: TimeInterval) {
        navigationBannerView.messageTextLabel.text = text
        navigationBannerView.fadeInfadeOut(for: duration)
    }
}

然后,当您需要显示横幅时,可以调用NavigationController showBanner(with text: String, duration: TimeInterval)