17

ナビゲーションバーの下部に進行状況を表示する UIProgressView が必要です (iOS 7 で iMessage またはテキストメッセージを送信する場合と同様)。しかし、ナビゲーション コントローラーのすべてのテーブル ビュー ビューで一貫してこれが必要です。したがって、私にとっては明らかでした。これを UINavigationController に追加する必要があります。しかし問題は、UIProgressView を UINavigationController に追加できないことです。そこで、次の 2 つのことを試しました。

最初に、プログラムで UINavigationController のビューに追加しようとしました。しかし問題は、UIProgressView を配置し、デバイスの回転を変更するときに見栄えを良くすることでした。

私が試みた2番目のことは、UIProgressViewをすべてのUITableViewに追加することですが、実際にはすべてのビューに対してこれを行う必要があります. また、ナビゲーション バーの上ではなく下にあるため、見栄えもよくありません。しかし、2番目のソリューションが気に入らなかった主な理由は、ProgressViewsがTableViewに付属しているため、静的なものではなく変化するものがあるためです。

この後、私はこれを行う考えがないので、あなたに尋ねます… 誰かこれを行う方法を考えていますか?

それは次のようになります。 ここに画像の説明を入力

4

7 に答える 7

12

バーが実際にナビゲーションバーのすぐ内側になるように、元のポスターの回答を作り直しました。これの良いところは、表示時に 1 ピクセルのボトムラインに重なる (事実上、それを置き換える) ため、プログレス バーを非表示にアニメートすると、プログレス バーがフェードアウトし、区切り線がフェードインすることです。このソリューションは、Navigation バーではなく、Navigation Controller のビューに進行状況バーを追加しています。

- (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 コードに追加する必要がある理由はわかりませんが、そうです。私はこれらの視覚的なフォーマットを使用していませんが、選択はあなた次第です。ボトムスに拘束すると、これもローテーションでシームレスになることに注意してください。

于 2013-10-21T14:55:59.673 に答える
4

ここで既に提案されていることに基づいて、アプリのすべてのナビゲーション バーに表示する場合は、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を検索するために tag プロパティを使用していることに注意してください。もっとエレガントな方法があるかもしれませんが、これが最も簡単なようです)UIProgressViewprogressView

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)
}
于 2015-10-17T21:42:22.330 に答える
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])  
}
于 2015-11-09T10:02:26.987 に答える
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;

出力:プログレスバー付きのナビゲーションバー

お役に立てば幸いです。

于 2013-10-06T18:06:27.573 に答える
0

ここのブログ投稿でこれを行う方法の概要を説明しました

TL;DR

  • UIProgressView を UINavigationController サブビューとして提示するプロトコルを作成します

  • UIProgressView を更新するプロトコルを作成する

  • UINavigationController をプレゼンター プロトコルに準拠させる
  • ナビゲーション スタック内の各 UIViewController をアップデーター プロトコルに準拠させる
于 2017-04-06T15:13:18.257 に答える