2017-03-26 4 views
0

世界に共有したい最初のオープンソースプロジェクトを構築し始めました。 AudioProvidableプロトコルで動作し、受信後にオーディオデータを再生する単純なAudio Playerビューです。我々は音声が受信されたときに持っているものであるという結果iOS動的要素を使用したカスタムコントロール

override init(frame: CGRect) { 
     super.init(frame: frame) 
#if !TARGET_INTERFACE 
     translatesAutoresizingMaskIntoConstraints = false 
#endif 
     prepareView() 
     updateUI() 
    } 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     prepareView() 
     updateUI() 
    } 

    func prepareView() { 
      //Necessary in order to set our own constraints 
      //btnPlay is already doing the same inside buttonWithImage(_:) 
      spinner.translatesAutoresizingMaskIntoConstraints = false 
      sliderAudioProgress.translatesAutoresizingMaskIntoConstraints = false 

      //Add necessary subviews to start setting up layout 
      addSubview(sliderAudioProgress) 
      addSubview(lblAudioDuration) 
      addSubview(lblAudioProgress) 
      addSubview(spinner) 
      addSubview(btnPlay) 
      addSubview(lblTrackNumber) 
      addSubview(btnNextTrack) 
      addSubview(btnPreviousTrack) 

      //Height of play & next/previous track buttons defines AudioPlayerView height 
      let viewHeight:CGFloat = 48 * 2 

      //Setup UI layout using constraints 
      NSLayoutConstraint.activate([ 

       heightAnchor.constraint(equalToConstant: viewHeight), 

       //Play button constraints 
       btnPlay.topAnchor.constraint(equalTo: topAnchor), 
       btnPlay.leadingAnchor.constraint(equalTo: leadingAnchor), 

       //Spinner constraints 
       spinner.centerYAnchor.constraint(equalTo: btnPlay.centerYAnchor), 
       spinner.centerXAnchor.constraint(equalTo: btnPlay.centerXAnchor), 

       //Progress label constraints 
       lblAudioProgress.leadingAnchor.constraint(equalTo: btnPlay.trailingAnchor), 
       lblAudioProgress.centerYAnchor.constraint(equalTo: btnPlay.centerYAnchor), 

       //Duration label constraints 
       lblAudioDuration.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -spacing), 
       lblAudioDuration.centerYAnchor.constraint(equalTo: btnPlay.centerYAnchor), 

       //Audio Progress Slider constraints 
       sliderAudioProgress.leadingAnchor.constraint(equalTo: lblAudioProgress.trailingAnchor, constant: spacing), 
       sliderAudioProgress.trailingAnchor.constraint(equalTo: lblAudioDuration.leadingAnchor, constant: -spacing), 
       sliderAudioProgress.centerYAnchor.constraint(equalTo: btnPlay.centerYAnchor), 

       lblTrackNumber.centerXAnchor.constraint(equalTo: centerXAnchor), 

       btnPreviousTrack.topAnchor.constraint(equalTo: btnPlay.bottomAnchor), 
       btnPreviousTrack.trailingAnchor.constraint(equalTo: lblTrackNumber.leadingAnchor, constant: -spacing), 

       btnNextTrack.topAnchor.constraint(equalTo: btnPlay.bottomAnchor), 
       btnNextTrack.leadingAnchor.constraint(equalTo: lblTrackNumber.trailingAnchor, constant: spacing), 

       lblTrackNumber.centerYAnchor.constraint(equalTo: btnNextTrack.centerYAnchor) 
      ]) 

      //Spinner setup: 
      spinner.hidesWhenStopped = true 

      //btnPlay setup: 
      btnPlay.addTarget(self, action: #selector(AudioPlayerView.playButtonPressed), for: .touchUpInside) 

      //Slider setup 
      sliderAudioProgress.thumbTintColor = UIColor(keyFromAppColorPalette: "secondary_color") 
      sliderAudioProgress.addTarget(self, action: #selector(AudioPlayerView.durationSliderValueChanged), for: .valueChanged) 
      sliderAudioProgress.addTarget(self, action: #selector(AudioPlayerView.durationSliderReleased), for: .touchUpInside) 
      sliderAudioProgress.isEnabled = false 
      sliderAudioProgress.isContinuous = true 
      sliderAudioProgress.semanticContentAttribute = .playback 

      //View's UI effects to make it look better 
      layer.cornerRadius = 6 
      layer.masksToBounds = true 
      layer.borderColor = UIColor.black.cgColor 
      layer.borderWidth = 2 
      semanticContentAttribute = .playback 

      spinner.startAnimating() 
      btnPlay.isHidden = true 
     } 

:今のところ

私はIBDesignableクラスは、このようなサブビューの制約を定義することによって自分自身を構築しているのUIViewを継承してい

enter image description here

オーディオを受信した後:

enter image description here

ボトムパートを再生するオーディオが1つだけの場合、トラック間の切り替えは冗長です。私のUIを再設計するために、オーディオトラック数のチェックコードをどこに置く必要がありますか?私は、既存の要素を2度追加したくないので、をオーディオソース配列のdidSet {}にコールしたくありません。よろしくです。 よろしくお願いします。

+1

、私は何に明確ではないよ...私は簡単に、多分もう少し論理的見つけるものを、コードが初めて実行されているかどうかを確認するためにブールフラグを追加、または可能性がありあなたは尋ねています。 (1)IBDesignableは* design-time *ツールなので、その時点でいくつのトラックがあるか分からない。その部分(少なくともあなたが言ったもの)*は*ランタイム*コードの一部でなければなりません。 (2)これを仮定すると、いくつかの種類のコンテナビュー(簡単なUIViewにすることができます)と処理の適切な時点(おそらくオーディオを受け取った後の何らかの種類のクロージャ)に下部ビューを配置します。 (3)したがって、このコンテナコントロールをIBで少し違った外観にして、再生するトラックが1つあれば非表示にすることを示します。 – dfd

+0

@dfd、あなたの答えと物事の明確な説明に感謝します。私はちょうど完全に理解していない(3)d節。どのようにこの動作を実装することができるので、 'UIView'は_run-time_ではなくIBで異なる外観を持ちます。ありがとう。 – GeRyCh

+0

良い質問 - 私はそれを考えていませんでした。 :-)私の精神的なイメージは、IBでやや軽く見えるようなものでしたが、コードで変更しましたが、それ以上のレビューでは他の開発者にとって混乱します。 2つの他のアイデア:(1)トラックが1つだけの場合は、実際には何も間違っていないと考えて、* hideTrackCount *のようなプロパティをIBに公開してみませんか? (2)底部の外観を少し変更する代わりに、それをぼかす。残りの部分と同じスタイリング(フォント、色、背景)を使用します。 [これらの2つのアイデアのうち、私は最初のものがより好きです。] – dfd

答えて

1

あなたは

func prepareView() { 

     //Necessary in order to set our own constraints 
     //btnPlay is already doing the same inside buttonWithImage(_:) 
     spinner.translatesAutoresizingMaskIntoConstraints = false 
     sliderAudioProgress.translatesAutoresizingMaskIntoConstraints = false 

     // if our subviews have not yet been added 
     if sliderAudioProgress.superview == nil { 

      //Add necessary subviews to start setting up layout 
      addSubview(sliderAudioProgress) 
      addSubview(lblAudioDuration) 
      ... etc 

     } 

     // continue here with any "every time" setup tasks 
    } 
+0

ありがとう!可能な解決策の1つとして受け入れられるかもしれません – GeRyCh

関連する問題