swift实现仿知乎摇一摇弹出框

388 阅读2分钟

前言:在玩知乎的时候,总是一不小心摇动了下手机就弹出了一个反馈窗口(好吧,这并不是一个良好的用户体验),思考了一下它是怎么实现的,本来以为摇一摇这个功能比较复杂,没想到动手实现了一下发现,苹果已经完全的封装好了,只需要简单的实现它的代理方法即可。 先上效果图

这个弹出框的实现也非常简单,需要注意的几个点,适配弹出框的高度,由于顶部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里了。