我希望有一个UIProgressView来显示导航栏底部的进度(就像在iOS 7中发送iMessage或短信一样)。 但是我在导航控制器的每个表视图视图中都需要这一点。 所以对我来说很清楚:我必须将它添加到UINavigationController中。 但问题是,不可能将UIProgressView添加到UINavigationController。 所以我尝试了两件事:
第一次我尝试以编程方式将其添加到UINavigationController的视图中。但问题是定位UIProgressView并在更改设备旋转时使其看起来很好。
我尝试的第二件事是将UIProgressView添加到每个UITableView,但是我真的必须为每个视图执行此操作。它也不好看,因为它不在导航栏的顶部,而是在它下面。但是我不喜欢第二种解决方案的主要原因是因为ProgressViews带有他们的TableView,所以你没有静态的,而是改变它们。
在此之后,我不知道这样做,所以我问你......有没有人知道如何做到这一点?
它应该是这样的:
答案 0 :(得分:11)
我终于找到了解决方案:
我制作了一个自定义的UINavigationController并将其添加到viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
progress = [[UIProgressView alloc] init];
[[self view] addSubview:progress];
UIView *navBar = [self navigationBar];
[[self view] addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[navBar]-[progress(2@20)]"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:nil
views:NSDictionaryOfVariableBindings(progress, navBar)]];
[[self view] addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[progress]|"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:nil
views:NSDictionaryOfVariableBindings(progress)]];
[progress setTranslatesAutoresizingMaskIntoConstraints:NO];
[progress setProgress:0 animated:NO];
}
我创建了一个新的UIProgressView(我在@interface
中声明)添加了约束以将其定位在导航栏下方(这一步很重要:)将translatesAutoresizingMaskIntoConstraints
设置为NO
。< / p>
答案 1 :(得分:11)
我重写了原始海报的答案,以便栏实际上就在导航栏内。有趣的是,当它显示时,它与一个像素底线重叠(实际上取代它),所以当你将进度条设置为隐藏时,进度条淡出并且分隔线淡入。关键部分此解决方案是将进度条添加到导航控制器的视图,而不是导航栏。
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
UIProgressView *progress = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleBar];;
[self.view addSubview:progress];
UINavigationBar *navBar = [self navigationBar];
#if 1
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[navBar]-0-[progress]"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:nil
views:NSDictionaryOfVariableBindings(progress, navBar)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[progress]|"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:nil
views:NSDictionaryOfVariableBindings(progress)]];
#else
NSLayoutConstraint *constraint;
constraint = [NSLayoutConstraint constraintWithItem:progress attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:navBar attribute:NSLayoutAttributeBottom multiplier:1 constant:-0.5];
[self.view addConstraint:constraint];
constraint = [NSLayoutConstraint constraintWithItem:progress attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:navBar attribute:NSLayoutAttributeLeft multiplier:1 constant:0];
[self.view addConstraint:constraint];
constraint = [NSLayoutConstraint constraintWithItem:progress attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:navBar attribute:NSLayoutAttributeRight multiplier:1 constant:0];
[self.view addConstraint:constraint];
#endif
[progress setTranslatesAutoresizingMaskIntoConstraints:NO];
[progress setProgress:0.5 animated:NO];
}
我不确定为什么必须在NSLayoutContstraints代码中添加0.5偏移量以获得相同的匹配,但事实确实如此。我使用的不是视觉格式,而是你的选择。请注意,与底部相反,这也使其无缝旋转。
答案 2 :(得分:3)
基于此处已建议的内容,如果您想在应用程序的每个导航栏上显示它,您可以将其变为UINavigationController上的扩展(Swift):
{}
更新(使用Swift 3语法)
这是一个更完整的解决方案。我把这个扩展名放在一个名为 UINavigationController + Progress.swift 的文件中。 (注意我正在使用threadInfoString
标记属性来查找具有可选extension UINavigationController {
public override func viewDidLoad() {
super.viewDidLoad()
let progressView = UIProgressView(progressViewStyle: .Bar)
self.view.addSubview(progressView)
let navBar = self.navigationBar
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[navBar]-0-[progressView]", options: .DirectionLeadingToTrailing, metrics: nil, views: ["progressView" : progressView, "navBar" : navBar]))
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[progressView]|", options: .DirectionLeadingToTrailing, metrics: nil, views: ["progressView" : progressView]))
progressView.translatesAutoresizingMaskIntoConstraints = false
progressView.setProgress(0.5, animated: false)
}
}
属性的UIView
。可能有更优雅的方法来做到这一点,但这似乎是最直接的)< / p>
UIProgressView
所以我在这里给出了一个特定的实现,假设您希望使用当前计数和总计数值来更新进度条。现在,您需要的是从执行任何用于确定进度的任务的代码发布通知 - 例如下载文件列表。这是发布通知的代码:
progressView
答案 3 :(得分:2)
您可以在navigationController的根viewController中执行此操作:
override func viewDidLoad() {
super.viewDidLoad()
// if VC is pushed in a navigation controller I add a progress bar
if let navigationVC = self.navigationController {
// create progress bar with .bar style and add it as subview
let progressBar = UIProgressView(progressViewStyle: .Bar)
navigationVC.navigationBar.addSubview(self.progressView)
// create constraints
// NOTE: bottom constraint has 1 as constant value instead of 0; this way the progress bar will look like the one in Safari
let bottomConstraint = NSLayoutConstraint(item: navigationVC.navigationBar, attribute: .Bottom, relatedBy: .Equal, toItem: progressBar, attribute: .Bottom, multiplier: 1, constant: 1)
let leftConstraint = NSLayoutConstraint(item: navigationVC.navigationBar, attribute: .Leading, relatedBy: .Equal, toItem: progressBar, attribute: .Leading, multiplier: 1, constant: 0)
let rightConstraint = NSLayoutConstraint(item: navigationVC.navigationBar, attribute: .Trailing, relatedBy: .Equal, toItem: progressBar, attribute: .Trailing, multiplier: 1, constant: 0)
// add constraints
progressBar.translatesAutoresizingMaskIntoConstraints = false
navigationVC.view.addConstraints([bottomConstraint, leftConstraint, rightConstraint])
}
}
但是如果你想要总是在导航栏中为所有推送的VC提供相同的进度条,那么最好继承UINavigationController并且:
override func viewDidLoad() {
super.viewDidLoad()
// create progress bar with .bar style and keep reference with a property
let progressBar = UIProgressView(progressViewStyle: .Bar)
self.progressBar = progressBar
// add progressBar as subview
self.navigationBar.addSubview(progressBar)
// create constraints
// NOTE: bottom constraint has 1 as constant value instead of 0; this way the progress bar will look like the one in Safari
let bottomConstraint = NSLayoutConstraint(item: self.navigationBar, attribute: .Bottom, relatedBy: .Equal, toItem: progressBar, attribute: .Bottom, multiplier: 1, constant: 1)
let leftConstraint = NSLayoutConstraint(item: self.navigationBar, attribute: .Leading, relatedBy: .Equal, toItem: progressBar, attribute: .Leading, multiplier: 1, constant: 0)
let rightConstraint = NSLayoutConstraint(item: self.navigationBar, attribute: .Trailing, relatedBy: .Equal, toItem: progressBar, attribute: .Trailing, multiplier: 1, constant: 0)
// add constraints
progressBar.translatesAutoresizingMaskIntoConstraints = false
self.view.addConstraints([bottomConstraint, leftConstraint, rightConstraint])
}
答案 4 :(得分:1)
您可以在UInavigationController的titleView中添加ProgressBar,如下面的屏幕截图所示:
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0,0,200,30)];
[customView setBackgroundColor:[UIColor whiteColor]];
UIProgressView *p = [[UIProgressView alloc] initWithFrame:CGRectMake(10, 20, 180,20)]; // Here pass frame as per your requirement
p.progress = 0.5f;
[customView addSubview:p];
self.navigationItem.titleView = customView;
输出:
希望它对你有所帮助。
答案 5 :(得分:1)
SnapKit个用户的解决方案。还将progressView
放在navigationBar
上方。
extension UINavigationController {
public override func viewDidLoad() {
super.viewDidLoad()
let progressView = UIProgressView(progressViewStyle: .bar)
self.view.addSubview(progressView)
let navBar = self.navigationBar
progressView.snp.makeConstraints { make in
make.leading.trailing.equalToSuperview()
make.top.equalTo(navBar.snp.top)
}
progressView.setProgress(0.5, animated: false)
view.bringSubviewToFront(progressView)
}
}
答案 6 :(得分:0)
我已在我的博文here
中概述了如何执行此操作TL; DR
创建协议,将UIProgressView呈现为UINavigationController子视图
创建更新UIProgressView