Commit 11cd8da4 authored by zhangzhe's avatar zhangzhe

新增录音

parent dae5e19a
......@@ -138,6 +138,8 @@
CC29A709251C71AC0059BD5C /* SHSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC29A708251C71AC0059BD5C /* SHSwift.swift */; };
CC29A716251C75210059BD5C /* SHInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC29A715251C75210059BD5C /* SHInputView.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 */
/* Begin PBXContainerItemProxy section */
......@@ -338,6 +340,8 @@
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>"; };
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 */
/* Begin PBXFrameworksBuildPhase section */
......@@ -831,6 +835,8 @@
CC13DB73251C9A2F00835654 /* SHInputTextView.swift */,
CC29A71A251C790D0059BD5C /* SHInputBottomView.swift */,
CC13DB78251CA62800835654 /* SHInputAudioButton.swift */,
CCAD0B7C2521D5C600781276 /* SHInputProgressView.swift */,
CCAD0B772521C97F00781276 /* SHInputAudioPlayView.swift */,
);
path = View;
sourceTree = "<group>";
......@@ -1110,6 +1116,7 @@
A95CE00A24E0F42F0066DAE6 /* CRDateFormatter.swift in Sources */,
A95CDFC024E0EBF10066DAE6 /* Date+Extension.swift in Sources */,
A924A84B251B842C00CB2947 /* SHRecordDetailsBottomView.swift in Sources */,
CCAD0B782521C97F00781276 /* SHInputAudioPlayView.swift in Sources */,
A94EE118251B682C0066B490 /* SHSettingViewController.swift in Sources */,
A95CDFC424E0EBF10066DAE6 /* Double+Extension.swift in Sources */,
CC13DB6A251C83E600835654 /* SHInputViewModel.swift in Sources */,
......@@ -1136,6 +1143,7 @@
A950F5AF24F4E06E007AB63E /* SHMineViewController.swift in Sources */,
A95CE02F24E151340066DAE6 /* UIButton+Category.m in Sources */,
A94D935924F7969600A886C0 /* CMNetworkManager.swift in Sources */,
CCAD0B7D2521D5C600781276 /* SHInputProgressView.swift in Sources */,
A94DD56724FDF29700B1B5A2 /* XBAudioUnitPlayer.m in Sources */,
A94DD56F24FDF29700B1B5A2 /* XBAACEncoder_system.m in Sources */,
A95CE03624E1729B0066DAE6 /* SHRecordWaveView.swift in Sources */,
......@@ -1330,8 +1338,8 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "ShorthandMaster/速记大师.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 2;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 8F4PP38DC3;
......@@ -1350,7 +1358,7 @@
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.ShorthandMaster.www;
PRODUCT_NAME = "速记大师";
PROVISIONING_PROFILE_SPECIFIER = "";
PROVISIONING_PROFILE_SPECIFIER = ShorthandMasterDevProfile;
SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/ShorthandMaster/ShorthandMaster-Bridging-Header.h";
SWIFT_OBJC_INTERFACE_HEADER_NAME = "ShorthandMaster-Swift.h";
SWIFT_VERSION = 5.0;
......@@ -1364,8 +1372,8 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = "ShorthandMaster/速记大师.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 2;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 8F4PP38DC3;
......@@ -1384,7 +1392,7 @@
MARKETING_VERSION = 1.0.0;
PRODUCT_BUNDLE_IDENTIFIER = com.ShorthandMaster.www;
PRODUCT_NAME = "速记大师";
PROVISIONING_PROFILE_SPECIFIER = "";
PROVISIONING_PROFILE_SPECIFIER = ShorthandMasterDevProfile;
SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/ShorthandMaster/ShorthandMaster-Bridging-Header.h";
SWIFT_OBJC_INTERFACE_HEADER_NAME = "ShorthandMaster-Swift.h";
SWIFT_VERSION = 5.0;
......
{
"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
class SHInputController: SHBaseViewController
{
// MARK: - property
/// viewModel
var viewModel: SHInputViewModel = SHInputViewModel()
/// 文件夹model
var folderModel : SHRecordFolderModel!
......@@ -24,6 +27,16 @@ class SHInputController: SHBaseViewController
/// 未填写标题时的默认标题
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 let recorder_mp3: SHMp3RecordManager = SHMp3RecordManager.shared()
......@@ -45,12 +58,49 @@ class SHInputController: SHBaseViewController
self.addSubviews()
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
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.shDelegate = self;
self.view.addSubview(self.shInputView!)
......@@ -62,60 +112,26 @@ class SHInputController: SHBaseViewController
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.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
let attributeString : NSMutableAttributedString = NSMutableAttributedString()
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
// 显示记录
self.shInputView.textView.attributedText = self.viewModel.getAttributedStringWithSHRecordModel(recordModel: self.dataModel)
}
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
self.dataModel.createDate = 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.imagesIndex = imageArray.imagesIndexArray
......@@ -154,9 +170,15 @@ class SHInputController: SHBaseViewController
if self.dataModel.rename.length == 0
{
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
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"))
{
// 开始输入内容字体
textView.typingAttributes = SHInputViewModel.contentAttributes() as! [NSAttributedString.Key : Any]
textView.typingAttributes = self.viewModel.contentAttributes() as! [NSAttributedString.Key : Any]
}
else
{
......@@ -246,7 +268,7 @@ extension SHInputController: UITextViewDelegate, SHInputTextViewDelegate
else
{
// 使用内容字体
textView.typingAttributes = SHInputViewModel.contentAttributes() as! [NSAttributedString.Key : Any]
textView.typingAttributes = self.viewModel.contentAttributes() as! [NSAttributedString.Key : Any]
}
return true
......@@ -337,7 +359,7 @@ extension SHInputController: UIImagePickerControllerDelegate, UINavigationContro
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.placeholder.isHidden = true
......@@ -358,7 +380,7 @@ extension SHInputController: UIImagePickerControllerDelegate, UINavigationContro
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()
paragraphStyle.lineSpacing = 18
......@@ -368,9 +390,9 @@ extension SHInputController: UIImagePickerControllerDelegate, UINavigationContro
// 如果前文以换行符结尾, 图片前面不再加换行符
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)
......@@ -378,7 +400,7 @@ extension SHInputController: UIImagePickerControllerDelegate, UINavigationContro
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
......@@ -587,70 +609,210 @@ extension SHInputController
@objc func didSelectedAddAudioButton(sender : SHInputAudioButton)
{
self.shInputView.bottomView.addAudioButton.isHidden = true
self.shInputView.bottomView.audioTimeBgView.isHidden = false
self.shInputView.bottomView.pauseAudioButton.isHidden = false
self.shInputView.bottomView.goOnAudioButton.isHidden = true
self.shInputView.bottomView.stopAudioButton.isHidden = false
let mp3Path : String = DocumentPath + "/recorder.mp3"
let pcmPath : String = DocumentPath + "/xbMixData.caf"
self.shInputView.bottomView.stopAudioButton.isHidden = true
self.shInputView.bottomView.playView.isHidden = true
self.shInputView.bottomView.setUpSubviewsLocation()
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.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: 点击暂停录音按钮
@objc func didSelectedPauseAudioButton(sender : SHInputAudioButton)
{
self.shInputView.bottomView.addAudioButton.isHidden = true
self.shInputView.bottomView.audioTimeBgView.isHidden = false
self.shInputView.bottomView.pauseAudioButton.isHidden = true
self.shInputView.bottomView.goOnAudioButton.isHidden = false
self.shInputView.bottomView.stopAudioButton.isHidden = false
self.shInputView.bottomView.playView.isHidden = true
self.shInputView.bottomView.setUpSubviewsLocation()
recorder_mp3.pause()
let mp3Path : String = DocumentPath + "/recorder.mp3"
let pcmPath : String = DocumentPath + "/xbMixData.caf"
self.timer.suspend()
print("mp3Path" + mp3Path)
print("pcmPath" + pcmPath)
self.shInputView.bottomView.audioTimePointViewAnimation(animation: false)
}
// MARK: 点击继续录音按钮
@objc func didSelectedGoOnAudioButton(sender : SHInputAudioButton)
{
self.shInputView.bottomView.addAudioButton.isHidden = true
self.shInputView.bottomView.audioTimeBgView.isHidden = false
self.shInputView.bottomView.pauseAudioButton.isHidden = false
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()
let mp3Path : String = DocumentPath + "/recorder.mp3"
let pcmPath : String = DocumentPath + "/xbMixData.caf"
self.timer.resume()
print("mp3Path" + mp3Path)
print("pcmPath" + pcmPath)
self.shInputView.bottomView.audioTimePointViewAnimation(animation: true)
}
// MARK: 点击结束录制按钮
@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.goOnAudioButton.isHidden = true
self.shInputView.bottomView.stopAudioButton.isHidden = true
self.shInputView.bottomView.playView.isHidden = false
self.shInputView.bottomView.setUpSubviewsLocation()
recorder_mp3.stop()
let mp3Path : String = DocumentPath + "/recorder.mp3"
let pcmPath : String = DocumentPath + "/xbMixData.caf"
self.timer.cancel()
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
class SHInputBottomView: UIView {
// MARK: - property
/// 背景
var bgView : UIView!
/// 分割线
var line : UIView!
/// 选择图片按钮
var imageButton : UIButton!
......@@ -20,15 +21,16 @@ class SHInputBottomView: UIView {
/// 录音按钮背景
var audioBgView : UIView!
/// 添加录音按钮
var addAudioButton : SHInputAudioButton!
/// 录制时间背景
var audioTimeBgView : UIView!
/// 录制时间小红点
var audioTimePointView : UIView!
/// 录制时间
var audioTimeLabel : UIView!
var audioTimeLabel : UILabel!
/// 添加录音按钮
var addAudioButton : SHInputAudioButton!
/// 暂停录音按钮
var pauseAudioButton : SHInputAudioButton!
/// 继续录音按钮
......@@ -36,23 +38,43 @@ class SHInputBottomView: UIView {
/// 结束录音按钮
var stopAudioButton : SHInputAudioButton!
/// 录制结束播放控件
var playView: SHInputAudioPlayView!
/// 播放进度条
var progressView: SHInputProgressView!
/// 键盘按钮
var keyboardButton : UIButton!
/// 箭头图片
var directionImageView : UIImageView!
/// 计时器控制小红点闪烁
let timer = DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.global())
// MARK: - func
override init(frame: CGRect)
init(frame:CGRect, isEdited: Bool)
{
super.init(frame: frame)
self.backgroundColor = UIColor.white
self.layer.masksToBounds = true
self.addSubviews()
self.setUpSubviewsLocation()
if isEdited
{
self.setUpEditedSUbviewsLocation()
}
else
{
self.setUpSubviewsLocation()
}
}
required init?(coder: NSCoder)
......@@ -60,31 +82,25 @@ class SHInputBottomView: UIView {
fatalError("init(coder:) has not been implemented")
}
// MAKR: - UI
func addSubviews()
{
// 背景
self.bgView = UIView()
self.bgView.backgroundColor = UIColor(r: 249, g: 249, b: 249)
self.addSubview(self.bgView)
// 分割线
self.line = UIView()
self.line.backgroundColor = UIColor(r: 221, g: 221, b: 221)
self.addSubview(self.line)
// 选择图片按钮
self.imageButton = UIButton(type: UIButton.ButtonType.custom)
self.imageButton.setImage(UIImage(named: "input_image"), for: UIControl.State.normal)
self.bgView.addSubview(self.imageButton)
self.addSubview(self.imageButton)
// 录音按钮背景
self.audioBgView = UIView()
self.bgView.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.audioBgView.backgroundColor = UIColor.red
self.addSubview(self.audioBgView)
// 添加录音按钮
self.addAudioButton = SHInputAudioButton(type: UIButton.ButtonType.custom)
......@@ -95,6 +111,27 @@ class SHInputBottomView: UIView {
self.addAudioButton.rightLabel.textColor = UIColor(r: 244, g: 65, b: 65)
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.layer.cornerRadius = 15
......@@ -120,91 +157,203 @@ class SHInputBottomView: UIView {
self.stopAudioButton.layer.cornerRadius = 15
self.stopAudioButton.backgroundColor = UIColor(r: 250, g: 219, b: 219)
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.audioBgView.addSubview(self.stopAudioButton)
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.setImage(UIImage(named: "input_keyboard"), for: UIControl.State.normal)
self.bgView.addSubview(self.keyboardButton)
self.addSubview(self.keyboardButton)
// 箭头图片
self.directionImageView = UIImageView()
self.directionImageView.image = UIImage(named: "input_down")
self.bgView.addSubview(self.directionImageView)
self.addSubview(self.directionImageView)
}
// MARK: - 控件位置
// MARK: 编辑时的控件位置
func setUpEditedSUbviewsLocation()
{
}
// MARK: 控件位置
// MARK: 新增时的控件位置
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?.bottom.mas_equalTo()(-SafeAreaBottomHeight())
make?.height.mas_equalTo()(1)
}
self.imageButton.mas_makeConstraints { (make) in
make?.top.bottom()?.mas_equalTo()(0)
make?.left.mas_equalTo()(39 - 11)
make?.width.height()?.mas_equalTo()(self.bgView.mas_height)
make?.bottom.mas_equalTo()(-SafeAreaBottomHeight())
make?.left.mas_equalTo()(10)
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?.size.mas_equalTo()(CGSize(width: 72 + 18 + 100, height: 50))
make?.centerX.equalTo()(self)
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?.size.mas_equalTo()(CGSize(width: 100, height: 30))
}
}
if self.audioTimeBgView.isHidden == false
{
self.audioTimeBgView.mas_remakeConstraints { (make) in
make?.left.equalTo()(self.audioBgView)
make?.centerY.equalTo()(self.audioBgView)
make?.size.mas_equalTo()(CGSize(width: 81, height: 30))
}
make?.center.equalTo()(self.audioBgView)
make?.size.mas_equalTo()(CGSize(width: 100, 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)
}
}
self.pauseAudioButton.mas_makeConstraints { (make) in
make?.left.mas_equalTo()(0)
make?.centerY.equalTo()(self.audioBgView)
make?.size.mas_equalTo()(CGSize(width: 72, height: 30))
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?.size.mas_equalTo()(CGSize(width: 72, height: 30))
}
}
if self.goOnAudioButton.isHidden == false
{
self.goOnAudioButton.mas_remakeConstraints { (make) in
make?.left.equalTo()(self.audioTimeBgView.mas_right)?.offset()(8)
make?.centerY.equalTo()(self.audioBgView)
make?.size.mas_equalTo()(CGSize(width: 72, height: 30))
}
}
if self.stopAudioButton.isHidden == false
{
self.stopAudioButton.mas_remakeConstraints { (make) in
make?.right.mas_equalTo()(0)
make?.left.equalTo()(self.goOnAudioButton.mas_right)?.offset()(8)
make?.centerY.equalTo()(self.audioBgView)
make?.size.mas_equalTo()(CGSize(width: 72, height: 30))
}
}
self.goOnAudioButton.mas_makeConstraints { (make) in
self.playView.mas_makeConstraints { (make) in
make?.top.left()?.bottom()?.right()?.equalTo()(self.pauseAudioButton)
make?.centerX.equalTo()(self)
make?.bottom.mas_equalTo()(-SafeAreaBottomHeight() - 10)
make?.size.mas_equalTo()(CGSize(width: 160, height: 30))
}
self.stopAudioButton.mas_makeConstraints { (make) in
self.progressView.mas_makeConstraints { (make) in
make?.left.equalTo()(self.pauseAudioButton.mas_right)?.offset()(18)
make?.right.mas_equalTo()(0)
make?.centerY.equalTo()(self.audioBgView)
make?.size.mas_equalTo()(CGSize(width: 100, height: 30))
make?.top.left()?.right()?.mas_equalTo()(self)
make?.height.mas_equalTo()(50)
}
self.keyboardButton.mas_makeConstraints { (make) in
make?.top.bottom()?.mas_equalTo()(0)
make?.right.mas_equalTo()(11 - 40)
make?.bottom.mas_equalTo()(-SafeAreaBottomHeight())
make?.right.mas_equalTo()(10 - 40)
make?.size.equalTo()(self.imageButton)
}
self.directionImageView.mas_makeConstraints { (make) in
make?.centerY.equalTo()(self.bgView)
make?.bottom.mas_equalTo()(-SafeAreaBottomHeight() - 16)
make?.width.height()?.mas_equalTo()(16)
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 {
{
delegateOK.textViewDidDelete?(textView: self)
}
}
}
extension SHInputTextView: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
}
}
......@@ -16,11 +16,16 @@ class SHInputView: UIView {
var bottomView : SHInputBottomView!
var isEdited: Bool = Bool()
// MARK: - func
override init(frame: CGRect)
init(frame: CGRect, isEdited: Bool)
{
super.init(frame: frame)
self.isEdited = isEdited
self.addSubviews()
self.setUpSubviewsLocation()
......@@ -32,6 +37,8 @@ class SHInputView: UIView {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(note:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
......@@ -45,6 +52,7 @@ class SHInputView: UIView {
self.textView.textColor = UIColor.init(r: 34, g: 34, b: 34, a: 1)
self.textView.font = UIFont.init(name: SHPingFangMedium, size: 18)
self.textView.contentInset = UIEdgeInsets.init(top: 24, left: 0, bottom: 0, right: 0);
self.textView.alwaysBounceVertical = true
self.addSubview(self.textView)
// 占位文字
......@@ -55,7 +63,7 @@ class SHInputView: UIView {
self.textView.addSubview(self.placeholder)
// 底部栏
self.bottomView = SHInputBottomView.init()
self.bottomView = SHInputBottomView.init(frame: .zero, isEdited: isEdited)
self.addSubview(self.bottomView)
}
......@@ -107,9 +115,7 @@ class SHInputView: UIView {
weakSelf?.bottomView.mas_updateConstraints { (make) in
make?.left.right()?.mas_equalTo()(0)
make?.bottom.mas_equalTo()(-height + SafeAreaBottomHeight())
make?.height.mas_equalTo()(50 + SafeAreaBottomHeight());
}
......@@ -131,8 +137,7 @@ class SHInputView: UIView {
weakSelf?.bottomView.mas_updateConstraints { (make) in
make?.left.right().bottom()?.mas_equalTo()(0)
make?.height.mas_equalTo()(50 + SafeAreaBottomHeight());
make?.bottom.mas_equalTo()(0)
}
......
......@@ -11,22 +11,11 @@ import UIKit
class SHInputViewModel: NSObject {
// MARK: - property
// /// 标题文字
// var title : String = ""
// /// 内容文字
// var content : String = ""
// /// 图片数组
// var imageArray : Array = Array<Any>()
// var recordModel : SHRecordModel = SHRecordModel()
// MARK: - func
// MARK: 标题文字样式
class func titleAttributes() -> NSDictionary
func titleAttributes() -> NSDictionary
{
let paragraphStyle : NSMutableParagraphStyle = NSMutableParagraphStyle.init()
paragraphStyle.lineSpacing = 5;
......@@ -40,7 +29,7 @@ class SHInputViewModel: NSObject {
}
// MARK: 内容文字样式
class func contentAttributes() -> NSDictionary
func contentAttributes() -> NSDictionary
{
let paragraphStyle : NSMutableParagraphStyle = NSMutableParagraphStyle.init()
paragraphStyle.lineSpacing = 5;
......@@ -52,30 +41,54 @@ class SHInputViewModel: NSObject {
return titleAttributes
}
// MARK: 沙盒文件夹路径, 生成沙盒文件, 图片和录音都保存在这个路径下
lazy var documentFilePath : String = {
let dateFormat = Date().format("yyyyMMdd")
let time = Date.init().timeStamp
let filePath = "/" + dateFormat + time
if !FileManager.default.fileExists(atPath: DocumentPath + filePath)
{
do
{
try FileManager.default.createDirectory(atPath: DocumentPath + filePath, withIntermediateDirectories: true, attributes: nil)
}
catch let error
{
print(error)
}
}
return filePath
}()
// MARK: 获取textView中的图片, 保存到本地, 并生成数组
class func setUpImageArrayWithTextView(textView: UITextView) -> (imagesPathArray: Array<String>, imagesIndexArray: Array<Int>)
func setUpImageArrayWithTextView(textView: UITextView) -> (imagesPathArray: Array<String>, imagesIndexArray: Array<Int>)
{
/// 图片路径数组
var imagesPathArray = Array<String>()
/// 图片位置数组
var imagesIndexArray = Array<Int>()
// 创建文件夹
/// 文件夹路径
let subFile = Date().format("yyyyMMdd")
let time = Date.init().timeStamp
let filePath = DocumentPath + "/" + subFile + time
do
{
try FileManager.default.createDirectory(atPath: filePath, withIntermediateDirectories: true, attributes: nil)
}
catch let error
{
print(error)
return (imagesPathArray, imagesIndexArray)
}
// // 创建文件夹
// /// 文件夹路径
// 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
......@@ -96,7 +109,7 @@ class SHInputViewModel: NSObject {
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)
......@@ -128,4 +141,62 @@ class SHInputViewModel: NSObject {
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)
}
}
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