2017-10-15 3 views
2

iosで複数の進捗状況を示すプログレスバーを作成するにはどうすればよいですか? は、私はそれが私がこのような何かを探していますUIProgressView複数の進行状況を持つUIProgressView

では可能ではないと思います(UIのみ): progress bar ありがとう!

+0

Rob、あなたはコメントでOPの質問に答えました。あなたはあなたの回答を回答として投稿して、彼がそれを受け入れることができるようにし、私たちはそれらを投票することができます。 –

答えて

1

標準UIProgressViewには1つの進捗のみが表示され、複数のアイテムの進捗状況をキャプチャしようとする場合は、Progress/NSProgressというオブジェクトの階層があります。例えば。 5つのファイルをアップロードする場合は、Progress個のオブジェクトがアップロードごとに1つずつあり、次にUIProgressViewが参照する第6のNSProgressがあり、残りの5つは子として表示されます。進捗オブジェクトのツリーの作成NSProgress class referenceを参照してください。例については、https://stackoverflow.com/a/36616538/1271826を参照してください。

個々のNSProgressの進行状況を視覚的に表す進捗状況を表示するには、これを自分で行う必要があります(またはこれを行う第三者のコントロールを見つける必要があります)。しかし、標準UIProgressViewはあなたのためにこれを行いません。

しかし、それは難しくありません。たとえば、横方向のスタックビューを作成し、追跡するごとに1つを追加し、サブビューのそれぞれの幅を、タスク全体のどのような割合で設定するかを設定します。

など。ここでは3 UIProgressView水平スタックビューは、サブビューを配置している。

enter image description here

は、ユーザーがより簡単に、彼らがどのように遠くに沿って見ることができるので、私は標準のシングルを好む、連結UIProgessViewと述べました。このような一連の進捗状況がある場合は、個々の進捗状況をすべて見て精神的に把握しなければならないため、「どれくらいの時間がかかりますか」を視覚的に確認することは本当に難しいです(たとえば、「最初は50 %done、2回目は66%、3回目は75%done ...というように、どれくらいの距離があるのでしょうか?

とにかく、私のスウィフトコードは上記をレンダリングします。私はあなたがObjective-Cの探している知っているが、うまくいけば、これは簡単にスウィフトやObjective-Cのいずれかで実装することができる基本的な考え方説明するために十分である:

class MultiProgressView: UIStackView { 

    struct ProgressInfo { 
     let progressView: UIProgressView 
     let totalToken: NSKeyValueObservation 
     let progressToken: NSKeyValueObservation 
    } 
    var progressInfo = [ProgressInfo]() 
    var progressHandler: ((Double) -> Void)? 

    var widthConstraints: [NSLayoutConstraint]? 

    func add(_ progress: Progress, progressTintColor: UIColor = .blue, trackTintColor: UIColor? = nil) { 
     let progressView = UIProgressView(progressViewStyle: .bar) 
     progressView.translatesAutoresizingMaskIntoConstraints = false 
     progressView.progressTintColor = progressTintColor 
     progressView.trackTintColor = trackTintColor ?? progressTintColor.withAlphaComponent(0.5) 
     addArrangedSubview(progressView) 
     progressView.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 1) 
     progressView.observedProgress = progress 
     let totalToken = progress.observe(\.totalUnitCount) { [weak self] (_, _) in 
      self?.updateWidths() 
     } 
     let progressToken = progress.observe(\.completedUnitCount) { [weak self] (_, _) in 
      if let percent = self?.percent { 
       self?.progressHandler?(percent) 
      } 
     } 
     progressInfo.append(ProgressInfo(progressView: progressView, totalToken: totalToken, progressToken: progressToken)) 
     updateWidths() 
    } 

    private func updateWidths() { 
     if let widthConstraints = self.widthConstraints { 
      removeConstraints(widthConstraints) 
     } 

     let totalUnitCount = self.totalUnitCount 
     guard totalUnitCount > 0 else { return } 

     widthConstraints = progressInfo.map { progressInfo in 
      let unitCount = progressInfo.progressView.observedProgress?.totalUnitCount ?? 0 
      return NSLayoutConstraint(item: progressInfo.progressView, attribute: .width, relatedBy: .equal, toItem: self, attribute: .width, multiplier: CGFloat(unitCount)/CGFloat(totalUnitCount), constant: 0) 
     } 

     DispatchQueue.main.async { 
      self.addConstraints(self.widthConstraints!) 
     } 
    } 

    var totalUnitCount: Int64 { 
     return progressInfo.reduce(Int64(0)) { $0 + ($1.progressView.observedProgress?.totalUnitCount ?? 0) } 
    } 

    var completedUnitCount: Int64 { 
     return progressInfo.reduce(Int64(0)) { $0 + ($1.progressView.observedProgress?.completedUnitCount ?? 0) } 
    } 

    var percent: Double { 
     return Double(completedUnitCount)/Double(totalUnitCount) 
    } 
} 

をし、それを使用する:

override func viewDidLoad() { 
    super.viewDidLoad() 

    let download1 = Download(...) 
    let download2 = Download(...) 
    let download3 = Download(...) 

    mainProgressView.progressHandler = { [weak self] percent in 
     self?.checkIfDone(percent: percent) 
    } 

    mainProgressView.add(download1.progress, progressTintColor: .blue) 
    mainProgressView.add(download2.progress, progressTintColor: .green) 
    mainProgressView.add(download3.progress, progressTintColor: .red) 

    download1.startDownload() 
    download2.startDownload() 
    download3.startDownload() 
} 

private func checkIfDone(percent: Double) { 
    if percent == 1 { 
     print("done") 
    } 
} 
関連する問題