世界に共有したい最初のオープンソースプロジェクトを構築し始めました。 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を継承してい
オーディオを受信した後:
ボトムパートを再生するオーディオが1つだけの場合、トラック間の切り替えは冗長です。私のUIを再設計するために、オーディオトラック数のチェックコードをどこに置く必要がありますか?私は、既存の要素を2度追加したくないので、をオーディオソース配列のdidSet {}
にコールしたくありません。よろしくです。 よろしくお願いします。
、私は何に明確ではないよ...私は簡単に、多分もう少し論理的見つけるものを、コードが初めて実行されているかどうかを確認するためにブールフラグを追加、または可能性がありあなたは尋ねています。 (1)IBDesignableは* design-time *ツールなので、その時点でいくつのトラックがあるか分からない。その部分(少なくともあなたが言ったもの)*は*ランタイム*コードの一部でなければなりません。 (2)これを仮定すると、いくつかの種類のコンテナビュー(簡単なUIViewにすることができます)と処理の適切な時点(おそらくオーディオを受け取った後の何らかの種類のクロージャ)に下部ビューを配置します。 (3)したがって、このコンテナコントロールをIBで少し違った外観にして、再生するトラックが1つあれば非表示にすることを示します。 – dfd
@dfd、あなたの答えと物事の明確な説明に感謝します。私はちょうど完全に理解していない(3)d節。どのようにこの動作を実装することができるので、 'UIView'は_run-time_ではなくIBで異なる外観を持ちます。ありがとう。 – GeRyCh
良い質問 - 私はそれを考えていませんでした。 :-)私の精神的なイメージは、IBでやや軽く見えるようなものでしたが、コードで変更しましたが、それ以上のレビューでは他の開発者にとって混乱します。 2つの他のアイデア:(1)トラックが1つだけの場合は、実際には何も間違っていないと考えて、* hideTrackCount *のようなプロパティをIBに公開してみませんか? (2)底部の外観を少し変更する代わりに、それをぼかす。残りの部分と同じスタイリング(フォント、色、背景)を使用します。 [これらの2つのアイデアのうち、私は最初のものがより好きです。] – dfd