14

我想要一個UIProgressView來顯示導航欄底部的進度(就像在iOS 7中發送iMessage或文本消息時一樣)。 但我需要這個一貫的我的導航控制器的每個表視圖視圖。 所以對我來說很明顯:我必須將其添加到UINavigationController。 但問題是,無法將UIProgressView添加到UINavigationController。 所以我嘗試了兩件事:在UINavigationController的UINavigationBar內部或頂部顯示UIProgressView

1st我嘗試以編程方式將其添加到UINavigationController的視圖。但問題在於定位UIProgressView並在更改設備旋轉時使其看起來不錯。

我嘗試的第二件事是將UIProgressView添加到每個UITableView,但我真的必須爲每個視圖執行此操作。它看起來不太好,因爲它不在導航欄的頂部,而是在它的下面。但是我不喜歡第二種解決方案的主要原因是因爲ProgressViews與他們的TableView一起來,所以你沒有一個靜態的但改變了。

在此之後,我沒有任何想法做到這一點,所以我問你...有沒有人有一個想法如何做到這一點?

這就是它看起來應該像: enter image description here

+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([email protected])]" 
                     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

+2

再一次,很好的回答 - 還沒有人看到有人將導入控制器的視圖添加進度欄是一個竅門!大! –

+0

嗨,我剛剛遇到這個問題,當你添加一個UISearchBar到UITableView。當你進入搜索欄並且導航欄消失時,會稍微擰緊一點。 7.0.4(iPad)和7.1 beta 2(iPhone)有不同的結果,一個進度條移到0,0,然後在搜索欄退出時不重新定位,另一個出現在搜索欄上。我沒有花時間去修復它,但是想知道你是否遇到過類似的事情,或者你有什麼建議來解決它? –

1

您可以的UINavigationController的titleview的補充進度如下面的截圖顯示:

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; 

OUTPUT:NAVIGATIONBAR WITH PROGRESSBAR

希望它可以幫助你。

+0

當我將它添加到導航項目中時,我(再次)必須將其添加到每個TableView中,是否正確?就我所見,UINavigationController堆棧上的每個視圖都會用自己的視圖覆蓋導航項。 (我添加了截圖來顯示結果應該是什麼) – h345k34cr

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]; 
} 

我不知道爲什麼它需要添加0.5偏移到NSLayoutContstraints代碼以獲得相同的比賽,但它是。我使用這些不是視覺格式,但選擇是你的。請注意,對底部的壓制使得這個無縫循環也是如此。

3

大廈包括已經在這裏建議一下,如果你想讓它顯示在應用程序在每個導航欄上,你可以把它插入UINavigationController的擴展(SWIFT):

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) 

    } 
} 

UPDATE(使用Swift 3語法)

這是一個更完整的解決方案。我把這個擴展名放到一個叫做的文件中,UINavigationController + Progress.swift。 (請注意,我使用的是UIView標記屬性找到UIProgressView與可選progressView屬性。可能有更優雅的方式來做到這一點,但是這似乎是最簡單的)

import UIKit 

let kProgressViewTag = 10000 
let kProgressUpdateNotification = "kProgressUpdateNotification" 

extension UINavigationController { 

    open override func viewDidLoad() { 
     super.viewDidLoad() 

     let progressView = UIProgressView(progressViewStyle: .bar) 
     progressView.tag = kProgressViewTag 
     self.view.addSubview(progressView) 
     let navBar = self.navigationBar 

     self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[navBar]-0-[progressView]", options: .directionLeadingToTrailing, metrics: nil, views: ["progressView" : progressView, "navBar" : navBar])) 
     self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[progressView]|", options: .directionLeadingToTrailing, metrics: nil, views: ["progressView" : progressView])) 

     progressView.translatesAutoresizingMaskIntoConstraints = false 
     progressView.setProgress(0.0, animated: false) 

     NotificationCenter.default.addObserver(self, selector: #selector(UINavigationController.didReceiveNotification(notification:)), name: NSNotification.Name(rawValue: kProgressUpdateNotification), object: nil) 
    } 

    var progressView : UIProgressView? { 
     return self.view.viewWithTag(kProgressViewTag) as? UIProgressView 
    } 

    func didReceiveNotification(notification:NSNotification) { 
     if let progress = notification.object as? ProgressNotification { 
      if progress.current == progress.total { 
       self.progressView?.setProgress(0.0, animated: false) 
      } else { 
       let perc = Float(progress.current)/Float(progress.total) 
       self.progressView?.setProgress(perc, animated: true) 
      } 
     } 
    } 
} 


class ProgressNotification { 
    var current: Int = 0 
    var total: Int = 0 

} 

所以我給了一個這裏假定您希望使用當前計數和總計數值來更新進度欄。現在,您需要從執行任何任務的代碼中發佈通知來確定進度 - 例如下載文件列表。下面是張貼通知的代碼:

let notification = ProgressNotification() 
notification.current = processedTaskCount 
notification.total = totalTaskCount 
DispatchQueue.main.async { 
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: kProgressUpdateNotification), object: notification) 
} 
+0

如何從我的具體UINavigationController實現中獲取此progressView?是否只能通過子視圖迭代? – user3537411

+0

如何獲取進度視圖的參考? – Isuru

+0

@Isuru我用更完整的解決方案更新了我的答案。希望能幫助到你。 –

1

你可以做到這一點的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]) 
    } 
} 

但是,如果你總是希望在導航欄的所有相同的進度條推風投那麼最好是子類的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]) 
} 
0

我已經概述瞭如何在我的博客文章做到這一點here

TL; DR

  • 創建協議,它提出了一個UIProgressView爲UINavigationController的子視圖

  • 創建協議,更新UIProgressView

  • 符合您的UINavigationController到演示協議
  • 符合各自的UIViewController在您的導航堆棧中更新到協議