From aea3f0e39a68508229ad71378a91522704ade232 Mon Sep 17 00:00:00 2001 From: Peter Stajger Date: Tue, 24 Oct 2017 14:54:35 +0200 Subject: [PATCH 01/14] #14 improved ratios of action item both for portrait and landscape modes --- ImagePicker/ImagePickerLayout.swift | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ImagePicker/ImagePickerLayout.swift b/ImagePicker/ImagePickerLayout.swift index 45c3a36..1266cdf 100644 --- a/ImagePicker/ImagePickerLayout.swift +++ b/ImagePicker/ImagePickerLayout.swift @@ -58,14 +58,16 @@ final class ImagePickerLayout { case configuration.sectionIndexForActions: //this will make sure that action item is either square if there are 2 items, //or a recatangle if there is only 1 item - let width = sizeForItem(numberOfItemsInRow: 2, preferredWidthOrHeight: nil, collectionView: collectionView, scrollDirection: layout.scrollDirection).width + //let width = sizeForItem(numberOfItemsInRow: 2, preferredWidthOrHeight: nil, collectionView: collectionView, scrollDirection: layout.scrollDirection).width + let ratio: CGFloat = 0.25 + let width = collectionView.frame.width * ratio return sizeForItem(numberOfItemsInRow: layoutModel.numberOfItems(in: configuration.sectionIndexForActions), preferredWidthOrHeight: width, collectionView: collectionView, scrollDirection: layout.scrollDirection) case configuration.sectionIndexForCamera: //lets keep this ratio so camera item is a nice rectangle let ratio: CGFloat = 0.734 - let width: CGFloat = collectionView.frame.height * ratio - return sizeForItem(numberOfItemsInRow: layoutModel.numberOfItems(in: configuration.sectionIndexForCamera), preferredWidthOrHeight: width, collectionView: collectionView, scrollDirection: layout.scrollDirection) + let widthOrHeight: CGFloat = collectionView.frame.height * ratio + return sizeForItem(numberOfItemsInRow: layoutModel.numberOfItems(in: configuration.sectionIndexForCamera), preferredWidthOrHeight: widthOrHeight, collectionView: collectionView, scrollDirection: layout.scrollDirection) case configuration.sectionIndexForAssets: //make sure there is at least 1 item, othewise invalid layout From 3b9f780b783e1b9f6972e8f7830f94f0382cef2e Mon Sep 17 00:00:00 2001 From: Peter Stajger Date: Tue, 24 Oct 2017 15:53:34 +0200 Subject: [PATCH 02/14] close 14# update rates based on interface orientation --- ImagePicker/ImagePickerController.swift | 2 +- ImagePicker/ImagePickerLayout.swift | 26 ++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/ImagePicker/ImagePickerController.swift b/ImagePicker/ImagePickerController.swift index 4cd5bb9..acab9b2 100644 --- a/ImagePicker/ImagePickerController.swift +++ b/ImagePicker/ImagePickerController.swift @@ -303,7 +303,7 @@ open class ImagePickerController : UIViewController { collectionViewDataSource.cellRegistrator = cellRegistrator collectionViewDelegate.delegate = self collectionViewDelegate.layout = ImagePickerLayout(configuration: layoutConfiguration) - + //register for photo library updates - this is needed when changing permissions to photo library //TODO: this is expensive (loading library for the first time) PHPhotoLibrary.shared().register(self) diff --git a/ImagePicker/ImagePickerLayout.swift b/ImagePicker/ImagePickerLayout.swift index 1266cdf..115c02f 100644 --- a/ImagePicker/ImagePickerLayout.swift +++ b/ImagePicker/ImagePickerLayout.swift @@ -65,7 +65,31 @@ final class ImagePickerLayout { case configuration.sectionIndexForCamera: //lets keep this ratio so camera item is a nice rectangle - let ratio: CGFloat = 0.734 + + let traitCollection = collectionView.traitCollection + + var ratio: CGFloat = 160/212 + + //for iphone in landscape we need different ratio + switch traitCollection.userInterfaceIdiom { + case .phone: + switch (traitCollection.horizontalSizeClass, traitCollection.verticalSizeClass) { + //iphones in landscape + case (.unspecified, .compact): + fallthrough + //iphones+ in landscape + case (.regular, .compact): + fallthrough + //iphones in landscape except iphone + + case (.compact, .compact): + ratio = 1/ratio + default: break + } + + default: + break + } + let widthOrHeight: CGFloat = collectionView.frame.height * ratio return sizeForItem(numberOfItemsInRow: layoutModel.numberOfItems(in: configuration.sectionIndexForCamera), preferredWidthOrHeight: widthOrHeight, collectionView: collectionView, scrollDirection: layout.scrollDirection) From c7925f6a637fbcac3ee6fde195caa29c6ab0e233 Mon Sep 17 00:00:00 2001 From: Peter Stajger Date: Wed, 25 Oct 2017 09:52:17 +0200 Subject: [PATCH 03/14] shutter button on camera cells are smaller 44x44 --- ImagePicker/LivePhotoCameraCell.xib | 6 +++--- ImagePicker/VideoCameraCell.xib | 11 ++++++----- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/ImagePicker/LivePhotoCameraCell.xib b/ImagePicker/LivePhotoCameraCell.xib index 85c46fd..5bba886 100644 --- a/ImagePicker/LivePhotoCameraCell.xib +++ b/ImagePicker/LivePhotoCameraCell.xib @@ -30,10 +30,10 @@ + + + + + + + + - + + + + + + + - + From f0eb14d8c5d9618660047806563c96d76061b21b Mon Sep 17 00:00:00 2001 From: Peter Stajger Date: Wed, 25 Oct 2017 10:56:02 +0200 Subject: [PATCH 06/14] project files --- ImagePicker.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ImagePicker.xcodeproj/project.pbxproj b/ImagePicker.xcodeproj/project.pbxproj index edd7859..42afdc3 100644 --- a/ImagePicker.xcodeproj/project.pbxproj +++ b/ImagePicker.xcodeproj/project.pbxproj @@ -230,11 +230,11 @@ 427925FF1F963E9B00B6D55F /* LivePhotoCameraCell.swift */, 427926001F963E9C00B6D55F /* LivePhotoCameraCell.xib */, 427925F61F96388000B6D55F /* RecordButton.swift */, + 42990DBE1FA07AF7001658C4 /* RecordDurationLabel.swift */, 427925F41F96381400B6D55F /* ShutterButton.swift */, 427925F21F9636D700B6D55F /* StationaryButton.swift */, 427925FB1F963A8C00B6D55F /* VideoCameraCell.swift */, 427925FC1F963A8C00B6D55F /* VideoCameraCell.xib */, - 42990DBE1FA07AF7001658C4 /* RecordDurationLabel.swift */, ); name = Views; sourceTree = ""; From 01bd0093a12d4398049172043a53b9af64326b3f Mon Sep 17 00:00:00 2001 From: Peter Stajger Date: Wed, 25 Oct 2017 11:40:57 +0200 Subject: [PATCH 07/14] #12 updating duration label based on recording state every second --- ImagePicker/RecordDurationLabel.swift | 43 +++++++++++++++++++++++++-- ImagePicker/VideoCameraCell.swift | 3 ++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/ImagePicker/RecordDurationLabel.swift b/ImagePicker/RecordDurationLabel.swift index 79d0e07..bee9fea 100644 --- a/ImagePicker/RecordDurationLabel.swift +++ b/ImagePicker/RecordDurationLabel.swift @@ -24,28 +24,65 @@ final class RecordDurationLabel : UILabel { private var indicatorLayer: CALayer = { let layer = CALayer() - layer.backgroundColor = UIColor(red: 234/255, green: 53/255, blue: 52/255, alpha: 1).cgColor layer.masksToBounds = true + layer.backgroundColor = UIColor(red: 234/255, green: 53/255, blue: 52/255, alpha: 1).cgColor + layer.frame.size = CGSize(width: 6, height: 6) layer.cornerRadius = layer.frame.width/2 + layer.opacity = 0 return layer }() override init(frame: CGRect) { super.init(frame: frame) - layer.addSublayer(indicatorLayer) + commonInit() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) - layer.addSublayer(indicatorLayer) + commonInit() + } + + override func layoutSubviews() { + super.layoutSubviews() + indicatorLayer.position = CGPoint(x: -7, y: bounds.height/2) } // MARK: Public Methods + private var timer: Timer? + private var backingSeconds: TimeInterval = 0 { + didSet { updateLabel() } + } + func start() { + + guard timer == nil else { + return + } + + timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { [weak self] (timer) in + self?.backingSeconds += 1 + }) + timer?.tolerance = 0.1 + } + + func stop() { + timer?.invalidate() + timer = nil + backingSeconds = 0 + } // MARK: Private Methods + private func updateLabel() { + text = RecordDurationLabel.durationFormatter.string(from: backingSeconds) + } + + private func commonInit() { + layer.addSublayer(indicatorLayer) + clipsToBounds = false + } + private func fadeAnimation(fromValue: CGFloat, toValue: CGFloat, duration: CFTimeInterval) -> CAAnimation { let animation = CABasicAnimation() animation.keyPath = "opacity" diff --git a/ImagePicker/VideoCameraCell.swift b/ImagePicker/VideoCameraCell.swift index d9dee23..3f04ac7 100644 --- a/ImagePicker/VideoCameraCell.swift +++ b/ImagePicker/VideoCameraCell.swift @@ -42,6 +42,9 @@ class VideoCameraCell : CameraCollectionViewCell { //update button state recordButton.isSelected = isRecording + //update duration label + isRecording ? recordLabel.start() : recordLabel.stop() + //update other buttons let updates: () -> Void = { self.flipButton.alpha = isRecording ? 0 : 1 From 5d5bb8083426780b4629e7c18a30fc5c268693ad Mon Sep 17 00:00:00 2001 From: Peter Stajger Date: Wed, 25 Oct 2017 12:06:39 +0200 Subject: [PATCH 08/14] #12 updated duration formatting - cant use date components formatter because it does not pad first zero for hours, formating manually --- ImagePicker/RecordDurationLabel.swift | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/ImagePicker/RecordDurationLabel.swift b/ImagePicker/RecordDurationLabel.swift index bee9fea..9a4685e 100644 --- a/ImagePicker/RecordDurationLabel.swift +++ b/ImagePicker/RecordDurationLabel.swift @@ -13,14 +13,6 @@ import UIKit /// duration in general. /// final class RecordDurationLabel : UILabel { - - private static let durationFormatter: DateComponentsFormatter = { - let formatter = DateComponentsFormatter() - formatter.unitsStyle = .positional - formatter.allowedUnits = [.minute, .second] - formatter.zeroFormattingBehavior = .pad - return formatter - }() private var indicatorLayer: CALayer = { let layer = CALayer() @@ -50,7 +42,7 @@ final class RecordDurationLabel : UILabel { // MARK: Public Methods private var timer: Timer? - private var backingSeconds: TimeInterval = 0 { + private var backingSeconds: TimeInterval = 10000 { didSet { updateLabel() } } @@ -75,7 +67,13 @@ final class RecordDurationLabel : UILabel { // MARK: Private Methods private func updateLabel() { - text = RecordDurationLabel.durationFormatter.string(from: backingSeconds) + + //we are not using DateComponentsFormatter because it does not pad zero to hours component + //so it regurns pattern 0:00:00, we need 00:00:00 + let hours = Int(backingSeconds) / 3600 + let minutes = Int(backingSeconds) / 60 % 60 + let seconds = Int(backingSeconds) % 60 + text = String(format:"%02i:%02i:%02i", hours, minutes, seconds) } private func commonInit() { From 1669fd91b60b245ff129b5770701bee866738e00 Mon Sep 17 00:00:00 2001 From: Peter Stajger Date: Wed, 25 Oct 2017 12:11:13 +0200 Subject: [PATCH 09/14] #12 updated text alignment and fixed widht - so when label is updated, text acts like monospaced --- ImagePicker/VideoCameraCell.xib | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ImagePicker/VideoCameraCell.xib b/ImagePicker/VideoCameraCell.xib index 90452a6..687037a 100644 --- a/ImagePicker/VideoCameraCell.xib +++ b/ImagePicker/VideoCameraCell.xib @@ -49,8 +49,11 @@ -