세계에 공유하고 싶은 첫 번째 오픈 소스 프로젝트를 빌드하기 시작했습니다. AudioProvidable 프로토콜로 작동하고 수신 된 오디오 데이터를 재생하는 간단한 오디오 플레이어보기입니다. 우리는 오디오가 수신 될 때 무엇을 가지고 그 결과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의 상속이
오디오받은 후 :
하단 부분을 재생할 오디오가 하나 뿐인 경우 트랙 간 전환이 중복됩니다. 내 UI를 재 설계하려면 오디오 트랙 수를 확인하는 코드를 어디에 두어야합니까? 기존 요소를 두 번 추가하고 싶지 않기 때문에 오디오 소스 배열의 didSet {}
에 prepareView()
을 호출하고 싶지 않습니다. 감사합니다.
내가 무엇에 명확하지 않다 ... 내가 쉽게 어쩌면 좀 더 논리적 무엇을 발견, 코드가 처음으로 실행되고 있는지 확인하기 위해 부울 플래그를 추가하거나 수 너는 묻고있다. (1) IBDesignable은 * 디자인 타임 * 도구이므로 해당 시간에 트랙의 수를 알 수 없습니다. 그 부분 (적어도 당신이 말한 것과 함께)은 반드시 * 실행 시간 * 코드의 일부가되어야합니다. (2) 이것을 가정하면 어떤 종류의 컨테이너보기 (간단한 UIView 일 수 있음)와 처리의 적절한 순간에 밑 부분보기를 배치합니다. "오디오 수신"이후의 일종의 종결 일 것입니다. 전체를 숨 깁니다. (3) 따라서이 컨테이너 컨트롤을 IB에서 약간 다른 모양으로 만들어 재생할 트랙이 하나라도 있으면 숨길 것임을 나타냅니다. – dfd
@dfd, 답 및 명확한 설명에 감사드립니다. 나는 단지 (3) d 절을 완전히 이해하지 못했다. 이 동작을 어떻게 구현할 수 있도록 'UIView'는 _run-time_이 아닌 IB에서 다른 모양을 갖습니다. 감사. – GeRyCh
좋은 질문 - 나는 그것을 통해 생각하지 않았다. :-) 내 정신적 인 그림은 IB에서 약간 더 가벼운 것처럼 보이지만 코드에서 바뀌 었습니다. 그러나 다른 검토 자에게 혼란 스러울 수 있습니다. 두 가지 다른 아이디어 : (1) 하나의 트랙 만있는 경우 맨 아래에 실제로 * 잘못된 * 표시가 없다는 것을 고려하여 * IB에서 * hideTrackCount *와 같은 속성을 노출하지 않으시겠습니까? (2) 바닥 모양을 약간 변경하는 대신 흐리게 처리하십시오. 다른 스타일과 동일한 스타일 (글꼴, 색상, 배경)을 사용합니다. [이 두 가지 아이디어 중 첫 번째 것이 더 마음에 듭니다.] – dfd