我希望有一个应用程序范围的横幅来向用户显示自定义消息。此横幅并不总是存在,但可以显示在应用程序的任何屏幕上。显示时,它不会位于当前视图的顶部,而是强制当前视图在其下方调整大小。目标是仅实现一次自定义横幅,而不是在每个屏幕中实现。
我尝试过的方法是使用带有UINavigationController
根的UIViewController
和两个容器UIView
(例如IB中的ContainerView)。然后,根视图控制器将具有自定义代码来控制两个容器视图的大小,具体取决于是否显示状态标志。
问题是在推送到UINavigationController
时,它会用新的UIViewController
替换两个容器视图。相反,我想只推入底部视图容器。可以UINavigationController
配置为仅使用底部视图还是应该有更好的方法?
这是一个模型:
答案 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)
。