Browse Source

Merge branch 'dev' of https://git.yishihui.com/iOS/BFRecordScreenKit into dev

* 'dev' of https://git.yishihui.com/iOS/BFRecordScreenKit:
  发音人的状态控制逻辑
  只是格式化
  发音人状态逻辑
  发音人状态 UI
  添加发音人试听逻辑
  发音人 UI使用的资源
胡志强 3 years ago
parent
commit
5deadd4d75
30 changed files with 430 additions and 221 deletions
  1. 2 3
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/audioLoding.imageset/Contents.json
  2. BIN
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/audioLoding.imageset/audioLoding@2x.png
  3. BIN
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/audioLoding.imageset/audioLoding@3x.png
  4. 23 0
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/markPlaying.imageset/Contents.json
  5. BIN
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/markPlaying.imageset/markPlaying.png
  6. BIN
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/markPlaying.imageset/markPlaying@2x.png
  7. BIN
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/markPlaying.imageset/markPlaying@3x.png
  8. 22 0
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/markSeleced.imageset/Contents.json
  9. BIN
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/markSeleced.imageset/markSeleced.png
  10. BIN
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/markSeleced.imageset/markSeleced@3x.png
  11. 22 0
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/stuckPoint_music_pause.imageset/Contents.json
  12. BIN
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/stuckPoint_music_pause.imageset/stuckPoint_music_pause@2x.png
  13. BIN
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/stuckPoint_music_pause.imageset/stuckPoint_music_pause@3x.png
  14. 12 0
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/stuckPoint_music_playing.dataset/Contents.json
  15. BIN
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/stuckPoint_music_playing.dataset/stuckPoint_music_playing.gif
  16. 23 0
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDeleteN.imageset/Contents.json
  17. 0 0
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDeleteN.imageset/voiceDeleteN.png
  18. 0 0
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDeleteN.imageset/voiceDeleteN@2x.png
  19. 0 0
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDeleteN.imageset/voiceDeleteN@3x.png
  20. 23 0
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDeleteS.imageset/Contents.json
  21. BIN
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDeleteS.imageset/voiceDeleteS.png
  22. BIN
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDeleteS.imageset/voiceDeleteS@2x.png
  23. BIN
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDeleteS.imageset/voiceDeleteS@3x.png
  24. 21 0
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/xmarkSeleced.imageset/Contents.json
  25. BIN
      BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/xmarkSeleced.imageset/xmarkSeleced@2x.png
  26. BIN
      BFRecordScreenKit/Assets/stuckPoint_music_playing.gif
  27. 84 14
      BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenController.swift
  28. 111 80
      BFRecordScreenKit/Classes/RecordScreen/View/BFVoiceSettingView.swift
  29. 76 108
      BFRecordScreenKit/Classes/RecordScreen/View/Cell/PQVoiceCell.swift
  30. 11 16
      BFRecordScreenKit/Classes/RecordScreen/ViewModel/BFRecordScreenViewModel.swift

+ 2 - 3
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDelete.imageset/Contents.json → BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/audioLoding.imageset/Contents.json

@@ -1,17 +1,16 @@
 {
   "images" : [
     {
-      "filename" : "voiceDelete.png",
       "idiom" : "universal",
       "scale" : "1x"
     },
     {
-      "filename" : "voiceDelete@2x.png",
+      "filename" : "audioLoding@2x.png",
       "idiom" : "universal",
       "scale" : "2x"
     },
     {
-      "filename" : "voiceDelete@3x.png",
+      "filename" : "audioLoding@3x.png",
       "idiom" : "universal",
       "scale" : "3x"
     }

BIN
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/audioLoding.imageset/audioLoding@2x.png


BIN
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/audioLoding.imageset/audioLoding@3x.png


+ 23 - 0
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/markPlaying.imageset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "markPlaying.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "markPlaying@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "markPlaying@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/markPlaying.imageset/markPlaying.png


BIN
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/markPlaying.imageset/markPlaying@2x.png


BIN
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/markPlaying.imageset/markPlaying@3x.png


+ 22 - 0
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/markSeleced.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "filename" : "markSeleced.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "markSeleced@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/markSeleced.imageset/markSeleced.png


BIN
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/markSeleced.imageset/markSeleced@3x.png


+ 22 - 0
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/stuckPoint_music_pause.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "stuckPoint_music_pause@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "stuckPoint_music_pause@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/stuckPoint_music_pause.imageset/stuckPoint_music_pause@2x.png


BIN
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/stuckPoint_music_pause.imageset/stuckPoint_music_pause@3x.png


+ 12 - 0
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/stuckPoint_music_playing.dataset/Contents.json

@@ -0,0 +1,12 @@
+{
+  "data" : [
+    {
+      "filename" : "stuckPoint_music_playing.gif",
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/stuckPoint_music_playing.dataset/stuckPoint_music_playing.gif


+ 23 - 0
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDeleteN.imageset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "voiceDeleteN.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "voiceDeleteN@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "voiceDeleteN@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 0 - 0
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDelete.imageset/voiceDelete.png → BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDeleteN.imageset/voiceDeleteN.png


+ 0 - 0
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDelete.imageset/voiceDelete@2x.png → BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDeleteN.imageset/voiceDeleteN@2x.png


+ 0 - 0
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDelete.imageset/voiceDelete@3x.png → BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDeleteN.imageset/voiceDeleteN@3x.png


+ 23 - 0
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDeleteS.imageset/Contents.json

@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "voiceDeleteS.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "voiceDeleteS@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "voiceDeleteS@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDeleteS.imageset/voiceDeleteS.png


BIN
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDeleteS.imageset/voiceDeleteS@2x.png


BIN
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/voiceDeleteS.imageset/voiceDeleteS@3x.png


+ 21 - 0
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/xmarkSeleced.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "xmarkSeleced@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
BFRecordScreenKit/Assets/BFRecordScreenKit.xcassets/xmarkSeleced.imageset/xmarkSeleced@2x.png


BIN
BFRecordScreenKit/Assets/stuckPoint_music_playing.gif


+ 84 - 14
BFRecordScreenKit/Classes/RecordScreen/Controller/BFRecordScreenController.swift

@@ -484,6 +484,17 @@ public class BFRecordScreenController: BFBaseViewController {
         voiceSettingView.isHidden = true
         return voiceSettingView
     }()
+    //显示选中发音人的头像
+    lazy var voiceIconView: UIImageView = {
+        let voiceIconView = UIImageView()
+        voiceIconView.addCorner(corner: 25 / 2)
+        return voiceIconView
+    }()
+    //tts 服务
+    var tts:BFTTSManager?
+    //当前选择的发音人
+    var mSelectVoiced:PQVoiceModel?
+    
  
     // 编辑字幕
     lazy var subtitleEditView: BFSubtitleEditView = {
@@ -684,6 +695,9 @@ public class BFRecordScreenController: BFBaseViewController {
             BFLog(message: "nls appkey is \(appkey), token is \(token)")
             wself.NeoNuiAPPID = appkey
             wself.NeoNuiToken = token
+            
+            wself.tts = BFTTSManager.init(nui: token, appid: appkey)
+            wself.tts?.delegate = wself
         }
         
         initlizeRecordManager()
@@ -701,6 +715,7 @@ public class BFRecordScreenController: BFBaseViewController {
         view.addSubview(soundSettingBtn)
         if(BFLocalizedUtil.currentLanguage() == "zh"){
             view.addSubview(voiceSettingBtn)
+            voiceSettingBtn.addSubview(voiceIconView)
         }
    
         view.addSubview(cameraFlipBtn)
@@ -782,17 +797,64 @@ public class BFRecordScreenController: BFBaseViewController {
             view.addSubview(audioQueueRecoderLabel)
         }
         
-        
+        // add by ak 发音人相关操作
+        BFRecordScreenViewModel.getAllVoiceCates { [weak self] categorys, voices in
+            guard let wself = self else { return }
+            wself.voiceSettingView.categorys = categorys
+            wself.voiceSettingView.voices = voices
+         
+        }
         voiceSettingView.voiceSettingCallBack = {[weak self] actionType ,selectVoice in
             guard let wself = self else { return }
-            if actionType == .VoiceSettingActionConfirm{
-                BFLog(2, message: "确认发音人操作")
-                
+          
+            if actionType == .VoiceSettingActionConfirm{//要生成真实音频文件
+                BFLog(2, message: "确认选择发音人操作")
+                wself.mSelectVoiced = selectVoice
+                wself.voiceSettingView.flushSelectVoiceStatus(voiceStatue: .isSelected)
+                if(wself.mSelectVoiced != nil){
+                    wself.tts?.startTTS("", taskId: "", isAudition: false,fontName: selectVoice?.voice ?? "")
+                    wself.voiceIconView.setNetImage(url: "\(wself.mSelectVoiced?.avatarUrl ?? "")")
+                    
+                }else{
+                    wself.voiceIconView.image = nil
+                }
             }else if actionType == .voiceSettingActionCancel{
                 BFLog(2, message: "取消发音人操作")
-                
+                wself.tts?.stopTTS("")
+                wself.voiceSettingView.flushSelectVoiceStatus(voiceStatue: .isSelected)
+        
             }else if actionType == .voiceSettingActionDelete{
                 BFLog(2, message: "删除发音人操作")
+                //停止文字转换
+                wself.tts?.stopTTS("")
+            }else if actionType == .VoiceSettingActionSelected{//要进行试听或暂停操作
+                BFLog(2, message: "选择了一个发音人操作")
+                if(wself.mSelectVoiced == nil){
+                    //首次选直接转
+                    wself.tts?.startTTS("", taskId: "", isAudition: true,fontName: selectVoice?.voice ?? "")
+                    wself.voiceSettingView.flushSelectVoiceStatus(voiceStatue: .isLoading)
+                }else{
+                    
+         
+                    if(wself.mSelectVoiced == selectVoice){  //是同一个发音人暂停
+
+                        BFLog(message: "试听播放器状态\(String(describing: wself.tts?.voicePlayer.state.rawValue) )")
+                     
+                        if (wself.tts?.voicePlayer.state == PlayerState.playing){
+                            wself.tts?.stopTTS("")
+                            wself.voiceSettingView.flushSelectVoiceStatus(voiceStatue: .isPause)
+                        }else{
+                            wself.tts?.startTTS("", taskId: "", isAudition: true,fontName: selectVoice?.voice ?? "")
+                            wself.voiceSettingView.flushSelectVoiceStatus(voiceStatue: .isLoading)
+                        }
+
+                    } else{//开始试听
+                        wself.tts?.startTTS("", taskId: "", isAudition: true,fontName: selectVoice?.voice ?? "")
+                        wself.voiceSettingView.flushSelectVoiceStatus(voiceStatue: .isLoading)
+                    }
+                }
+
+                wself.mSelectVoiced = selectVoice
             }
             
         }
@@ -865,6 +927,11 @@ public class BFRecordScreenController: BFBaseViewController {
                 make.right.width.height.equalTo(subtitleBtn)
                 make.top.equalTo(subtitleBtn.snp.bottom).offset(18)
             }
+            voiceIconView.snp.makeConstraints { make in
+                make.width.height.equalTo(26)
+                make.centerX.equalTo(voiceSettingBtn)
+                make.top.equalTo(voiceSettingBtn).offset(8)
+            }
         }
         
         cameraFlipBtn.snp.makeConstraints { make in
@@ -1269,15 +1336,6 @@ public class BFRecordScreenController: BFBaseViewController {
         BFLog(message: "设置变音")
 
         voiceSettingView.isHidden = false
-        
-    
-        BFRecordScreenViewModel.getAllVoiceCates { [weak self] categorys, voices in
-            guard let wself = self else { return }
-            wself.voiceSettingView.categorys = categorys
-            wself.voiceSettingView.voices = voices
-         
-        }
-        
       
     }
     
@@ -2617,3 +2675,15 @@ public extension BFRecordScreenController {
         indirectionView?.resetAllSubViews(items: itemModels[currItemModelIndex].voiceStickers, percenWidth: percenWidth, totalDuration: itemModels[currItemModelIndex].materialDuraion.seconds)
     }
 }
+
+// MARK: - TTS 试听回调
+extension BFRecordScreenController: BFTTSManagerDelegte{
+    public func playerDidStart() {
+        BFLog(message: "试听开始播放")
+        voiceSettingView.flushSelectVoiceStatus(voiceStatue: .isPlaying)
+    }
+    public func playerDidFinish() {
+        BFLog(message: "试听播放完成")
+        voiceSettingView.flushSelectVoiceStatus(voiceStatue: .isSelected)
+    }
+}

+ 111 - 80
BFRecordScreenKit/Classes/RecordScreen/View/BFVoiceSettingView.swift

@@ -5,53 +5,51 @@
 //  Created by ak on 2022/2/15.
 //  功能:发音人设置面板
 
-import Foundation
 import BFCommonKit
-import BFUIKit
 import BFMediaKit
+import BFUIKit
+import Foundation
 import UIKit
 
-
 // 操作动作类型
 public enum VoiceSettingActionType: Int {
     case voiceSettingActionCancel = 1 // 取消
     case voiceSettingActionDelete = 2 // 删除
     case VoiceSettingActionConfirm = 3 // 确认
+    case VoiceSettingActionSelected = 4 // 选择了一个发音人 如用于试听
 }
 
 class BFVoiceSettingView: UIView {
-    
     let itemSize = CGSize(width: adapterWidth(width: 52) + 9, height: 40)
-    
-    //操作板背景
+
+    // 操作板背景
     let backView = UIButton()
-    
-    //保存所有发音人
-    public var voices: Dictionary = Dictionary<String, [PQVoiceModel]>.init(){
+
+    // 保存所有发音人
+    public var voices: Dictionary = Dictionary<String, [PQVoiceModel]>.init() {
         didSet {
             voicesCollectView.reloadData()
-            
         }
     }
-    //所有分类
-    public var categorys: Array = Array<BFVoiceCategoryModel>.init(){
+
+    // 所有分类
+    public var categorys: Array = Array<BFVoiceCategoryModel>.init() {
         didSet {
             BFLog(message: "发音人分类数: \(categorys.count)")
             curretnCategory = categorys.first
+            curretnCategory?.isSelected = true
             catagaryCollectView.reloadData()
-        
         }
     }
-    
-    //操作回调
-    public var voiceSettingCallBack: ((_ actionType: VoiceSettingActionType,_ selectVoice:PQVoiceModel?) -> Void)?
 
-    //当前选择的分类
-    var curretnCategory:BFVoiceCategoryModel?
-    //当前选择的发音人
-    var selectVoice:PQVoiceModel?
+    // 操作回调
+    public var voiceSettingCallBack: ((_ actionType: VoiceSettingActionType, _ selectVoice: PQVoiceModel?) -> Void)?
+
+    // 当前选择的分类
+    var curretnCategory: BFVoiceCategoryModel?
+    // 当前选择的发音人
+    public var selectVoice: PQVoiceModel?
 
-    
     // 分类列表
     lazy var catagaryCollectView: UICollectionView = {
         let layout = UICollectionViewFlowLayout()
@@ -78,18 +76,32 @@ class BFVoiceSettingView: UIView {
 
         return collectView
     }()
-    
+
+    // 删除 btn
+    lazy var deleteBtn: UIButton = {
+        let deleteBtn = UIButton()
+        deleteBtn.backgroundColor = .clear
+        deleteBtn.setTitleColor(.white, for: .normal)
+        deleteBtn.titleLabel?.font = UIFont.systemFont(ofSize: 16)
+        deleteBtn.addTarget(self, action: #selector(deleteBtnAction), for: .touchUpInside)
+
+        deleteBtn.setBackgroundImage(imageInRecordScreenKit(by: "voiceDeleteN"), for: .normal)
+        deleteBtn.setBackgroundImage(imageInRecordScreenKit(by: "voiceDeleteS"), for: .selected)
+        deleteBtn.adjustsImageWhenHighlighted = false
+        return deleteBtn
+    }()
+
     // 所有发音人列表
     lazy var voicesCollectView: UICollectionView = {
         let layout = UICollectionViewFlowLayout()
         layout.scrollDirection = .vertical
-        layout.itemSize = CGSize(width: adapterWidth(width:60) , height: 78)
-        //每行最小边距
+        layout.itemSize = CGSize(width: adapterWidth(width: 60), height: 78)
+        // 每行最小边距
         layout.minimumLineSpacing = 10
-        //每列最小边距
+        // 每列最小边距
         layout.minimumInteritemSpacing = 0
         layout.sectionInset = UIEdgeInsets.zero
-     
+
         let collectView = UICollectionView(frame: CGRect(x: 0, y: 98, width: cScreenWidth, height: 242 - cSafeAreaHeight), collectionViewLayout: layout)
         collectView.isPagingEnabled = false
         collectView.showsHorizontalScrollIndicator = false
@@ -107,24 +119,20 @@ class BFVoiceSettingView: UIView {
 
         return collectView
     }()
-    
+
     required init?(coder _: NSCoder) {
         fatalError("init(coder:) has not been implemented")
     }
-    
+
     override func layoutSubviews() {
         super.layoutSubviews()
-        self.backView.addCorner(roundingCorners: [.topLeft, .topRight], corner: 10)
+        backView.addCorner(roundingCorners: [.topLeft, .topRight], corner: 10)
     }
-    
+
     override init(frame: CGRect) {
         super.init(frame: frame)
 
-        backgroundColor = UIColor.clear
-        let view = UIView.init(frame: frame)
-        view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(hidden)))
-        addSubview(view)
-
+        backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5)
         backView.backgroundColor = UIColor.hexColor(hexadecimal: "#121212")
 
         addSubview(backView)
@@ -135,8 +143,8 @@ class BFVoiceSettingView: UIView {
             make.height.equalTo(340)
         }
         backView.setNeedsUpdateConstraints()
-        
-        //取消
+
+        // 取消
         let cancelBtn = UIButton()
         cancelBtn.backgroundColor = .clear
         cancelBtn.setTitle("取消", for: .normal)
@@ -144,15 +152,15 @@ class BFVoiceSettingView: UIView {
         cancelBtn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 17)
         cancelBtn.addTarget(self, action: #selector(cancelAction), for: .touchUpInside)
         backView.addSubview(cancelBtn)
-        
+
         cancelBtn.snp.makeConstraints { make in
             make.left.equalToSuperview().offset(18)
             make.width.equalTo(35)
             make.height.equalTo(24)
             make.top.equalToSuperview().offset(18)
         }
-        
-        //确认
+
+        // 确认
         let okBtn = UIButton()
         okBtn.backgroundColor = .clear
         okBtn.setTitle("确认", for: .normal)
@@ -166,9 +174,9 @@ class BFVoiceSettingView: UIView {
             make.height.equalTo(24)
             make.top.equalToSuperview().offset(18)
         }
-        
-        //删除发音设置
-        let catagaryBackView = UIView.init()
+
+        // 删除发音设置
+        let catagaryBackView = UIView()
         catagaryBackView.backgroundColor = UIColor.hexColor(hexadecimal: "#0B0B0B")
         backView.addSubview(catagaryBackView)
         catagaryBackView.snp.makeConstraints { make in
@@ -177,66 +185,85 @@ class BFVoiceSettingView: UIView {
             make.height.equalTo(40)
             make.top.equalToSuperview().offset(58)
         }
-        
+
         catagaryBackView.addSubview(catagaryCollectView)
-        
-        let deleteBtn = UIButton()
-        deleteBtn.backgroundColor = .clear
-        deleteBtn.setTitleColor(.white, for: .normal)
-        deleteBtn.titleLabel?.font = UIFont.systemFont(ofSize: 16)
-        deleteBtn.addTarget(self, action: #selector(deleteBtnAction), for: .touchUpInside)
+
         catagaryBackView.addSubview(deleteBtn)
-        deleteBtn.setBackgroundImage(imageInRecordScreenKit(by: "voiceDelete"), for: .normal)
         deleteBtn.snp.makeConstraints { make in
             make.left.equalToSuperview().offset(16)
             make.width.equalTo(24)
             make.height.equalTo(24)
             make.top.equalTo(cancelBtn.bottomY).offset(8)
         }
-  
+
         backView.addSubview(voicesCollectView)
-    
     }
     
+    func show(){
+        isHidden = false
+
+    }
+
     @objc func hidden() {
         isHidden = true
     }
-    
-    @objc func cancelAction(){
-        if(voiceSettingCallBack != nil){
-            voiceSettingCallBack!(.voiceSettingActionCancel,selectVoice)
+
+    @objc func cancelAction() {
+        hidden()
+        if voiceSettingCallBack != nil {
+            voiceSettingCallBack!(.voiceSettingActionCancel, selectVoice)
         }
     }
     
-    @objc func okBtnAction(){
-        
-        if(voiceSettingCallBack != nil){
-            voiceSettingCallBack!(.VoiceSettingActionConfirm,selectVoice)
+
+    @objc func okBtnAction() {
+        hidden()
+        if voiceSettingCallBack != nil {
+            voiceSettingCallBack!(.VoiceSettingActionConfirm, selectVoice)
         }
-        
     }
-    @objc func deleteBtnAction(){
-        if(voiceSettingCallBack != nil){
-            voiceSettingCallBack!(.voiceSettingActionDelete,selectVoice)
+
+    @objc func deleteBtnAction() {
+        // 说明已经选择过发音人
+        if selectVoice != nil {
+            // 删除选择的发音人
+            if deleteBtn.isSelected {
+                selectVoice?.voiceStatue = .isNormal
+                selectVoice = nil
+                voicesCollectView.reloadData()
+            }
+            deleteBtn.isSelected = !deleteBtn.isSelected
+
+        } else {
+            cShowHUB(superView: nil, msg: "还没有选择发音人")
+        }
+
+        if voiceSettingCallBack != nil {
+            voiceSettingCallBack!(.voiceSettingActionDelete, selectVoice)
         }
     }
+    
+    
+    /// 刷新当前选择发音人显示状态(业务使用方调用)
+    /// - Parameter voiceStatue: 状态值
+    public func flushSelectVoiceStatus(voiceStatue: voiceStatue){
+        selectVoice?.voiceStatue = voiceStatue
+        voicesCollectView.reloadData()
+        
+    }
 }
 
 extension BFVoiceSettingView: UICollectionViewDelegate, UICollectionViewDataSource, UIScrollViewDelegate, UICollectionViewDelegateFlowLayout {
     func collectionView(_ collectionView: UICollectionView,
                         layout _: UICollectionViewLayout,
-                        sizeForItemAt indexPath: IndexPath) -> CGSize
-    {
-      
-        if(collectionView == catagaryCollectView){
+                        sizeForItemAt indexPath: IndexPath) -> CGSize {
+        if collectionView == catagaryCollectView {
             return CGSize(width: adapterWidth(width: 52) + 9, height: 40)
         }
-        return CGSize(width: adapterWidth(width:60) , height: 78)
-        
+        return CGSize(width: adapterWidth(width: 60), height: 78)
     }
 
     func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection _: Int) -> Int {
-   
         if collectionView == catagaryCollectView {
             return categorys.count
         }
@@ -244,15 +271,13 @@ extension BFVoiceSettingView: UICollectionViewDelegate, UICollectionViewDataSour
     }
 
     func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
- 
         if collectionView == catagaryCollectView {
-
             let cell = BFVoiceCategoryCell.setCategory(collectionView: collectionView, indexPath: indexPath)
- 
+
             cell.category = categorys[indexPath.item]
             return cell
         }
-        
+
         let cell = PQVoiceCell.voiceList(collectionView: collectionView, indexPath: indexPath)
         let model = voices[curretnCategory?.cateName ?? ""]?[indexPath.item]
 
@@ -261,18 +286,24 @@ extension BFVoiceSettingView: UICollectionViewDelegate, UICollectionViewDataSour
     }
 
     func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-     
         if collectionView == catagaryCollectView {
             BFLog(message: "===开始点击\(curretnCategory?.cateName ?? "")")
             curretnCategory?.isSelected = false
             curretnCategory = categorys[indexPath.item]
             curretnCategory?.isSelected = true
             catagaryCollectView.reloadData()
-          
+
             voicesCollectView.reloadData()
-        }else{
+        } else {
+            selectVoice?.voiceStatue = .isNormal
             selectVoice = voices[curretnCategory?.cateName ?? ""]?[indexPath.item]
+            selectVoice?.voiceStatue = .isSelected
+            deleteBtn.isSelected = true
+            voicesCollectView.reloadData()
+
+            if voiceSettingCallBack != nil {
+                voiceSettingCallBack!(.VoiceSettingActionSelected, selectVoice)
+            }
         }
-   
     }
 }

+ 76 - 108
BFRecordScreenKit/Classes/RecordScreen/View/Cell/PQVoiceCell.swift

@@ -1,4 +1,7 @@
 //
+import BFCommonKit
+import BFMediaKit
+import BFUIKit
 //  PQVoiceCell.swift
 //  PQSpeed
 //
@@ -6,81 +9,56 @@
 //  Copyright © 2020 BytesFlow. All rights reserved.
 //
 import Foundation
-import BFMediaKit
-import BFUIKit
-import BFCommonKit
+import UIKit
 
 class PQVoiceCell: UICollectionViewCell {
-    lazy var background: UIView = {
-        let background = UIView()
-        background.backgroundColor = UIColor.clear
-        return background
-    }()
-
-    //头像
+ 
+    // 头像
     lazy var coverView: UIImageView = {
         let coverView = UIImageView()
         coverView.backgroundColor = UIColor.clear
-        coverView.addCorner(corner: 30)
+        coverView.addCorner(corner: 25)
+
         return coverView
     }()
 
- 
     lazy var nameLab: UILabel = {
         let nameLab = UILabel()
-        nameLab.textColor = UIColor.hexColor(hexadecimal: "#E4E4E4")
-        nameLab.addCorner(corner: 3)
-        nameLab.font = UIFont.systemFont(ofSize: 11)
+        nameLab.font = UIFont.systemFont(ofSize: 15)
         nameLab.textAlignment = .center
         return nameLab
     }()
- 
-    lazy var markView: UIView = {
-        let markView = UIView(frame: self.frame)
-        markView.backgroundColor = UIColor.black
-        markView.alpha = 0.7
+
+    lazy var markView: UIImageView = {
+        let markView = UIImageView()
         markView.isHidden = true
         return markView
     }()
 
-    // 语音加载动画
+    // 语音加载动画
     lazy var audioLoding: UIImageView = {
         let audioLoding = UIImageView(frame: self.frame)
-
-        audioLoding.image = UIImage(named: "audioLoding")
+        audioLoding.image = imageInRecordScreenKit(by: "audioLoding")?.withRenderingMode(.alwaysTemplate)
         audioLoding.isHidden = true
-
+        audioLoding.tintColor = .white
         return audioLoding
     }()
 
-    // 语音播放动画
+    // 语音播放动画和暂停播放
     lazy var audioPlaying: UIImageView = {
-        let audioPlaying = UIImageView()
-
-        var images = [UIImage]()
-//        for i in 0...44 {
-//            images.append(UIImage(named: "\(i).png")!)
-//        }
-
-        audioPlaying.animationImages = images
-        audioPlaying.animationDuration = 2
-        audioPlaying.animationRepeatCount = 0
-
-        audioPlaying.isHidden = true
-
-        return audioPlaying
+        let playImageView = UIImageView()
+        playImageView.image = imageInRecordScreenKit(by: "stuckPoint_music_pause")
+        playImageView.contentMode = .scaleAspectFit
+        return playImageView
     }()
 
     override init(frame: CGRect) {
         super.init(frame: frame)
-        backgroundColor = UIColor.clear
-        contentView.addSubview(background)
-        background.addSubview(coverView)
-        background.addSubview(markView)
-        background.addSubview(nameLab)
-        background.addSubview(audioLoding)
-        background.addSubview(audioPlaying)
-
+        contentView.addSubview(coverView)
+        contentView.addSubview(markView)
+        contentView.addSubview(nameLab)
+        contentView.addSubview(audioLoding)
+        contentView.addSubview(audioPlaying)
     }
 
     required init?(coder _: NSCoder) {
@@ -110,93 +88,83 @@ class PQVoiceCell: UICollectionViewCell {
 
     func addData() {
         nameLab.text = voice?.name
-//        netImage(url: voice!.avatarUrl, mainView: coverView)
 
         coverView.setNetImage(url: "\(voice?.avatarUrl ?? "")")
-        BFLog(message: "voice!.voiceStatue is \(voice?.name) : \(voice!.voiceStatue)")
+        BFLog(message: "voice!.voiceStatue is \(voice?.name ?? "") : \(voice!.voiceStatue)")
+
+        // 0控制蒙层
         if voice!.voiceStatue == .isNormal {
             markView.isHidden = true
+        } else {
+            markView.isHidden = false
+            if voice!.voiceStatue == .isSelected {
+                markView.image = imageInRecordScreenKit(by: "markSeleced")
+            } else {
+                markView.image = imageInRecordScreenKit(by: "markPlaying")
+            }
+        }
 
-            background.layer.borderWidth = 0
-            nameLab.textColor = UIColor.white
+        // 1控制文字
+        nameLab.textColor = voice!.voiceStatue == .isNormal ? UIColor.white : UIColor.hexColor(hexadecimal: "#389AFF")
 
-            audioPlaying.isHidden = true
-            audioPlaying.stopAnimating()
-            audioLoding.isHidden = true
-            audioLoding.stopAnimating()
+        // 2控制播放状态
+        if voice!.voiceStatue == .isPlaying {
+            BFLog(message: "设置到播放状态!")
+            audioPlaying.isHidden = false
+            audioPlaying.kf.setImage(with: URL(fileURLWithPath: currentBundle()!.path(forResource: "stuckPoint_music_playing", ofType: ".gif")!))
+        } else if voice!.voiceStatue == .isPause {
+            audioPlaying.isHidden = false
+            audioPlaying.image = imageInRecordScreenKit(by: "stuckPoint_music_pause")
 
         } else {
-            markView.isHidden = false
-            background.layer.borderWidth = 2 / 812 * cScreenHeigth
-            background.layer.borderColor = UIColor.hexColor(hexadecimal: "#EE0051").cgColor
-
-            nameLab.textColor = UIColor.hexColor(hexadecimal: "#EE0051")
-
-            if voice!.voiceStatue == .isPlaying {
-                BFLog(message: "设置到播放状态!")
-                audioPlaying.isHidden = false
-                audioLoding.stopAnimating()
-                audioPlaying.stopAnimating()
-                audioPlaying.startAnimating()
-
-                audioLoding.isHidden = true
-            } else if voice!.voiceStatue == .isLoading {
-                audioLoding.layer.removeAllAnimations()
-                audioPlaying.stopAnimating()
-                audioLoding.isHidden = false
-                audioPlaying.isHidden = true
-                // 1.创建动画
-                let rotationAnim = CABasicAnimation(keyPath: "transform.rotation.z")
-                // 2.设置动画的属性
-                rotationAnim.fromValue = 0
-                rotationAnim.toValue = Double.pi * 2
-                rotationAnim.repeatCount = MAXFLOAT
-                rotationAnim.duration = 1
-                // 这个属性很重要 如果不设置当页面运行到后台再次进入该页面的时候 动画会停止
-                rotationAnim.isRemovedOnCompletion = false
-                // 3.将动画添加到layer中
-                audioLoding.layer.add(rotationAnim, forKey: nil)
-            } else if voice!.voiceStatue == .isSelected {
-                audioLoding.isHidden = true
-                audioPlaying.isHidden = true
-
-                audioPlaying.stopAnimating()
-                audioLoding.stopAnimating()
-            }
+            audioPlaying.isHidden = true
         }
 
+        // 3控制加载中状态
+        if voice!.voiceStatue == .isLoading {
+            audioLoding.layer.removeAllAnimations()
+            audioLoding.isHidden = false
+            // 1.创建动画
+            let rotationAnim = CABasicAnimation(keyPath: "transform.rotation.z")
+            // 2.设置动画的属性
+            rotationAnim.fromValue = 0
+            rotationAnim.toValue = Double.pi * 2
+            rotationAnim.repeatCount = MAXFLOAT
+            rotationAnim.duration = 1
+            // 这个属性很重要 如果不设置当页面运行到后台再次进入该页面的时候 动画会停止
+            rotationAnim.isRemovedOnCompletion = false
+            // 3.将动画添加到layer中
+            audioLoding.layer.add(rotationAnim, forKey: nil)
+        } else {
+            audioLoding.layer.removeAllAnimations()
+            audioLoding.isHidden = true
+        }
     }
 
     func addLayout() {
-   
-        background.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.right.equalToSuperview()
-            make.left.bottom.equalToSuperview()
-        }
         coverView.snp.makeConstraints { make in
-            make.top.left.equalToSuperview()
-            make.width.height.equalTo(background.snp.width)
+            make.top.equalToSuperview()
+            make.centerX.equalToSuperview()
+            make.width.height.equalTo(50)
         }
 
-  
         nameLab.snp.makeConstraints { make in
-            make.top.equalTo(coverView.snp.bottom)
-            make.bottom.centerX.equalToSuperview()
+            make.top.equalTo(coverView.snp.bottom).offset(7)
+            make.centerX.equalToSuperview()
+            make.bottom.equalToSuperview()
         }
 
         audioLoding.snp.makeConstraints { make in
             make.center.equalTo(coverView.snp.center)
-            make.height.width.equalTo(adapterHeight(height: cDefaultMargin * 3))
+            make.height.width.equalTo(18)
         }
         audioPlaying.snp.makeConstraints { make in
             make.center.equalTo(coverView.snp.center)
-            make.height.width.equalTo(adapterHeight(height: cDefaultMargin * 3))
+            make.height.width.equalTo(18)
         }
         markView.snp.makeConstraints { make in
-            make.size.equalToSuperview()
+            make.size.equalTo(coverView)
+            make.centerX.equalTo(coverView)
         }
     }
 }
-
-

+ 11 - 16
BFRecordScreenKit/Classes/RecordScreen/ViewModel/BFRecordScreenViewModel.swift

@@ -16,21 +16,19 @@ public class BFRecordScreenViewModel: NSObject {
     /// 取文本转语言 token
     /// - Parameter completeHander: completeHander description
     public class func getNlsAccessToken(completeHander: @escaping (_ token: String, _ appkey: String) -> Void) {
-   
-        let currentLanguage =  BFLocalizedUtil.currentLanguage()
-        BFLog(2,message: "当前的系统语言是:\(currentLanguage)")
+        let currentLanguage = BFLocalizedUtil.currentLanguage()
+        BFLog(2, message: "当前的系统语言是:\(currentLanguage)")
         let nowTime: TimeInterval = Date().timeIntervalSince1970
         //token = "5d96258dcea34d7b91576031cd25a9ba"; 返回数据
-        //expireTime = 1601376826000; //1601377050000;
+        // expireTime = 1601376826000; //1601377050000;
         let saveToken: Dictionary? = getUserDefaults(key: currentLanguage) as? [String: Any] ?? nil
         if saveToken != nil && Double(saveToken!["expireTime"] as! Double) > nowTime * 1000 {
             BFLog(message: "nls token 还有效期内不用重新请求 \(String(describing: saveToken!["expireTime"])) nowTime:\(nowTime * 1000)")
             completeHander(saveToken!["token"] as! String, saveToken!["appkey"] as! String)
             return
         }
-        
-  
-        BFNetRequestAdaptor.getRequestData(url: PQENVUtil.shared.clipapiapi + getNlsAccessTokenForJiangjieApp, parames: ["languageCode":currentLanguage], commonParams: commonParams()) { response, _, _, _ in
+
+        BFNetRequestAdaptor.getRequestData(url: PQENVUtil.shared.clipapiapi + getNlsAccessTokenForJiangjieApp, parames: ["languageCode": currentLanguage], commonParams: commonParams()) { response, _, _, _ in
 
             if let response = response as? [String: Any], let token = response["token"] as? String, let appkey = response["appkey"] as? String {
                 let nowTime: TimeInterval = Date().timeIntervalSince1970
@@ -46,25 +44,23 @@ public class BFRecordScreenViewModel: NSObject {
     }
 
     // 取发音人列表数据
-    class func getAllVoiceCates(completeHander: @escaping (_ categorys:[BFVoiceCategoryModel],_ voices: Dictionary<String, [PQVoiceModel]>) -> Void) {
+    class func getAllVoiceCates(completeHander: @escaping (_ categorys: [BFVoiceCategoryModel], _ voices: Dictionary<String, [PQVoiceModel]>) -> Void) {
         BFNetRequestAdaptor.getRequestData(url: PQENVUtil.shared.clipapiapi + listAllCateVoicesUrl, parames: nil, commonParams: commonParams()) { response, _, _, _ in
 
-            
-            var categorys:[BFVoiceCategoryModel] = Array()
+            var categorys: [BFVoiceCategoryModel] = Array()
             var voccesDic: Dictionary<String, [PQVoiceModel]> = Dictionary()
             if response != nil, !(response is NSNull) {
                 for voices in response as! [[String: Any]] {
-                    
                     var voicesData: [PQVoiceModel] = Array()
                     let cateName = voices["cateName"] as? String ?? ""
                     let cateId = voices["cateId"] as? Int ?? 0
                     BFLog(message: "cateName is \(cateName) cateId is \(cateId)")
-                    let category = BFVoiceCategoryModel.init()
+                    let category = BFVoiceCategoryModel()
                     category.cateName = cateName
                     category.cateID = cateId
                     categorys.append(category)
                     for voice in voices["voiceDatas"] as! [[String: Any]] {
-                        if voice.keys.contains("channel"), "\(voice["channel"] ?? "")" == "aliyun", voice.keys.contains("appEnable"), "\(voice["appEnable"] ?? "")" == "1"  {
+                        if voice.keys.contains("channel"), "\(voice["channel"] ?? "")" == "aliyun", voice.keys.contains("appEnable"), "\(voice["appEnable"] ?? "")" == "1" {
                             let voiceModel = PQVoiceModel()
                             voiceModel.voice = voice["voice"] as? String ?? ""
                             voiceModel.name = voice["name"] as? String ?? ""
@@ -95,16 +91,15 @@ public class BFRecordScreenViewModel: NSObject {
                                 }
                             }
                             voicesData.append(voiceModel)
-                            
                         }
                     }
 
                     voccesDic[cateName] = voicesData
                 }
-                completeHander(categorys,voccesDic)
+                completeHander(categorys, voccesDic)
 
             } else {
-                completeHander(categorys,voccesDic)
+                completeHander(categorys, voccesDic)
             }
         }
     }