Commit 1a7e95d5 authored by lmj_521aiau@163.com's avatar lmj_521aiau@163.com

Merge branch 'branch_1.0.1' of gitlab.huolea.com:lmi/shorthandmaster into branch_1.0.1

# Conflicts:
#	ShorthandMaster.xcodeproj/project.pbxproj

delete record  crash fix
parents d8bc51f3 483eb3fe
...@@ -139,6 +139,8 @@ ...@@ -139,6 +139,8 @@
CC29A709251C71AC0059BD5C /* SHSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC29A708251C71AC0059BD5C /* SHSwift.swift */; }; CC29A709251C71AC0059BD5C /* SHSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC29A708251C71AC0059BD5C /* SHSwift.swift */; };
CC29A716251C75210059BD5C /* SHInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC29A715251C75210059BD5C /* SHInputView.swift */; }; CC29A716251C75210059BD5C /* SHInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC29A715251C75210059BD5C /* SHInputView.swift */; };
CC29A71B251C790D0059BD5C /* SHInputBottomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC29A71A251C790D0059BD5C /* SHInputBottomView.swift */; }; CC29A71B251C790D0059BD5C /* SHInputBottomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC29A71A251C790D0059BD5C /* SHInputBottomView.swift */; };
CCAD0B782521C97F00781276 /* SHInputAudioPlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAD0B772521C97F00781276 /* SHInputAudioPlayView.swift */; };
CCAD0B7D2521D5C600781276 /* SHInputProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCAD0B7C2521D5C600781276 /* SHInputProgressView.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
...@@ -344,6 +346,8 @@ ...@@ -344,6 +346,8 @@
CC29A708251C71AC0059BD5C /* SHSwift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SHSwift.swift; sourceTree = "<group>"; }; CC29A708251C71AC0059BD5C /* SHSwift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SHSwift.swift; sourceTree = "<group>"; };
CC29A715251C75210059BD5C /* SHInputView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SHInputView.swift; sourceTree = "<group>"; }; CC29A715251C75210059BD5C /* SHInputView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SHInputView.swift; sourceTree = "<group>"; };
CC29A71A251C790D0059BD5C /* SHInputBottomView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SHInputBottomView.swift; sourceTree = "<group>"; }; CC29A71A251C790D0059BD5C /* SHInputBottomView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SHInputBottomView.swift; sourceTree = "<group>"; };
CCAD0B772521C97F00781276 /* SHInputAudioPlayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SHInputAudioPlayView.swift; sourceTree = "<group>"; };
CCAD0B7C2521D5C600781276 /* SHInputProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SHInputProgressView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
...@@ -848,6 +852,8 @@ ...@@ -848,6 +852,8 @@
CC13DB73251C9A2F00835654 /* SHInputTextView.swift */, CC13DB73251C9A2F00835654 /* SHInputTextView.swift */,
CC29A71A251C790D0059BD5C /* SHInputBottomView.swift */, CC29A71A251C790D0059BD5C /* SHInputBottomView.swift */,
CC13DB78251CA62800835654 /* SHInputAudioButton.swift */, CC13DB78251CA62800835654 /* SHInputAudioButton.swift */,
CCAD0B7C2521D5C600781276 /* SHInputProgressView.swift */,
CCAD0B772521C97F00781276 /* SHInputAudioPlayView.swift */,
); );
path = View; path = View;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -1128,6 +1134,7 @@ ...@@ -1128,6 +1134,7 @@
A95CE00A24E0F42F0066DAE6 /* CRDateFormatter.swift in Sources */, A95CE00A24E0F42F0066DAE6 /* CRDateFormatter.swift in Sources */,
A95CDFC024E0EBF10066DAE6 /* Date+Extension.swift in Sources */, A95CDFC024E0EBF10066DAE6 /* Date+Extension.swift in Sources */,
A924A84B251B842C00CB2947 /* SHRecordDetailsBottomView.swift in Sources */, A924A84B251B842C00CB2947 /* SHRecordDetailsBottomView.swift in Sources */,
CCAD0B782521C97F00781276 /* SHInputAudioPlayView.swift in Sources */,
A94EE118251B682C0066B490 /* SHSettingViewController.swift in Sources */, A94EE118251B682C0066B490 /* SHSettingViewController.swift in Sources */,
A95CDFC424E0EBF10066DAE6 /* Double+Extension.swift in Sources */, A95CDFC424E0EBF10066DAE6 /* Double+Extension.swift in Sources */,
CC13DB6A251C83E600835654 /* SHInputViewModel.swift in Sources */, CC13DB6A251C83E600835654 /* SHInputViewModel.swift in Sources */,
...@@ -1155,6 +1162,7 @@ ...@@ -1155,6 +1162,7 @@
A950F5AF24F4E06E007AB63E /* SHMineViewController.swift in Sources */, A950F5AF24F4E06E007AB63E /* SHMineViewController.swift in Sources */,
A95CE02F24E151340066DAE6 /* UIButton+Category.m in Sources */, A95CE02F24E151340066DAE6 /* UIButton+Category.m in Sources */,
A94D935924F7969600A886C0 /* CMNetworkManager.swift in Sources */, A94D935924F7969600A886C0 /* CMNetworkManager.swift in Sources */,
CCAD0B7D2521D5C600781276 /* SHInputProgressView.swift in Sources */,
A94DD56724FDF29700B1B5A2 /* XBAudioUnitPlayer.m in Sources */, A94DD56724FDF29700B1B5A2 /* XBAudioUnitPlayer.m in Sources */,
A94DD56F24FDF29700B1B5A2 /* XBAACEncoder_system.m in Sources */, A94DD56F24FDF29700B1B5A2 /* XBAACEncoder_system.m in Sources */,
A950F5AA24F3727A007AB63E /* SHRecordListCell.swift in Sources */, A950F5AA24F3727A007AB63E /* SHRecordListCell.swift in Sources */,
......
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "input_audio_10before@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "input_audio_10before@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "input_audio_10later@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "input_audio_10later@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "input_audio_pause@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "input_audio_pause@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "input_audio_play@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "input_audio_play@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "input_copy@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "input_copy@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "input_share@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "input_share@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
...@@ -12,6 +12,9 @@ import Photos ...@@ -12,6 +12,9 @@ import Photos
class SHInputController: SHBaseViewController class SHInputController: SHBaseViewController
{ {
// MARK: - property // MARK: - property
/// viewModel
var viewModel: SHInputViewModel = SHInputViewModel()
/// 文件夹model /// 文件夹model
var folderModel : SHRecordFolderModel! var folderModel : SHRecordFolderModel!
...@@ -24,6 +27,16 @@ class SHInputController: SHBaseViewController ...@@ -24,6 +27,16 @@ class SHInputController: SHBaseViewController
/// 未填写标题时的默认标题 /// 未填写标题时的默认标题
private let defaultTitle: String = "新建笔记" private let defaultTitle: String = "新建笔记"
/// 计时器
let timer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.global())
/// 音频播放器
var audioPlayer: AVAudioPlayer = AVAudioPlayer()
/// 播放计时器
let playTimer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.global())
private var shInputView: SHInputView! private var shInputView: SHInputView!
private let recorder_mp3: SHMp3RecordManager = SHMp3RecordManager.shared() private let recorder_mp3: SHMp3RecordManager = SHMp3RecordManager.shared()
...@@ -45,12 +58,49 @@ class SHInputController: SHBaseViewController ...@@ -45,12 +58,49 @@ class SHInputController: SHBaseViewController
self.addSubviews() self.addSubviews()
self.setUpSubviewsLocation() self.setUpSubviewsLocation()
// 初始化录音计时器
timer.schedule(deadline: .now(), repeating: 1)
timer.setEventHandler {
DispatchQueue.main.sync {
self.dataModel.during += 1
self.shInputView.bottomView.audioTimeLabel.text = self.viewModel.getTimeStringWithSeconds(seconds: self.dataModel.during)
}
}
// 初始化播放计时器
self.playTimer.schedule(deadline: .now(), repeating: 0.03)
self.playTimer.setEventHandler {
DispatchQueue.main.sync {
self.shInputView.bottomView.progressView.slider.value = Float(self.audioPlayer.currentTime) / Float(self.dataModel.during)
self.shInputView.bottomView.progressView.timeLabel.text = self.viewModel.getTimeStringWithSeconds(seconds: NSInteger(self.audioPlayer.currentTime))
}
}
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
self.timer.suspend()
self.timer.cancel()
self.shInputView.bottomView.timer.suspend()
self.shInputView.bottomView.timer.cancel()
self.playTimer.suspend()
self.playTimer.cancel()
if self.audioPlayer.isPlaying
{
self.audioPlayer.stop()
}
} }
// MARK: - UI // MARK: - UI
func addSubviews() func addSubviews()
{ {
self.shInputView = SHInputView.init() self.shInputView = SHInputView.init(frame: .zero, isEdited: self.dataModel.rename.length > 0)
self.shInputView.textView.delegate = self; self.shInputView.textView.delegate = self;
self.shInputView.textView.shDelegate = self; self.shInputView.textView.shDelegate = self;
self.view.addSubview(self.shInputView!) self.view.addSubview(self.shInputView!)
...@@ -62,60 +112,26 @@ class SHInputController: SHBaseViewController ...@@ -62,60 +112,26 @@ class SHInputController: SHBaseViewController
self.shInputView.bottomView.goOnAudioButton.addTarget(self, action: #selector(didSelectedGoOnAudioButton(sender:)), for: UIControl.Event.touchUpInside) self.shInputView.bottomView.goOnAudioButton.addTarget(self, action: #selector(didSelectedGoOnAudioButton(sender:)), for: UIControl.Event.touchUpInside)
self.shInputView.bottomView.stopAudioButton.addTarget(self, action: #selector(didSelectedStopAudioButton(sender:)), for: UIControl.Event.touchUpInside) self.shInputView.bottomView.stopAudioButton.addTarget(self, action: #selector(didSelectedStopAudioButton(sender:)), for: UIControl.Event.touchUpInside)
self.shInputView.bottomView.keyboardButton.addTarget(self, action: #selector(didSelectedKeyboardButton(sender:)), for: UIControl.Event.touchUpInside) self.shInputView.bottomView.keyboardButton.addTarget(self, action: #selector(didSelectedKeyboardButton(sender:)), for: UIControl.Event.touchUpInside)
self.shInputView.bottomView.progressView.beforeButton.addTarget(self, action: #selector(didSelectedBeforeButton(sender:)), for: .touchUpInside)
self.shInputView.bottomView.progressView.laterButton.addTarget(self, action: #selector(didSelectedLaterButton(sender:)), for: .touchUpInside)
self.shInputView.bottomView.progressView.slider.addTarget(self, action: #selector(sliderTouchBegin(sender:)), for: .touchDown)
self.shInputView.bottomView.progressView.slider.addTarget(self, action: #selector(sliderTouchEnd(sender:)), for: .touchUpInside)
self.shInputView.bottomView.playView.playButton.addTarget(self, action: #selector(didSelectedPlayButton(sender:)), for: .touchUpInside)
self.shInputView.bottomView.playView.speedButton.addTarget(self, action: #selector(didSelectedSpeedButton(sender:)), for: .touchUpInside)
// 有记录显示记录 // 有记录显示记录
if dataModel.rename.length > 0 if self.dataModel.rename.length > 0
{ {
// 隐藏占位文字
self.shInputView.placeholder.isHidden = true self.shInputView.placeholder.isHidden = true
let attributeString : NSMutableAttributedString = NSMutableAttributedString() // 显示记录
self.shInputView.textView.attributedText = self.viewModel.getAttributedStringWithSHRecordModel(recordModel: self.dataModel)
let titleString = NSAttributedString(string: self.dataModel.rename, attributes: (SHInputViewModel.titleAttributes() as! [NSAttributedString.Key : Any]))
attributeString.append(titleString)
let contentString = NSAttributedString(string: self.dataModel.txt, attributes: SHInputViewModel.contentAttributes() as? [NSAttributedString.Key : Any])
attributeString.append(contentString)
let imagesPath : Array = self.dataModel.imagesPath
let imagesIndex : Array = self.dataModel.imagesIndex
var i = 0
for imagePath : String in imagesPath
{
let image : UIImage = UIImage(contentsOfFile: DocumentPath + imagePath) ?? UIImage()
// 调整图片大小, 宽相同, 高随比例变化
let newWidth = kScreenWidth - 20 * 2
let newHeight = newWidth * image.size.height / image.size.width
let newSize = CGSize(width: newWidth, height: newHeight)
let imageLocation : Int = imagesIndex[i]
let attachment = NSTextAttachment.init()
attachment.image = image
attachment.bounds = CGRect(origin: CGPoint.zero, size: newSize)
let imageString = NSMutableAttributedString(attachment: attachment)
// 设置图片文字属性
imageString.addAttributes((SHInputViewModel.contentAttributes() as? [NSAttributedString.Key : Any])!, range: NSRange(location: 0, length: imageString.length))
// 设置图片间距
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 18
imageString.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: imageString.length))
attributeString.insert(imageString, at: imageLocation)
i += 1
}
self.shInputView.textView.attributedText = attributeString
} }
else else
{ {
// 默认文字样式 // 默认文字样式
self.shInputView.textView.typingAttributes = SHInputViewModel.titleAttributes() as! [NSAttributedString.Key : Any] self.shInputView.textView.typingAttributes = self.viewModel.titleAttributes() as! [NSAttributedString.Key : Any]
} }
} }
...@@ -146,7 +162,7 @@ class SHInputController: SHBaseViewController ...@@ -146,7 +162,7 @@ class SHInputController: SHBaseViewController
self.dataModel.createDate = Date() self.dataModel.createDate = Date()
self.dataModel.modifyDate = Date() self.dataModel.modifyDate = Date()
let imageArray = SHInputViewModel.setUpImageArrayWithTextView(textView: self.shInputView.textView) let imageArray = self.viewModel.setUpImageArrayWithTextView(textView: self.shInputView.textView)
self.dataModel.imagesPath = imageArray.imagesPathArray self.dataModel.imagesPath = imageArray.imagesPathArray
self.dataModel.imagesIndex = imageArray.imagesIndexArray self.dataModel.imagesIndex = imageArray.imagesIndexArray
...@@ -154,9 +170,15 @@ class SHInputController: SHBaseViewController ...@@ -154,9 +170,15 @@ class SHInputController: SHBaseViewController
if self.dataModel.rename.length == 0 if self.dataModel.rename.length == 0
{ {
self.dataModel.rename = defaultTitle self.dataModel.rename = defaultTitle
self.shInputView.textView.text = self.dataModel.rename
} }
self.dataModel.txt = self.shInputView.textView.text.substring(self.dataModel.rename.length, length: self.shInputView.textView.text.length - self.dataModel.rename.length)! self.dataModel.txt = self.shInputView.textView.text.substring(self.dataModel.rename.length, length: self.shInputView.textView.text.length - self.dataModel.rename.length) ?? ""
// 是否有录音都传, 用它来做为唯一表示
self.dataModel.pathFile = self.viewModel.documentFilePath + "/recorder.mp3"
self.dataModel.pcmPathFile = self.viewModel.documentFilePath + "/xbMixData.caf"
// 保存到沙盒 // 保存到沙盒
...@@ -225,13 +247,13 @@ extension SHInputController: UITextViewDelegate, SHInputTextViewDelegate ...@@ -225,13 +247,13 @@ extension SHInputController: UITextViewDelegate, SHInputTextViewDelegate
if range.location <= titleRange.location + titleRange.length if range.location <= titleRange.location + titleRange.length
{ {
// 使用标题字体 // 使用标题字体
textView.typingAttributes = SHInputViewModel.titleAttributes() as! [NSAttributedString.Key : Any] textView.typingAttributes = self.viewModel.titleAttributes() as! [NSAttributedString.Key : Any]
// 输入换行符即表示标题输入完成 // 输入换行符即表示标题输入完成
if (text.isEqualTo("\n")) if (text.isEqualTo("\n"))
{ {
// 开始输入内容字体 // 开始输入内容字体
textView.typingAttributes = SHInputViewModel.contentAttributes() as! [NSAttributedString.Key : Any] textView.typingAttributes = self.viewModel.contentAttributes() as! [NSAttributedString.Key : Any]
} }
else else
{ {
...@@ -246,7 +268,7 @@ extension SHInputController: UITextViewDelegate, SHInputTextViewDelegate ...@@ -246,7 +268,7 @@ extension SHInputController: UITextViewDelegate, SHInputTextViewDelegate
else else
{ {
// 使用内容字体 // 使用内容字体
textView.typingAttributes = SHInputViewModel.contentAttributes() as! [NSAttributedString.Key : Any] textView.typingAttributes = self.viewModel.contentAttributes() as! [NSAttributedString.Key : Any]
} }
return true return true
...@@ -337,7 +359,7 @@ extension SHInputController: UIImagePickerControllerDelegate, UINavigationContro ...@@ -337,7 +359,7 @@ extension SHInputController: UIImagePickerControllerDelegate, UINavigationContro
if self.dataModel.rename.length == 0 if self.dataModel.rename.length == 0
{ {
// 标题 // 标题
let titleString = NSMutableAttributedString(string: self.defaultTitle, attributes: (SHInputViewModel.titleAttributes() as! [NSAttributedString.Key : Any])) let titleString = NSMutableAttributedString(string: self.defaultTitle, attributes: (self.viewModel.titleAttributes() as! [NSAttributedString.Key : Any]))
self.shInputView.textView.attributedText = titleString self.shInputView.textView.attributedText = titleString
self.shInputView.placeholder.isHidden = true self.shInputView.placeholder.isHidden = true
...@@ -358,7 +380,7 @@ extension SHInputController: UIImagePickerControllerDelegate, UINavigationContro ...@@ -358,7 +380,7 @@ extension SHInputController: UIImagePickerControllerDelegate, UINavigationContro
let imageString = NSMutableAttributedString(attachment: attachment) let imageString = NSMutableAttributedString(attachment: attachment)
// 设置图片文字属性 // 设置图片文字属性
imageString.addAttributes((SHInputViewModel.contentAttributes() as? [NSAttributedString.Key : Any])!, range: NSRange(location: 0, length: imageString.length)) imageString.addAttributes((self.viewModel.contentAttributes() as? [NSAttributedString.Key : Any])!, range: NSRange(location: 0, length: imageString.length))
// 设置图片间距 // 设置图片间距
let paragraphStyle = NSMutableParagraphStyle() let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 18 paragraphStyle.lineSpacing = 18
...@@ -368,9 +390,9 @@ extension SHInputController: UIImagePickerControllerDelegate, UINavigationContro ...@@ -368,9 +390,9 @@ extension SHInputController: UIImagePickerControllerDelegate, UINavigationContro
// 如果前文以换行符结尾, 图片前面不再加换行符 // 如果前文以换行符结尾, 图片前面不再加换行符
if !textString.string.hasSuffix("\n") if !textString.string.hasSuffix("\n")
{ {
imageString.insert(NSAttributedString(string: "\n", attributes: (SHInputViewModel.contentAttributes() as! [NSAttributedString.Key : Any])), at: 0) imageString.insert(NSAttributedString(string: "\n", attributes: (self.viewModel.contentAttributes() as! [NSAttributedString.Key : Any])), at: 0)
} }
imageString.insert(NSAttributedString(string: "\n", attributes: (SHInputViewModel.contentAttributes() as! [NSAttributedString.Key : Any])), at: imageString.length) imageString.insert(NSAttributedString(string: "\n", attributes: (self.viewModel.contentAttributes() as! [NSAttributedString.Key : Any])), at: imageString.length)
// 合并内容 // 合并内容
textString.insert(imageString, at: self.shInputView.textView.selectedRange.location) textString.insert(imageString, at: self.shInputView.textView.selectedRange.location)
...@@ -378,7 +400,7 @@ extension SHInputController: UIImagePickerControllerDelegate, UINavigationContro ...@@ -378,7 +400,7 @@ extension SHInputController: UIImagePickerControllerDelegate, UINavigationContro
self.shInputView.textView.attributedText = textString self.shInputView.textView.attributedText = textString
// 使用内容字体 // 使用内容字体
self.shInputView.textView.typingAttributes = SHInputViewModel.contentAttributes() as! [NSAttributedString.Key : Any] self.shInputView.textView.typingAttributes = self.viewModel.contentAttributes() as! [NSAttributedString.Key : Any]
} }
// MARK: - Events // MARK: - Events
...@@ -587,70 +609,210 @@ extension SHInputController ...@@ -587,70 +609,210 @@ extension SHInputController
@objc func didSelectedAddAudioButton(sender : SHInputAudioButton) @objc func didSelectedAddAudioButton(sender : SHInputAudioButton)
{ {
self.shInputView.bottomView.addAudioButton.isHidden = true self.shInputView.bottomView.addAudioButton.isHidden = true
self.shInputView.bottomView.audioTimeBgView.isHidden = false
self.shInputView.bottomView.pauseAudioButton.isHidden = false self.shInputView.bottomView.pauseAudioButton.isHidden = false
self.shInputView.bottomView.goOnAudioButton.isHidden = true self.shInputView.bottomView.goOnAudioButton.isHidden = true
self.shInputView.bottomView.stopAudioButton.isHidden = false self.shInputView.bottomView.stopAudioButton.isHidden = true
self.shInputView.bottomView.playView.isHidden = true
let mp3Path : String = DocumentPath + "/recorder.mp3" self.shInputView.bottomView.setUpSubviewsLocation()
let pcmPath : String = DocumentPath + "/xbMixData.caf"
self.dataModel.pathFile = self.viewModel.documentFilePath + "/recorder.mp3"
self.dataModel.pcmPathFile = self.viewModel.documentFilePath + "/xbMixData.caf"
let mp3Path : String = DocumentPath + self.dataModel.pathFile
let pcmPath : String = DocumentPath + self.dataModel.pcmPathFile
recorder_mp3.configMp3Path(mp3Path, pcmPath: pcmPath) recorder_mp3.configMp3Path(mp3Path, pcmPath: pcmPath)
recorder_mp3.start() recorder_mp3.start()
print("mp3Path" + mp3Path) // 开始计时
print("pcmPath" + pcmPath) self.dataModel.during = -1
self.timer.resume()
// 小红点
self.shInputView.bottomView.setUpTimer()
self.shInputView.bottomView.audioTimePointViewAnimation(animation: true)
} }
// MARK: 点击暂停录音按钮 // MARK: 点击暂停录音按钮
@objc func didSelectedPauseAudioButton(sender : SHInputAudioButton) @objc func didSelectedPauseAudioButton(sender : SHInputAudioButton)
{ {
self.shInputView.bottomView.addAudioButton.isHidden = true self.shInputView.bottomView.addAudioButton.isHidden = true
self.shInputView.bottomView.audioTimeBgView.isHidden = false
self.shInputView.bottomView.pauseAudioButton.isHidden = true self.shInputView.bottomView.pauseAudioButton.isHidden = true
self.shInputView.bottomView.goOnAudioButton.isHidden = false self.shInputView.bottomView.goOnAudioButton.isHidden = false
self.shInputView.bottomView.stopAudioButton.isHidden = false self.shInputView.bottomView.stopAudioButton.isHidden = false
self.shInputView.bottomView.playView.isHidden = true
self.shInputView.bottomView.setUpSubviewsLocation()
recorder_mp3.pause() recorder_mp3.pause()
let mp3Path : String = DocumentPath + "/recorder.mp3" self.timer.suspend()
let pcmPath : String = DocumentPath + "/xbMixData.caf"
print("mp3Path" + mp3Path) self.shInputView.bottomView.audioTimePointViewAnimation(animation: false)
print("pcmPath" + pcmPath)
} }
// MARK: 点击继续录音按钮 // MARK: 点击继续录音按钮
@objc func didSelectedGoOnAudioButton(sender : SHInputAudioButton) @objc func didSelectedGoOnAudioButton(sender : SHInputAudioButton)
{ {
self.shInputView.bottomView.addAudioButton.isHidden = true self.shInputView.bottomView.addAudioButton.isHidden = true
self.shInputView.bottomView.audioTimeBgView.isHidden = false
self.shInputView.bottomView.pauseAudioButton.isHidden = false self.shInputView.bottomView.pauseAudioButton.isHidden = false
self.shInputView.bottomView.goOnAudioButton.isHidden = true self.shInputView.bottomView.goOnAudioButton.isHidden = true
self.shInputView.bottomView.stopAudioButton.isHidden = false self.shInputView.bottomView.stopAudioButton.isHidden = true
self.shInputView.bottomView.playView.isHidden = true
self.shInputView.bottomView.setUpSubviewsLocation()
recorder_mp3.start() recorder_mp3.start()
let mp3Path : String = DocumentPath + "/recorder.mp3" self.timer.resume()
let pcmPath : String = DocumentPath + "/xbMixData.caf"
print("mp3Path" + mp3Path) self.shInputView.bottomView.audioTimePointViewAnimation(animation: true)
print("pcmPath" + pcmPath)
} }
// MARK: 点击结束录制按钮 // MARK: 点击结束录制按钮
@objc func didSelectedStopAudioButton(sender : SHInputAudioButton) @objc func didSelectedStopAudioButton(sender : SHInputAudioButton)
{ {
self.shInputView.bottomView.addAudioButton.isHidden = false self.shInputView.bottomView.addAudioButton.isHidden = true
self.shInputView.bottomView.audioTimeBgView.isHidden = true
self.shInputView.bottomView.pauseAudioButton.isHidden = true self.shInputView.bottomView.pauseAudioButton.isHidden = true
self.shInputView.bottomView.goOnAudioButton.isHidden = true self.shInputView.bottomView.goOnAudioButton.isHidden = true
self.shInputView.bottomView.stopAudioButton.isHidden = true self.shInputView.bottomView.stopAudioButton.isHidden = true
self.shInputView.bottomView.playView.isHidden = false
self.shInputView.bottomView.setUpSubviewsLocation()
recorder_mp3.stop() recorder_mp3.stop()
let mp3Path : String = DocumentPath + "/recorder.mp3" self.timer.cancel()
let pcmPath : String = DocumentPath + "/xbMixData.caf" self.shInputView.bottomView.timer.cancel()
self.shInputView.bottomView.playView.timeLabel.text = self.viewModel.getTimeStringWithSeconds(seconds: self.dataModel.during)
self.initPlayer()
self.shInputView.setNeedsUpdateConstraints()
UIView.animate(withDuration: 0.3) {
self.shInputView.bottomView.mas_updateConstraints { (make) in
make?.height.mas_equalTo()(100 + SafeAreaBottomHeight())
}
self.shInputView.bottomView.progressView.alpha = 1;
self.shInputView.bottomView.superview!.layoutIfNeeded()
}
}
}
// MARK: - 播放
extension SHInputController: AVAudioPlayerDelegate {
// MARK: 初始化播放器
func initPlayer()
{
try? self.audioPlayer = AVAudioPlayer(contentsOf: URL(fileURLWithPath: DocumentPath + self.dataModel.pathFile), fileTypeHint: AVFileType.mp3.rawValue)
self.audioPlayer.prepareToPlay()
self.audioPlayer.numberOfLoops = 0 // 循环播放次数
self.audioPlayer.enableRate = true // 允许变速播放
self.audioPlayer.delegate = self
// 后台播放
let session = AVAudioSession.sharedInstance()
try? session.setCategory(AVAudioSession.Category.playAndRecord, options: .defaultToSpeaker)
}
// MARK: 点击播放/暂停按钮
@objc func didSelectedPlayButton(sender: UIButton)
{
if self.audioPlayer.isPlaying
{
self.audioPlayer.pause()
self.playTimer.suspend()
sender.setImage(UIImage(named: "input_audio_play"), for: .normal)
}
else
{
self.playTimer.resume()
self.audioPlayer.play()
sender.setImage(UIImage(named: "input_audio_pause"), for: .normal)
}
}
// MARK: 后退10s
@objc func didSelectedBeforeButton(sender: UIButton)
{
self.audioPlayer.currentTime = max(self.audioPlayer.currentTime - 2, 0)
self.audioPlayer.pause()
self.playTimer.suspend()
sender.setImage(UIImage(named: "input_audio_play"), for: .normal)
}
// MARK: 前进10s
@objc func didSelectedLaterButton(sender: UIButton)
{
self.audioPlayer.currentTime = min(self.audioPlayer.currentTime + 2, TimeInterval(self.dataModel.during))
self.audioPlayer.pause()
self.playTimer.suspend()
sender.setImage(UIImage(named: "input_audio_play"), for: .normal)
}
// MARK: 开始拖动进度条
@objc func sliderTouchBegin(sender: UISlider)
{
self.didSelectedPlayButton(sender: self.shInputView.bottomView.playView.playButton)
}
// MARK: 结束拖动进度条
@objc func sliderTouchEnd(sender: UISlider)
{
self.didSelectedPlayButton(sender: self.shInputView.bottomView.playView.playButton)
self.audioPlayer.currentTime = TimeInterval(Double(sender.value) * self.audioPlayer.duration)
}
// MARK: 切换倍速
@objc func didSelectedSpeedButton(sender: UIButton)
{
if sender.titleLabel!.text!.isEqualTo("x1.5")
{
self.audioPlayer.rate = 1.5
sender.setTitle("x2", for: .normal)
}
else if sender.titleLabel!.text!.isEqualTo("x2")
{
self.audioPlayer.rate = 2
sender.setTitle("x1", for: .normal)
}
else if sender.titleLabel!.text!.isEqualTo("x1")
{
self.audioPlayer.rate = 1
sender.setTitle("x1.5", for: .normal)
}
}
// MARK: - 代理
// MARK: 播放完成
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
self.shInputView.bottomView.playView.playButton.setImage(UIImage(named: "input_audio_play"), for: .normal)
self.shInputView.bottomView.progressView.slider.value = 1;
self.shInputView.bottomView.progressView.timeLabel.text = self.viewModel.getTimeStringWithSeconds(seconds: self.dataModel.during)
self.playTimer.suspend()
print("mp3Path" + mp3Path)
print("pcmPath" + pcmPath)
} }
} }
//
// SHInputAudioPlayView.swift
// ShorthandMaster
//
// Created by 张哲 on 2020/9/28.
// Copyright © 2020 明津李. All rights reserved.
//
import UIKit
class SHInputAudioPlayView: UIView {
// MARK: - property
/// 播放/暂停按钮
var playButton: UIButton!
/// 时长
var timeLabel: UILabel!
/// 竖线
var line: UIView!
/// 播放速度按钮
var speedButton: UIButton!
// MARK - func
override init(frame: CGRect)
{
super.init(frame: frame)
self.backgroundColor = UIColor(r: 241, g: 241, b: 241)
self.layer.masksToBounds = true
self.layer.cornerRadius = 15
self.addSubviews()
self.setUpSubviewsLocation()
}
required init?(coder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
// MAKR: - UI
func addSubviews()
{
// 播放/暂停按钮
self.playButton = UIButton(type: .custom)
self.playButton.setImage(UIImage(named: "input_audio_play"), for: .normal)
self.addSubview(self.playButton)
// 时长
self.timeLabel = UILabel()
self.timeLabel.textColor = UIColor(r: 65, g: 131, b: 244)
self.timeLabel.font = UIFont(name: SHPingFangMedium, size: 14)
self.addSubview(self.timeLabel)
// 竖线
self.line = UIView()
self.line.backgroundColor = UIColor(r: 65, g: 131, b: 244)
self.addSubview(self.line)
// 播放速度按钮
self.speedButton = UIButton(type: .system)
self.speedButton.setTitle("x1.5", for: .normal)
self.speedButton.setTitleColor(UIColor(r: 65, g: 131, b: 244), for: .normal)
self.speedButton.titleLabel?.font = UIFont(name: SHPingFangMedium, size: 14)
self.addSubview(self.speedButton)
}
// MARK: 控件位置
func setUpSubviewsLocation()
{
self.playButton.mas_makeConstraints { (make) in
make?.left.mas_equalTo()(9)
make?.centerY.mas_equalTo()(self)
make?.size.mas_equalTo()(CGSize(width: 27, height: 30))
}
self.timeLabel.mas_makeConstraints { (make) in
make?.left.equalTo()(self.playButton.mas_right)
make?.centerY.equalTo()(self)
}
self.line.mas_makeConstraints { (make) in
make?.right.mas_equalTo()(-55)
make?.centerY.equalTo()(self)
make?.size.mas_equalTo()(CGSize(width: 1, height: 8))
}
self.speedButton.mas_makeConstraints { (make) in
make?.left.equalTo()(self.line.mas_right)
make?.right.mas_equalTo()(-9)
make?.top.bottom()?.mas_equalTo()(0)
}
}
}
...@@ -11,8 +11,9 @@ import UIKit ...@@ -11,8 +11,9 @@ import UIKit
class SHInputBottomView: UIView { class SHInputBottomView: UIView {
// MARK: - property // MARK: - property
/// 背景 /// 分割线
var bgView : UIView! var line : UIView!
/// 选择图片按钮 /// 选择图片按钮
var imageButton : UIButton! var imageButton : UIButton!
...@@ -20,15 +21,16 @@ class SHInputBottomView: UIView { ...@@ -20,15 +21,16 @@ class SHInputBottomView: UIView {
/// 录音按钮背景 /// 录音按钮背景
var audioBgView : UIView! var audioBgView : UIView!
/// 添加录音按钮
var addAudioButton : SHInputAudioButton!
/// 录制时间背景 /// 录制时间背景
var audioTimeBgView : UIView! var audioTimeBgView : UIView!
/// 录制时间小红点 /// 录制时间小红点
var audioTimePointView : UIView! var audioTimePointView : UIView!
/// 录制时间 /// 录制时间
var audioTimeLabel : UIView! var audioTimeLabel : UILabel!
/// 添加录音按钮
var addAudioButton : SHInputAudioButton!
/// 暂停录音按钮 /// 暂停录音按钮
var pauseAudioButton : SHInputAudioButton! var pauseAudioButton : SHInputAudioButton!
/// 继续录音按钮 /// 继续录音按钮
...@@ -36,6 +38,13 @@ class SHInputBottomView: UIView { ...@@ -36,6 +38,13 @@ class SHInputBottomView: UIView {
/// 结束录音按钮 /// 结束录音按钮
var stopAudioButton : SHInputAudioButton! var stopAudioButton : SHInputAudioButton!
/// 录制结束播放控件
var playView: SHInputAudioPlayView!
/// 播放进度条
var progressView: SHInputProgressView!
/// 键盘按钮 /// 键盘按钮
var keyboardButton : UIButton! var keyboardButton : UIButton!
...@@ -43,48 +52,55 @@ class SHInputBottomView: UIView { ...@@ -43,48 +52,55 @@ class SHInputBottomView: UIView {
var directionImageView : UIImageView! var directionImageView : UIImageView!
/// 计时器控制小红点闪烁
let timer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.global())
// MARK: - func // MARK: - func
override init(frame: CGRect) init(frame:CGRect, isEdited: Bool)
{ {
super.init(frame: frame) super.init(frame: frame)
self.backgroundColor = UIColor.white self.backgroundColor = UIColor.white
self.layer.masksToBounds = true
self.addSubviews() self.addSubviews()
if isEdited
{
self.setUpEditedSUbviewsLocation()
}
else
{
self.setUpSubviewsLocation() self.setUpSubviewsLocation()
} }
}
required init?(coder: NSCoder) required init?(coder: NSCoder)
{ {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
// MAKR: - UI // MAKR: - UI
func addSubviews() func addSubviews()
{ {
// 背景 // 分割线
self.bgView = UIView() self.line = UIView()
self.bgView.backgroundColor = UIColor(r: 249, g: 249, b: 249) self.line.backgroundColor = UIColor(r: 221, g: 221, b: 221)
self.addSubview(self.bgView) self.addSubview(self.line)
// 选择图片按钮 // 选择图片按钮
self.imageButton = UIButton(type: UIButton.ButtonType.custom) self.imageButton = UIButton(type: UIButton.ButtonType.custom)
self.imageButton.setImage(UIImage(named: "input_image"), for: UIControl.State.normal) self.imageButton.setImage(UIImage(named: "input_image"), for: UIControl.State.normal)
self.bgView.addSubview(self.imageButton) self.addSubview(self.imageButton)
// 录音按钮背景 // 录音按钮背景
self.audioBgView = UIView() self.audioBgView = UIView()
self.bgView.addSubview(self.audioBgView) // self.audioBgView.backgroundColor = UIColor.red
self.addSubview(self.audioBgView)
// 录制时间背景
self.audioTimeBgView = UIView()
self.audioTimeBgView.backgroundColor = UIColor(r: 241, g: 241, b: 241)
self.audioTimeBgView.layer.masksToBounds = true
self.bgView.addSubview(self.audioTimeBgView)
// 录制时间小红点
// 录制时间
// 添加录音按钮 // 添加录音按钮
self.addAudioButton = SHInputAudioButton(type: UIButton.ButtonType.custom) self.addAudioButton = SHInputAudioButton(type: UIButton.ButtonType.custom)
...@@ -95,6 +111,27 @@ class SHInputBottomView: UIView { ...@@ -95,6 +111,27 @@ class SHInputBottomView: UIView {
self.addAudioButton.rightLabel.textColor = UIColor(r: 244, g: 65, b: 65) self.addAudioButton.rightLabel.textColor = UIColor(r: 244, g: 65, b: 65)
self.audioBgView.addSubview(self.addAudioButton) self.audioBgView.addSubview(self.addAudioButton)
// 录制时间背景
self.audioTimeBgView = UIView()
self.audioTimeBgView.backgroundColor = UIColor(r: 241, g: 241, b: 241)
self.audioTimeBgView.layer.masksToBounds = true
self.audioTimeBgView.layer.cornerRadius = 15
self.addSubview(self.audioTimeBgView)
self.audioTimeBgView.isHidden = true
// 录制时间小红点
self.audioTimePointView = UIView()
self.audioTimePointView.backgroundColor = UIColor(r: 244, g: 65, b: 65)
self.audioTimePointView.layer.masksToBounds = true
self.audioTimePointView.layer.cornerRadius = 2
self.audioTimeBgView.addSubview(self.audioTimePointView)
// 录制时间
self.audioTimeLabel = UILabel()
self.audioTimeLabel.textColor = UIColor(r: 65, g: 131, b: 244)
self.audioTimeLabel.font = UIFont(name: SHPingFangMedium, size: 14)
self.audioTimeBgView.addSubview(self.audioTimeLabel)
// 暂停录音按钮 // 暂停录音按钮
self.pauseAudioButton = SHInputAudioButton(type: UIButton.ButtonType.custom) self.pauseAudioButton = SHInputAudioButton(type: UIButton.ButtonType.custom)
self.pauseAudioButton.layer.cornerRadius = 15 self.pauseAudioButton.layer.cornerRadius = 15
...@@ -120,91 +157,203 @@ class SHInputBottomView: UIView { ...@@ -120,91 +157,203 @@ class SHInputBottomView: UIView {
self.stopAudioButton.layer.cornerRadius = 15 self.stopAudioButton.layer.cornerRadius = 15
self.stopAudioButton.backgroundColor = UIColor(r: 250, g: 219, b: 219) self.stopAudioButton.backgroundColor = UIColor(r: 250, g: 219, b: 219)
self.stopAudioButton.leftImageView.image = UIImage(named: "input_stop") self.stopAudioButton.leftImageView.image = UIImage(named: "input_stop")
self.stopAudioButton.rightLabel.text = "结束录制" self.stopAudioButton.rightLabel.text = "结束"
self.stopAudioButton.rightLabel.textColor = UIColor(r: 244, g: 65, b: 65) self.stopAudioButton.rightLabel.textColor = UIColor(r: 244, g: 65, b: 65)
self.audioBgView.addSubview(self.stopAudioButton) self.audioBgView.addSubview(self.stopAudioButton)
self.stopAudioButton.isHidden = true self.stopAudioButton.isHidden = true
// 录制结束播放控件
self.playView = SHInputAudioPlayView()
self.addSubview(self.playView)
self.playView.isHidden = true
// 播放进度条
self.progressView = SHInputProgressView()
self.addSubview(self.progressView)
self.progressView.alpha = 0;
// 键盘按钮 // 键盘按钮
self.keyboardButton = UIButton(type: UIButton.ButtonType.custom) self.keyboardButton = UIButton(type: UIButton.ButtonType.custom)
self.keyboardButton.setImage(UIImage(named: "input_keyboard"), for: UIControl.State.normal) self.keyboardButton.setImage(UIImage(named: "input_keyboard"), for: UIControl.State.normal)
self.bgView.addSubview(self.keyboardButton) self.addSubview(self.keyboardButton)
// 箭头图片 // 箭头图片
self.directionImageView = UIImageView() self.directionImageView = UIImageView()
self.directionImageView.image = UIImage(named: "input_down") self.directionImageView.image = UIImage(named: "input_down")
self.bgView.addSubview(self.directionImageView) self.addSubview(self.directionImageView)
} }
// MARK: 控件位置 // MARK: - 控件位置
// MARK: 编辑时的控件位置
func setUpEditedSUbviewsLocation()
{
}
// MARK: 新增时的控件位置
func setUpSubviewsLocation() func setUpSubviewsLocation()
{ {
self.bgView.mas_makeConstraints { (make) in
for constraint in self.audioBgView.constraints
{
self.audioBgView.removeConstraint(constraint)
}
self.line.mas_makeConstraints { (make) in
make?.top.left()?.right()?.mas_equalTo()(0) make?.top.left()?.right()?.mas_equalTo()(0)
make?.bottom.mas_equalTo()(-SafeAreaBottomHeight()) make?.height.mas_equalTo()(1)
} }
self.imageButton.mas_makeConstraints { (make) in self.imageButton.mas_makeConstraints { (make) in
make?.top.bottom()?.mas_equalTo()(0) make?.bottom.mas_equalTo()(-SafeAreaBottomHeight())
make?.left.mas_equalTo()(39 - 11) make?.left.mas_equalTo()(10)
make?.width.height()?.mas_equalTo()(self.bgView.mas_height) make?.width.height()?.mas_equalTo()(28 + 10 * 2)
} }
self.audioBgView.mas_makeConstraints { (make) in self.audioBgView.mas_remakeConstraints { (make) in
make?.center.equalTo()(self.bgView) make?.centerX.equalTo()(self)
make?.size.mas_equalTo()(CGSize(width: 72 + 18 + 100, height: 50)) make?.bottom.mas_equalTo()(-SafeAreaBottomHeight())
make?.height.mas_equalTo()(50)
} }
self.addAudioButton.mas_makeConstraints { (make) in if self.addAudioButton.isHidden == false
{
self.addAudioButton.mas_remakeConstraints { (make) in
make?.left.right()?.equalTo()(self.audioBgView)
make?.center.equalTo()(self.audioBgView) make?.center.equalTo()(self.audioBgView)
make?.size.mas_equalTo()(CGSize(width: 100, height: 30)) make?.size.mas_equalTo()(CGSize(width: 100, height: 30))
} }
}
self.pauseAudioButton.mas_makeConstraints { (make) in if self.audioTimeBgView.isHidden == false
{
self.audioTimeBgView.mas_remakeConstraints { (make) in
make?.left.mas_equalTo()(0) make?.left.equalTo()(self.audioBgView)
make?.centerY.equalTo()(self.audioBgView)
make?.size.mas_equalTo()(CGSize(width: 81, height: 30))
}
self.audioTimePointView.mas_remakeConstraints { (make) in
make?.left.mas_equalTo()(8)
make?.centerY.equalTo()(self.audioTimeBgView)
make?.width.height()?.mas_equalTo()(4)
}
self.audioTimeLabel.mas_remakeConstraints { (make) in
make?.left.equalTo()(self.audioTimePointView.mas_right)?.offset()(3)
make?.centerY.equalTo()(self.audioTimeBgView)
}
}
if self.pauseAudioButton.isHidden == false
{
self.pauseAudioButton.mas_remakeConstraints { (make) in
make?.right.mas_equalTo()(0)
make?.left.equalTo()(self.audioTimeBgView.mas_right)?.offset()(8)
make?.centerY.equalTo()(self.audioBgView) make?.centerY.equalTo()(self.audioBgView)
make?.size.mas_equalTo()(CGSize(width: 72, height: 30)) make?.size.mas_equalTo()(CGSize(width: 72, height: 30))
} }
}
self.goOnAudioButton.mas_makeConstraints { (make) in if self.goOnAudioButton.isHidden == false
{
self.goOnAudioButton.mas_remakeConstraints { (make) in
make?.top.left()?.bottom()?.right()?.equalTo()(self.pauseAudioButton) make?.left.equalTo()(self.audioTimeBgView.mas_right)?.offset()(8)
make?.centerY.equalTo()(self.audioBgView)
make?.size.mas_equalTo()(CGSize(width: 72, height: 30))
} }
}
self.stopAudioButton.mas_makeConstraints { (make) in if self.stopAudioButton.isHidden == false
{
self.stopAudioButton.mas_remakeConstraints { (make) in
make?.left.equalTo()(self.pauseAudioButton.mas_right)?.offset()(18)
make?.right.mas_equalTo()(0) make?.right.mas_equalTo()(0)
make?.left.equalTo()(self.goOnAudioButton.mas_right)?.offset()(8)
make?.centerY.equalTo()(self.audioBgView) make?.centerY.equalTo()(self.audioBgView)
make?.size.mas_equalTo()(CGSize(width: 100, height: 30)) make?.size.mas_equalTo()(CGSize(width: 72, height: 30))
}
}
self.playView.mas_makeConstraints { (make) in
make?.centerX.equalTo()(self)
make?.bottom.mas_equalTo()(-SafeAreaBottomHeight() - 10)
make?.size.mas_equalTo()(CGSize(width: 160, height: 30))
}
self.progressView.mas_makeConstraints { (make) in
make?.top.left()?.right()?.mas_equalTo()(self)
make?.height.mas_equalTo()(50)
} }
self.keyboardButton.mas_makeConstraints { (make) in self.keyboardButton.mas_makeConstraints { (make) in
make?.top.bottom()?.mas_equalTo()(0) make?.bottom.mas_equalTo()(-SafeAreaBottomHeight())
make?.right.mas_equalTo()(11 - 40) make?.right.mas_equalTo()(10 - 40)
make?.size.equalTo()(self.imageButton) make?.size.equalTo()(self.imageButton)
} }
self.directionImageView.mas_makeConstraints { (make) in self.directionImageView.mas_makeConstraints { (make) in
make?.centerY.equalTo()(self.bgView) make?.bottom.mas_equalTo()(-SafeAreaBottomHeight() - 16)
make?.width.height()?.mas_equalTo()(16) make?.width.height()?.mas_equalTo()(16)
make?.right.mas_equalTo()(-20) make?.right.mas_equalTo()(-20)
} }
} }
// MARK: 计时器方法
func setUpTimer()
{
// 开始计时
timer.schedule(deadline: .now(), repeating: 0.5)
timer.setEventHandler {
DispatchQueue.main.sync {
print("在集市")
self.audioTimePointView.isHidden = !self.audioTimePointView.isHidden
}
}
}
// MARK: 小圆点闪烁方法
func audioTimePointViewAnimation(animation: Bool)
{
if animation
{
timer.resume()
}
else
{
timer.suspend()
self.audioTimePointView.isHidden = false
}
}
} }
//
// SHInputProgressView.swift
// ShorthandMaster
//
// Created by 张哲 on 2020/9/28.
// Copyright © 2020 明津李. All rights reserved.
//
import UIKit
class SHInputProgressView: UIView {
// MARK: - property
/// 后退10s按钮
var beforeButton: UIButton!
/// 前进10s按钮
var laterButton: UIButton!
/// 进度条
var slider: UISlider!
/// 播放时间
var timeLabel: UILabel!
// MARK - func
override init(frame: CGRect)
{
super.init(frame: frame)
self.addSubviews()
self.setUpSubviewsLocation()
}
required init?(coder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
// MAKR: - UI
func addSubviews()
{
// 后退10s按钮
self.beforeButton = UIButton(type: .custom)
self.beforeButton.setImage(UIImage(named: "input_audio_10before"), for: .normal)
self.addSubview(self.beforeButton)
// 前进10s按钮
self.laterButton = UIButton(type: .custom)
self.laterButton.setImage(UIImage(named: "input_audio_10later"), for: .normal)
self.addSubview(self.laterButton)
// 进度条
self.slider = UISlider()
self.slider.minimumTrackTintColor = UIColor(r: 102, g: 160, b: 255)
self.slider.maximumTrackTintColor = UIColor(r: 238, g: 238, b: 238)
self.addSubview(self.slider)
let thumView = UIView(frame: CGRect(x: 0, y: 0, width: 12, height: 12))
thumView.backgroundColor = UIColor(r: 102, g: 160, b: 255)
thumView.layer.masksToBounds = true
thumView.cornerRadius = 6
self.slider.setThumbImage(UIImage.imageWithView2(view: thumView), for: .normal)
self.slider.setThumbImage(UIImage.imageWithView2(view: thumView), for: .highlighted)
// 播放时间
self.timeLabel = UILabel()
self.timeLabel.text = "00:00:00"
self.timeLabel.textColor = UIColor(r: 102, g: 102, b: 102)
self.timeLabel.font = UIFont(name: SHPingFangRegular, size: 14)
self.addSubview(self.timeLabel)
}
// MARK: 控件位置
func setUpSubviewsLocation()
{
self.beforeButton.mas_makeConstraints { (make) in
make?.left.mas_equalTo()(20 - 8)
make?.centerY.mas_equalTo()(self)
make?.size.mas_equalTo()(CGSize(width: 24 + 8 * 2, height: 24 + 14 * 2))
}
self.laterButton.mas_makeConstraints { (make) in
make?.right.mas_equalTo()(8 - 20)
make?.centerY.mas_equalTo()(self)
make?.size.mas_equalTo()(CGSize(width: 24 + 8 * 2, height: 24 + 14 * 2))
}
self.slider.mas_makeConstraints { (make) in
make?.left.equalTo()(self.beforeButton.mas_right)
make?.right.equalTo()(self.timeLabel.mas_left)?.offset()(-8)
make?.centerY.mas_equalTo()(self)
make?.height.mas_equalTo()(24)
}
self.timeLabel.mas_makeConstraints { (make) in
make?.right.equalTo()(self.laterButton.mas_left)?.offset()(-8)
make?.centerY.mas_equalTo()(self)
make?.width.mas_equalTo()(60)
}
}
}
...@@ -28,6 +28,13 @@ class SHInputTextView: UITextView { ...@@ -28,6 +28,13 @@ class SHInputTextView: UITextView {
{ {
delegateOK.textViewDidDelete?(textView: self) delegateOK.textViewDidDelete?(textView: self)
} }
}
}
extension SHInputTextView: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
} }
} }
...@@ -16,11 +16,16 @@ class SHInputView: UIView { ...@@ -16,11 +16,16 @@ class SHInputView: UIView {
var bottomView : SHInputBottomView! var bottomView : SHInputBottomView!
var isEdited: Bool = Bool()
// MARK: - func // MARK: - func
override init(frame: CGRect) init(frame: CGRect, isEdited: Bool)
{ {
super.init(frame: frame) super.init(frame: frame)
self.isEdited = isEdited
self.addSubviews() self.addSubviews()
self.setUpSubviewsLocation() self.setUpSubviewsLocation()
...@@ -32,6 +37,8 @@ class SHInputView: UIView { ...@@ -32,6 +37,8 @@ class SHInputView: UIView {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(note:)), name: UIResponder.keyboardWillHideNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(note:)), name: UIResponder.keyboardWillHideNotification, object: nil)
} }
required init?(coder: NSCoder) { required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
...@@ -45,6 +52,7 @@ class SHInputView: UIView { ...@@ -45,6 +52,7 @@ class SHInputView: UIView {
self.textView.textColor = UIColor.init(r: 34, g: 34, b: 34, a: 1) self.textView.textColor = UIColor.init(r: 34, g: 34, b: 34, a: 1)
self.textView.font = UIFont.init(name: SHPingFangMedium, size: 18) self.textView.font = UIFont.init(name: SHPingFangMedium, size: 18)
self.textView.contentInset = UIEdgeInsets.init(top: 24, left: 0, bottom: 0, right: 0); self.textView.contentInset = UIEdgeInsets.init(top: 24, left: 0, bottom: 0, right: 0);
self.textView.alwaysBounceVertical = true
self.addSubview(self.textView) self.addSubview(self.textView)
// 占位文字 // 占位文字
...@@ -55,7 +63,7 @@ class SHInputView: UIView { ...@@ -55,7 +63,7 @@ class SHInputView: UIView {
self.textView.addSubview(self.placeholder) self.textView.addSubview(self.placeholder)
// 底部栏 // 底部栏
self.bottomView = SHInputBottomView.init() self.bottomView = SHInputBottomView.init(frame: .zero, isEdited: isEdited)
self.addSubview(self.bottomView) self.addSubview(self.bottomView)
} }
...@@ -107,9 +115,7 @@ class SHInputView: UIView { ...@@ -107,9 +115,7 @@ class SHInputView: UIView {
weakSelf?.bottomView.mas_updateConstraints { (make) in weakSelf?.bottomView.mas_updateConstraints { (make) in
make?.left.right()?.mas_equalTo()(0)
make?.bottom.mas_equalTo()(-height + SafeAreaBottomHeight()) make?.bottom.mas_equalTo()(-height + SafeAreaBottomHeight())
make?.height.mas_equalTo()(50 + SafeAreaBottomHeight());
} }
...@@ -131,8 +137,7 @@ class SHInputView: UIView { ...@@ -131,8 +137,7 @@ class SHInputView: UIView {
weakSelf?.bottomView.mas_updateConstraints { (make) in weakSelf?.bottomView.mas_updateConstraints { (make) in
make?.left.right().bottom()?.mas_equalTo()(0) make?.bottom.mas_equalTo()(0)
make?.height.mas_equalTo()(50 + SafeAreaBottomHeight());
} }
......
...@@ -11,22 +11,11 @@ import UIKit ...@@ -11,22 +11,11 @@ import UIKit
class SHInputViewModel: NSObject { class SHInputViewModel: NSObject {
// MARK: - property // MARK: - property
// /// 标题文字
// var title : String = ""
// /// 内容文字
// var content : String = ""
// /// 图片数组
// var imageArray : Array = Array<Any>()
// var recordModel : SHRecordModel = SHRecordModel()
// MARK: - func // MARK: - func
// MARK: 标题文字样式 // MARK: 标题文字样式
class func titleAttributes() -> NSDictionary func titleAttributes() -> NSDictionary
{ {
let paragraphStyle : NSMutableParagraphStyle = NSMutableParagraphStyle.init() let paragraphStyle : NSMutableParagraphStyle = NSMutableParagraphStyle.init()
paragraphStyle.lineSpacing = 5; paragraphStyle.lineSpacing = 5;
...@@ -40,7 +29,7 @@ class SHInputViewModel: NSObject { ...@@ -40,7 +29,7 @@ class SHInputViewModel: NSObject {
} }
// MARK: 内容文字样式 // MARK: 内容文字样式
class func contentAttributes() -> NSDictionary func contentAttributes() -> NSDictionary
{ {
let paragraphStyle : NSMutableParagraphStyle = NSMutableParagraphStyle.init() let paragraphStyle : NSMutableParagraphStyle = NSMutableParagraphStyle.init()
paragraphStyle.lineSpacing = 5; paragraphStyle.lineSpacing = 5;
...@@ -53,30 +42,54 @@ class SHInputViewModel: NSObject { ...@@ -53,30 +42,54 @@ class SHInputViewModel: NSObject {
return titleAttributes return titleAttributes
} }
// MARK: 获取textView中的图片, 保存到本地, 并生成数组 // MARK: 沙盒文件夹路径, 生成沙盒文件, 图片和录音都保存在这个路径下
class func setUpImageArrayWithTextView(textView: UITextView) -> (imagesPathArray: Array<String>, imagesIndexArray: Array<Int>) lazy var documentFilePath : String = {
{
/// 图片路径数组
var imagesPathArray = Array<String>()
/// 图片位置数组
var imagesIndexArray = Array<Int>()
// 创建文件夹 let dateFormat = Date().format("yyyyMMdd")
/// 文件夹路径
let subFile = Date().format("yyyyMMdd")
let time = Date.init().timeStamp let time = Date.init().timeStamp
let filePath = DocumentPath + "/" + subFile + time
let filePath = "/" + dateFormat + time
if !FileManager.default.fileExists(atPath: DocumentPath + filePath)
{
do do
{ {
try FileManager.default.createDirectory(atPath: filePath, withIntermediateDirectories: true, attributes: nil) try FileManager.default.createDirectory(atPath: DocumentPath + filePath, withIntermediateDirectories: true, attributes: nil)
} }
catch let error catch let error
{ {
print(error) print(error)
}
return (imagesPathArray, imagesIndexArray)
} }
return filePath
}()
// MARK: 获取textView中的图片, 保存到本地, 并生成数组
func setUpImageArrayWithTextView(textView: UITextView) -> (imagesPathArray: Array<String>, imagesIndexArray: Array<Int>)
{
/// 图片路径数组
var imagesPathArray = Array<String>()
/// 图片位置数组
var imagesIndexArray = Array<Int>()
// // 创建文件夹
// /// 文件夹路径
// let dateFormat = Date().format("yyyyMMdd")
// let time = Date.init().timeStamp
// let filePath = DocumentPath + "/" + dateFormat + time
// do
// {
// try FileManager.default.createDirectory(atPath: filePath, withIntermediateDirectories: true, attributes: nil)
// }
// catch let error
// {
// print(error)
//
// return (imagesPathArray, imagesIndexArray)
// }
// 遍历textView文字中的NSTextAttachment // 遍历textView文字中的NSTextAttachment
let attributedString = textView.attributedText let attributedString = textView.attributedText
...@@ -96,7 +109,7 @@ class SHInputViewModel: NSObject { ...@@ -96,7 +109,7 @@ class SHInputViewModel: NSObject {
let imageData : Data = (imageAttachment.image?.jpegData(compressionQuality: 1.0))! let imageData : Data = (imageAttachment.image?.jpegData(compressionQuality: 1.0))!
// 保存的本地路径 // 保存的本地路径
let imagePath = "/" + subFile + time + "/" + "image.jpeg" + imagesPathArray.count.string let imagePath = self.documentFilePath + "/image" + imagesPathArray.count.string + ".jpeg"
let imageUrl : URL = URL(fileURLWithPath: DocumentPath + imagePath) let imageUrl : URL = URL(fileURLWithPath: DocumentPath + imagePath)
...@@ -128,4 +141,62 @@ class SHInputViewModel: NSObject { ...@@ -128,4 +141,62 @@ class SHInputViewModel: NSObject {
return (imagesPathArray, imagesIndexArray) return (imagesPathArray, imagesIndexArray)
} }
// MARK: 编辑状态下进入页面时, 把SHRecordModel类型数据转成NSMutableAttributedString
func getAttributedStringWithSHRecordModel(recordModel: SHRecordModel) -> NSAttributedString
{
let attributeString : NSMutableAttributedString = NSMutableAttributedString()
let titleString = NSAttributedString(string: recordModel.rename, attributes: (self.titleAttributes() as! [NSAttributedString.Key : Any]))
attributeString.append(titleString)
let contentString = NSAttributedString(string: recordModel.txt, attributes: self.contentAttributes() as? [NSAttributedString.Key : Any])
attributeString.append(contentString)
let imagesPath : Array = recordModel.imagesPath
let imagesIndex : Array = recordModel.imagesIndex
var i = 0
for imagePath : String in imagesPath
{
let image : UIImage = UIImage(contentsOfFile: DocumentPath + imagePath) ?? UIImage()
// 调整图片大小, 宽相同, 高随比例变化
let newWidth = kScreenWidth - 20 * 2
let newHeight = newWidth * image.size.height / image.size.width
let newSize = CGSize(width: newWidth, height: newHeight)
let imageLocation : Int = imagesIndex[i]
let attachment = NSTextAttachment.init()
attachment.image = image
attachment.bounds = CGRect(origin: CGPoint.zero, size: newSize)
let imageString = NSMutableAttributedString(attachment: attachment)
// 设置图片文字属性
imageString.addAttributes((self.contentAttributes() as? [NSAttributedString.Key : Any])!, range: NSRange(location: 0, length: imageString.length))
// 设置图片间距
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 18
imageString.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: imageString.length))
attributeString.insert(imageString, at: imageLocation)
i += 1
}
return attributeString
}
// MARK: 秒数转00:00:00格式
func getTimeStringWithSeconds(seconds : NSInteger) -> String
{
let hour = seconds / 60 / 60
let minute = (seconds - hour * 60 * 60) / 60
let second = seconds - hour * 60 * 60 - minute * 60
return String(format: "%02d:%02d:%02d", hour, minute, second)
}
} }
...@@ -244,12 +244,13 @@ extension SHRecordDetailsVC { ...@@ -244,12 +244,13 @@ extension SHRecordDetailsVC {
} }
} }
//MARK:icloud 移除 Models //MARK:icloud 移除 Models
func icloundRemove(_ index:NSInteger){ func icloudRemove(_ index:NSInteger){
let model = currentModel.dataSources[index] let model = currentModel.dataSources[index]
SHCloudManager.shared.deleteRecord(model) { (result, models) in SHCloudManager.shared.deleteRecord(model) { (result, models) in
if result { if result {
model.icloud = false model.icloud = false
if let _ = SHCloudManager.shared.icloudFolderModels.filter({ $0.id == self.currentModel.id }).first{
SHCloudManager.shared.modifyFolder(self.currentModel) { (result, models) in SHCloudManager.shared.modifyFolder(self.currentModel) { (result, models) in
if result { if result {
self.updateocloudUI() self.updateocloudUI()
...@@ -258,6 +259,7 @@ extension SHRecordDetailsVC { ...@@ -258,6 +259,7 @@ extension SHRecordDetailsVC {
} }
} }
} }
}
//MARK:删除Models //MARK:删除Models
func deleteFile(){ func deleteFile(){
if selectRecordModels.count == 0 { if selectRecordModels.count == 0 {
...@@ -297,11 +299,14 @@ extension SHRecordDetailsVC { ...@@ -297,11 +299,14 @@ extension SHRecordDetailsVC {
} }
} }
} }
if let _ = SHCloudManager.shared.icloudFolderModels.filter({ $0.id == self.currentModel.id }).first{
SHCloudManager.shared.modifyFolder(self.currentModel) { (result, models) in SHCloudManager.shared.modifyFolder(self.currentModel) { (result, models) in
if result { if result {
self.updateocloudUI() self.updateocloudUI()
} }
} }
}
if self.currentModel.dataSources.count == 0 { if self.currentModel.dataSources.count == 0 {
self.editClick(true) self.editClick(true)
...@@ -391,7 +396,7 @@ extension SHRecordDetailsVC: UITableViewDelegate, UITableViewDataSource{ ...@@ -391,7 +396,7 @@ extension SHRecordDetailsVC: UITableViewDelegate, UITableViewDataSource{
if model.icloud == false{ if model.icloud == false{
self.icloundUpload(indexPath.row) self.icloundUpload(indexPath.row)
}else{ }else{
self.icloundRemove(indexPath.row) self.icloudRemove(indexPath.row)
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment