前言:在玩知乎的時候,總是一不小心搖動了下手機就彈出了一個反饋視窗(好吧,這並不是一個良好的使用者體驗),思考了一下它是怎麼實現的,本來以為搖一搖這個功能比較複雜,沒想到動手實現了一下發現,蘋果已經完全的封裝好了,只需要簡單的實現它的代理方法即可。 先上效果圖
這個彈出框的實現也非常簡單,需要注意的幾個點,適配彈出框的高度,由於頂部Label和下面TableView的高度是不固定的,所以我們需要注意適配彈出框的高度,這裡我用SnapKit做佈局,將tableView的底部和容器View的底部對齊,再讓容器View的高度大於等於某個值,這樣系統可以根據tableView的高度來自適應容器View的高度。下面我們看看程式碼具體是怎麼實現的:
首先定義一個協議FSCAlertViewDelegate,裡面含有一個方法alertViewSlectedAction,做為點選tableView中某一項的回撥
protocol FSCAlertViewDelegate { func alertViewSlectedAction(row: Int) }
宣告彈出框所需的UI和資料來源:
//背景容器
var backgroundView: UIView!
//標題Label
var titleLabel: UILabel!
//標題
var title:
//詳情Label
var messageLabel: UILabel!
//詳情
var message: String
//表格View
var tableView: UITableView!
//表格資料來源
var labelStrings: [String]
//點選按鈕回撥
var delegate: FSCAlertViewDelegate?
//初始化相關的控制元件
//注意為了讓彈出框的高度可以自適應,彈出框的高度不可以寫死,讓他大於等於某個高度即可
func initView() {
self.backgroundColor = UIColor.lightGray
self.alpha = 1
backgroundView = UIView(frame: CGRect.zero)
backgroundView.backgroundColor = UIColor.white
backgroundView.layer.cornerRadius = 20
backgroundView.clipsToBounds = true
addSubview(backgroundView)
backgroundView.snp.makeConstraints { (make) in
make.center.equalToSuperview()
make.width.equalTo(screenWidth - 80)
make.height.greaterThanOrEqualTo(0)
}
titleLabel = UILabel(frame: CGRect.zero)
titleLabel.text = title
titleLabel.textAlignment = .center
titleLabel.font = UIFont.systemFont(ofSize: 22)
titleLabel.textColor = UIColor.black
titleLabel.numberOfLines = 0
backgroundView.addSubview(titleLabel)
titleLabel.snp.makeConstraints { (make) in
make.left.equalTo(16)
make.right.equalTo(-16)
make.top.equalTo(16)
make.height.greaterThanOrEqualTo(20)
}
messageLabel = UILabel(frame: CGRect.zero)
messageLabel.text = message
messageLabel.textAlignment = .center
messageLabel.font = UIFont.systemFont(ofSize: 17)
messageLabel.textColor = UIColor.darkGray
messageLabel.numberOfLines = 0
backgroundView.addSubview(messageLabel)
messageLabel.snp.makeConstraints { (make) in
make.top.equalTo(titleLabel.snp.bottom).offset(8)
make.left.equalTo(16)
make.right.equalTo(-16)
make.height.greaterThanOrEqualTo(20)
}
tableView = UITableView(frame: CGRect.zero)
tableView.dataSource = self
tableView.delegate = self
backgroundView.addSubview(tableView)
tableView.snp.makeConstraints { (make) in
make.left.equalTo(0)
make.right.equalTo(0)
make.top.equalTo(messageLabel.snp.bottom).offset(10)
make.height.equalTo(50*labelStrings.count)
make.bottom.equalToSuperview()
}
}
//後面是tableView相關的資料來源和代理
//MARK: - TableViewDataSource and Delegate
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return labelStrings.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
cell.textLabel?.text = labelStrings[indexPath.row]
cell.textLabel?.textAlignment = .center
cell.textLabel?.textColor = UIColor.blue
cell.textLabel?.font = UIFont.systemFont(ofSize: 20)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
delegate?.alertViewSlectedAction(row: indexPath.row)
self.removeFromSuperview()
}
//實現搖一搖的功能也簡單,首先讓你的類實現AVAudioPlayerDelegate協議,代理有相關方法motionEnded,在代理方法中,彈出提示框即可
override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
fscAlertView = FSCAlertView(frame: self.view.bounds, title: "請問需要反饋什麼問題?", message: "你也可以在個人頁的反饋幫助中心找到這個功能", labelStrings: ["幫助中心","遇到異常","意見反饋","參與Beta版本","關閉搖一搖","沒啥事"])
fscAlertView.delegate = self
self.view.addSubview(fscAlertView)
}
附上專案連結:https://github.com/sichangfeng/FSCAlertView.git,專案下載即可用,一般在專案裡搖一搖事件應該是全域性監控的,相關的方法應該在AppDelegate中實現,可以獲取UIWindow下的view,再彈出提示框。專案例項程式碼為了方便,我就寫在ViewController裡了。複製程式碼