第八天:SwiftLrcShareTool

参考链接:https://www.jianshu.com/nb/13566182

 

                               

 

 

 1 import UIKit
 2 
 3 class MCLrcDecoder: NSObject {
 4     
 5     // 存储歌词的数组
 6     lazy var lrcArray = [String]()
 7     
 8     // 存储歌词时间的数组
 9     lazy var timeArray = [String]()
10     
11     // 歌词文件名
12     var fileName = ""
13     
14     public func loadLrc(fileName: String) -> NSString {
15         let filePath = Bundle.main.path(forResource: fileName, ofType: "lrc")
16         let data = NSData.init(contentsOfFile: filePath!)
17         return NSString(data: data! as Data, encoding: String.Encoding.utf8.rawValue)!
18     }
19     
20     func decodeLrc(lrcString: NSString) {
21         var sepArray = lrcString.components(separatedBy: "[")
22         var lineArray = [String]()
23         
24         for i in 0..<sepArray.count {
25             if sepArray[i].count > 0 {
26                 lineArray = sepArray[i].components(separatedBy: "]")
27                 if (lineArray[0] != "\n") {
28                     self.timeArray.append(lineArray[0])
29                     self.lrcArray.append(lineArray.count > 1 ? lineArray[1] : "")
30                 }
31             }
32         }
33     }
34 }

 

 1 import UIKit
 2 
 3 class MCLrcCell: UITableViewCell {
 4 
 5     @IBOutlet weak var iconImage: UIImageView!
 6     @IBOutlet weak var lrcLabel: UILabel!
 7     @IBOutlet weak var imgLeadConstrains: NSLayoutConstraint!
 8     
 9     // 属性,使用计算属性观察者
10     var lrcSelecting = false {
11         didSet {
12             self.didChangeLrcSelecting()
13         }
14     }
15     
16     var lrcSelected = false {
17         didSet {
18             self.didChangedLrcSelected()
19         }
20     }
21     
22     var lrc: String = "" {
23         didSet {
24             self.lrcLabel.text = lrc
25         }
26     }
27     
28     override func awakeFromNib() {
29         super.awakeFromNib()
30         // Initialization code
31         
32         self.backgroundColor = UIColor.clear
33         self.reset()
34     }
35     
36     func reset() {
37         // 重置 selecting 选项
38         self.lrcSelecting = false
39         // 重置 selected 选项
40         self.lrcSelected = false
41         // FIXME:
42     }
43     
44     // MARK: - 私有方法 API
45     let IMG_CONSTRAIN_SELE: CGFloat = 8
46     let IMG_CONSTRAIN_NONSELE: CGFloat = -8 + -8 + -20
47     private func didChangeLrcSelecting() {
48         // 设置约束
49         if self.lrcSelecting {
50             self.imgLeadConstrains.constant = IMG_CONSTRAIN_SELE
51         } else {
52             self.imgLeadConstrains.constant = IMG_CONSTRAIN_NONSELE
53         }
54     }
55 
56     private func didChangedLrcSelected() {
57         self.iconImage.image = self.lrcSelected ? #imageLiteral(resourceName: "img_selected") : #imageLiteral(resourceName: "img_nonselected")
58     }
59     
60     override func setSelected(_ selected: Bool, animated: Bool) {
61         super.setSelected(selected, animated: animated)
62 
63         // Configure the view for the selected state
64     }
65     
66 }

 

  1 import UIKit
  2 
  3 class MCLrcVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
  4 
  5     // UI 控件
  6     var tableView: UITableView!
  7     @IBOutlet weak var createButton: UIBarButtonItem!
  8     
  9     // 属性列表
 10     var decoder: MCLrcDecoder = MCLrcDecoder()
 11     var fileName: String?
 12     var cellSelecting: Bool?
 13     
 14     // 存储 cell 的选择状态
 15     var cellDict = [String: Bool]()
 16     
 17     override func viewDidLoad() {
 18         super.viewDidLoad()
 19 
 20         // Do any additional setup after loading the view.
 21         
 22         fileName = "song"
 23         setupTableView()
 24         setupButton()
 25         loadLrc()
 26     }
 27 
 28     // MARK: - 私有 API
 29     fileprivate func setupTableView() {
 30         let tableView = UITableView(frame: UIScreen.main.bounds)
 31         tableView.delegate = self
 32         tableView.dataSource = self
 33         tableView.backgroundColor = UIColor.black
 34         tableView.separatorStyle = UITableViewCellSeparatorStyle.none
 35         cellSelecting = false
 36         
 37         // 添加长按手势
 38         let longPressGes = UILongPressGestureRecognizer(target: self, action: #selector(tableViewLongPressAction(_:)))
 39         tableView.addGestureRecognizer(longPressGes)
 40         
 41         self.view.addSubview(tableView)
 42         self.tableView = tableView
 43         
 44         // 注册所用的 cell
 45         registeCell()
 46     }
 47     
 48     fileprivate func setupButton() {
 49         createButton.isEnabled = false
 50         createButton.tintColor = UIColor.clear
 51         createButton.target = self
 52         createButton.action = #selector(createShareImage)
 53     }
 54     
 55     fileprivate func registeCell() {
 56         tableView.register(UINib(nibName: "MCLrcCell", bundle: Bundle.main), forCellReuseIdentifier: "cellId")
 57     }
 58     
 59     fileprivate func loadLrc() {
 60         let filePath = self.decoder.loadLrc(fileName: self.fileName!)
 61         self.decoder.decodeLrc(lrcString: filePath)
 62         self.tableView.reloadData()
 63     }
 64     
 65     @objc fileprivate func createShareImage() {
 66         if cellSelecting == false {
 67             return
 68         }
 69         
 70         // 生成歌词数组
 71         var lrcArr = [String]()
 72         for i in 0..<decoder.lrcArray.count {
 73             // 生成 Key, 通过 Key 访问字典
 74             let isLrcSelected = cellDict["0-\(i)"]
 75             if isLrcSelected != nil && isLrcSelected == true {
 76                 lrcArr.append(self.decoder.lrcArray[i])
 77             }
 78         }
 79         
 80         // 如果没有选择歌词,则提示
 81         if lrcArr.count <= 0 {
 82             let alert = UIAlertController(title: "提示", message: "请至少选择一句歌词", preferredStyle: .alert)
 83             alert.addAction(UIAlertAction (title: "确定", style: .default, handler: nil))
 84             self.present(alert, animated: true, completion: nil)
 85             return
 86         }
 87         
 88         // 显示歌词分享界面
 89         let storyBoard = UIStoryboard (name: "MCShareVC", bundle: nil)
 90         let vc = storyBoard.instantiateViewController(withIdentifier: "MCShareVC") as! MCShareVC
 91         
 92         vc.lrcArr = lrcArr
 93         self.navigationController?.pushViewController(vc, animated: true)
 94     }
 95     
 96     @objc fileprivate func tableViewLongPressAction(_ longPresas: UILongPressGestureRecognizer) {
 97         if longPresas.state != UIGestureRecognizerState.began {
 98             return
 99         }
100         
101         // 切换选择模式
102         cellSelecting = cellSelecting == true ? false : true
103         if cellSelecting == true {
104             // 清空映射字典
105             cellDict.removeAll()
106             // 显示按钮
107             createButton.isEnabled = true
108             createButton.tintColor = UIColor.red
109         } else {
110             // 隐藏按钮
111             createButton.isEnabled = false
112             createButton.tintColor = UIColor.clear
113         }
114         
115         // 更新 tableView
116         self.tableView.reloadData()
117     }
118     
119     
120     override func didReceiveMemoryWarning() {
121         super.didReceiveMemoryWarning()
122         // Dispose of any resources that can be recreated.
123     }
124     
125 
126     /*
127     // MARK: - Navigation
128 
129     // In a storyboard-based application, you will often want to do a little preparation before navigation
130     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
131         // Get the new view controller using segue.destinationViewController.
132         // Pass the selected object to the new view controller.
133     }
134     */
135 
136 }
137 
138 // MARK: - 代理方法实现
139 extension MCLrcVC {
140     func numberOfSections(in tableView: UITableView) -> Int {
141         return 1
142     }
143     
144     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
145         return self.decoder.lrcArray.count
146     }
147     
148     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
149         let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! MCLrcCell
150         
151         cell.reset()
152         cell.lrc = self.decoder.lrcArray[indexPath.row]
153         cell.lrcSelecting = cellSelecting!
154         
155         // 判断 cell 是否正处于选择状态
156         let isCellSelected = cellDict["\(indexPath.section)-\(indexPath.row)"]
157         if let isCellSelected = isCellSelected {
158             cell.lrcSelected = isCellSelected
159         }
160         
161         
162         return cell
163     }
164     
165     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
166         tableView.deselectRow(at: indexPath, animated: true)
167         
168         // 如果没有在选择状态,则推出
169         if cellSelecting == false {
170             return
171         }
172         
173         let cell = tableView.cellForRow(at: indexPath) as! MCLrcCell
174         cell.lrcSelected = cell.lrcSelected == true ? false : true
175         self.cellDict["\(indexPath.section)-\(indexPath.row)"] = cell.lrcSelected
176     }
177     
178 }

 

  1 import UIKit
  2 
  3 class MCShareVC: UIViewController, UIScrollViewDelegate {
  4 
  5     // UI 控件
  6     @IBOutlet weak var scrollView: UIScrollView!
  7     @IBOutlet weak var shareButton: UIButton!
  8     @IBOutlet weak var saveButton: UIButton!
  9     
 10     var bkgImage: UIImageView!
 11     
 12     // 数据
 13     var lrcArr = [String]()
 14     
 15     override func viewDidLoad() {
 16         super.viewDidLoad()
 17 
 18         // Do any additional setup after loading the view.
 19         
 20         setupView()
 21         setupButton()
 22         
 23         drawLrcBackground()
 24         addLrcToBackground()
 25         
 26     }
 27 
 28     // MARK: - 初始化私有方法
 29     func setupView() {
 30         scrollView.backgroundColor = UIColor.clear
 31         
 32         if #available(iOS 11.0, *) {
 33             scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.never
 34         } else {
 35             automaticallyAdjustsScrollViewInsets = false
 36         }
 37         
 38         self.bkgImage = UIImageView()
 39         bkgImage.contentMode = UIViewContentMode.scaleToFill
 40     }
 41     
 42     func setupButton() {
 43         shareButton.addTarget(self, action: #selector(shareImageHandler), for: .touchUpInside)
 44         saveButton.addTarget(self, action: #selector(saveImageHandler), for: .touchUpInside)
 45     }
 46     
 47     let kItemHeight: CGFloat = 20
 48     let kItemMargin: CGFloat = 5
 49     
 50     // 通过图片拉伸,将背景图片适配各种屏幕
 51     func drawLrcBackground() {
 52         let kItemDefaultHeight: CGFloat = 150
 53         
 54         let imageWidth = view.frame.size.width
 55         let imageHeight = CGFloat(lrcArr.count) * (kItemHeight + kItemMargin)
 56         
 57         bkgImage.frame = CGRect(x: 0, y: 0, width: imageWidth, height: kItemDefaultHeight + imageHeight)
 58         scrollView.addSubview(bkgImage)
 59         
 60         // 获取图片
 61         let sourceImage = UIImage(named: "shareBkg.png")
 62         bkgImage.image = sourceImage
 63         
 64         // 设置图片拉伸参数
 65         let topInset = sourceImage!.size.height * 0.4
 66         let leftInset = sourceImage!.size.width * 0.7
 67         let bottomInset = sourceImage!.size.height - topInset - 1
 68         let rightInset = sourceImage!.size.width - leftInset - 1
 69         
 70         let bkgEdgeInsets = UIEdgeInsets(top: topInset, left: leftInset, bottom: bottomInset, right: rightInset)
 71         
 72         // 拉伸图片
 73         let resizedImage = sourceImage?.resizableImage(withCapInsets: bkgEdgeInsets, resizingMode: UIImageResizingMode.stretch)
 74         
 75         // 设置图片和 ScrollView
 76         bkgImage.image = resizedImage
 77         scrollView.contentSize = bkgImage.frame.size
 78     }
 79     
 80     // 向背景中添加歌词
 81     func addLrcToBackground() {
 82         let kLrcStartX: CGFloat = 40
 83         let kLrcStartY: CGFloat = 50
 84         
 85         let kLrcRightMargin: CGFloat = 20
 86         
 87         let xCursor = kLrcStartX
 88         var yCursor = kLrcStartY
 89         
 90         // 按顺序添加歌词到背景上
 91         for i in 0..<lrcArr.count {
 92             // 获取当前歌词
 93             let curLrc = lrcArr[i]
 94             // 创建歌词对应的 Label
 95             let lrcLabel = UILabel(frame: CGRect(x: xCursor, y: yCursor, width: view.frame.size.width - 2 * kLrcStartX, height: kItemHeight))
 96             
 97             lrcLabel.text = curLrc
 98             lrcLabel.textColor = UIColor.darkGray
 99             lrcLabel.font = UIFont.systemFont(ofSize: 15)
100             
101             bkgImage.addSubview(lrcLabel)
102             
103             // y 坐标递增
104             yCursor += kItemHeight + kItemMargin
105         }
106         
107         // 添加底部歌名
108         let rightText = "--[Minecode - iOS.Dev]"
109         
110         yCursor += kLrcRightMargin
111         
112         let rightLabel = UILabel (frame: CGRect (x: xCursor, y: yCursor, width: view.frame.size.width - 2 * kLrcStartX, height: kItemHeight))
113         
114         rightLabel.text = rightText
115         rightLabel.textColor = UIColor.darkGray
116         rightLabel.textAlignment = NSTextAlignment.right
117         rightLabel.font = UIFont.systemFont(ofSize: 15)
118         
119         bkgImage.addSubview(rightLabel)
120     }
121     
122     // MARK: - 分享和保存
123     
124     // 保存到相册中
125     @objc func saveImageHandler() {
126         // 生成 View 的图片
127         UIGraphicsBeginImageContextWithOptions(self.bkgImage.bounds.size, true, 0)
128         bkgImage.layer.render(in: UIGraphicsGetCurrentContext()!)
129         let bitmap = UIGraphicsGetImageFromCurrentImageContext()
130         UIGraphicsEndImageContext()
131         
132 //        let imageData = UIImagePNGRepresentation(bitmap!)
133         
134 //        let imageData = UIImageJPEGRepresentation(bitmap!, 0.1)
135 //        let tempImg = UIImage.init(data: imageData!)
136         
137         // 保存到相册
138         UIImageWriteToSavedPhotosAlbum(bitmap!, self, #selector(image(image:didFinishSavingWithError:contextInfo:)), nil)
139     }
140     
141     // 使用系统分享功能分享图片
142     @objc func shareImageHandler() {
143         
144         // 生成 View 的图片
145         UIGraphicsBeginImageContextWithOptions(self.bkgImage.bounds.size, true, 0)
146         bkgImage.layer.render(in: UIGraphicsGetCurrentContext()!)
147         let bitmap = UIGraphicsGetImageFromCurrentImageContext()
148         UIGraphicsEndImageContext()
149         
150         let activityVc = UIActivityViewController (activityItems: [bitmap!], applicationActivities: nil)
151         self.present(activityVc, animated: true, completion: nil)
152     }
153     
154     // 保存到相册后的回调
155     @objc func image(image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: AnyObject) {
156         
157         if error == nil {
158             
159             let alert = UIAlertController(title: "成功", message: "保存成功", preferredStyle: .alert)
160             alert.addAction(UIAlertAction(title: "确定", style: .destructive, handler: nil))
161             self.present(alert, animated: true, completion: nil)
162             
163         } else {
164             
165             let alert = UIAlertController(title: "失败", message: "保存失败", preferredStyle: .alert)
166             alert.addAction(UIAlertAction(title: "确定", style: .destructive, handler: nil))
167             self.present(alert, animated: true, completion: nil)
168             
169         }
170     }
171     
172     override func didReceiveMemoryWarning() {
173         super.didReceiveMemoryWarning()
174         // Dispose of any resources that can be recreated.
175     }
176     
177     /*
178     // MARK: - Navigation
179 
180     // In a storyboard-based application, you will often want to do a little preparation before navigation
181     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
182         // Get the new view controller using segue.destinationViewController.
183         // Pass the selected object to the new view controller.
184     }
185     */
186 
187 }

 

posted @ 2018-02-18 16:53  鳄鱼不怕牙医不怕  阅读(276)  评论(0编辑  收藏  举报