Swift4.0 实现底部弹出框

 

网上找了些例子,但是并不能满足我的要求,下面我将网上的荔枝与自己的改进分享给大家

原理: 通过swift4的present 结合SnapKit进行布局

看效果图: 

1、包含自定义view:

         

 

2:显示List

 

项目引进Snapkit

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'Test' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!
  pod 'SnapKit'
  # Pods for lhcp
end

 

弹出框的基类: 可继承实现自己的效果

import SnapKit
import UIKit
class BasePopView: UIViewController{
    
    var contentVeiw = UIView()
    var viewHight: CGFloat = 150
    var needClose = true
    
    let kScreenWidth: CGFloat = UIScreen.main.bounds.size.width
    let kScreenHeight: CGFloat = UIScreen.main.bounds.size.height
    
    
    required init() {
        super.init(nibName: nil, bundle: nil)

        view.backgroundColor = UIColor.clear
        self.providesPresentationContextTransitionStyle = true
        self.definesPresentationContext = true
        self.modalPresentationStyle = .custom
        
        // 初始化UI
        setupUIViews()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        UIView.animate(withDuration: 0.25) {
            self.contentVeiw.alpha = 1
        }
        
    }
    
    func setupUIViews() {
        self.contentVeiw = UIView()
        self.contentVeiw.backgroundColor = UIColor.white
        view.addSubview(self.contentVeiw)
        self.contentVeiw.snp.makeConstraints { (make) -> Void in
            make.left.equalTo(0)
            make.right.equalTo(0)
            make.width.equalTo(kScreenWidth)
            make.height.equalTo(viewHight)
            make.top.equalTo(self.view).offset(kScreenHeight-viewHight)
        }
        
        if(needClose){
            let close = UIButton()
            close.titleLabel?.font = UIFont.systemFont(ofSize: 12)
            close.setTitle("关闭", for: UIControl.State())
            close.setTitleColor(UIColor.black, for: UIControl.State())
            close.contentHorizontalAlignment = UIControl.ContentHorizontalAlignment.center
            close.backgroundColor = .white
            close.addTarget(self, action: #selector(sheetViewDismiss), for: .touchUpInside)
            self.contentVeiw.addSubview(close)
            close.snp.makeConstraints { (make) -> Void in
                make.right.equalTo(0)
                make.width.equalTo(35)
                make.height.equalTo(20)
                make.top.equalTo(self.contentVeiw)
            }
        }
        
    }
    
    @objc func sheetViewDismiss() {
        UIView.animate(withDuration: 0.1, animations: {
            self.contentVeiw.alpha = 0
        }) { (_) in
            self.dismiss(animated: false, completion: nil)
        }
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        //如果所有点都在ContentView外 才关闭
        for touch:AnyObject in touches{
            let point = (touch as AnyObject).location(in: self.view)
            let pt = self.contentVeiw.layer.convert(point, from: self.view.layer)
            if self.contentVeiw.layer.contains(pt){
                return
            }
        }

        sheetViewDismiss()
    }
    
    @objc func cancelBtnDidClick(btn: UIButton) {
        sheetViewDismiss()
    }
}

 

List部分代码:

import UIKit
import SnapKit
class ListPopViewController: BasePopView {
    // ----------------外界调用的属性值--------------
    var valueBlock: valueBlock?
    /// cell内容
    var cellTitleList = [String]()
    /// cell字体颜色
    var cellTitleColor = UIColor.white
    /// cell字体大小
    var cellTitleFont: CGFloat = 16
    /// 标题
    var titleString: String? = "标题"
    /// 标题字体大小
    var titleFont: CGFloat = 15

    
    
    // ---------------内部属性-------------------
    typealias valueBlock = (NSInteger)->Swift.Void
    var tableView = UITableView()
    let cellID = "cellID"
    var tableViewHight: CGFloat {
        return CGFloat(cellTitleList.count) * rowHight + headerViewHight + footerViewHight
    }
    fileprivate let rowHight: CGFloat = 35
    fileprivate let headerViewHight: CGFloat = 35
    fileprivate var footerViewLineHight: CGFloat = 5
    fileprivate var footerViewHight: CGFloat {
        return headerViewHight + footerViewLineHight
    }
    
    required init?(cellTitleList: [String]!) {
        super.init()
        self.needClose = false
        // 初始化
        self.cellTitleList = cellTitleList
        self.viewHight = tableViewHight
        
        view.backgroundColor = UIColor.clear
        self.providesPresentationContextTransitionStyle = true
        self.definesPresentationContext = true
        self.modalPresentationStyle = .custom
        
        // 初始化UI
        setupListViews()
    }

    required init() {
        fatalError("init() has not been implemented")
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    
    func setupListViews() {
        tableView = UITableView(frame: CGRect(x: 0, y: 0, width: kScreenWidth, height: tableViewHight), style: .plain)
        tableView.delegate = self
        tableView.dataSource = self
        tableView.showsVerticalScrollIndicator = false
        tableView.showsHorizontalScrollIndicator = false
        tableView.isScrollEnabled = false
        tableView.bounces = false
        tableView.isPagingEnabled = false
        tableView.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        tableView.register(TitleCell.classForCoder(), forCellReuseIdentifier: cellID)
        view.addSubview(tableView)
        self.tableView.snp.makeConstraints { (make) -> Void in
            make.left.equalTo(0)
            make.right.equalTo(0)
            make.height.equalTo(tableViewHight)
            make.top.equalTo(self.view).offset(kScreenHeight-tableViewHight)
        }
    }

}


// MARK: UITableViewDelegate, UITableViewDataSource
extension ListPopViewController: UITableViewDelegate, UITableViewDataSource {
 
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return cellTitleList.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath) as! TitleCell
        cell.titleLabel.text = cellTitleList[indexPath.row]
        cell.titleLabel.textColor = cellTitleColor
        cell.titleLabel.font = UIFont.systemFont(ofSize: cellTitleFont)
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return CGFloat(rowHight)
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        
        if (self.valueBlock != nil) {
            self.valueBlock!(indexPath.row)
        }
    }
    
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return headerViewHight
    }
    
    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return headerViewHight + 5
    }
    
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        
        let view = UIView(frame: CGRect(x: 0, y: 0, width: kScreenWidth, height: headerViewHight))
        // 标题
        let titleLabel = UILabel(frame: CGRect(x: 0, y: 0, width: kScreenWidth, height: headerViewHight))
        titleLabel.text = titleString
        titleLabel.font = UIFont.systemFont(ofSize: titleFont)
        titleLabel.textColor = UIColor.lightGray
        titleLabel.textAlignment = .center
        view.addSubview(titleLabel)
        // 线
        let lineView = UIView(frame: CGRect(x: 0, y: view.frame.size.height-1, width: kScreenWidth, height: 1))
        lineView.backgroundColor = UIColor(red: 220/250.0, green: 220/250.0, blue: 220/250.0, alpha: 1.0)
        view.addSubview(lineView)
        return view
        
    }
    
    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        let footerView = UIView(frame: CGRect(x: 0, y: 0, width: kScreenWidth, height: footerViewHight))
        
        let lineView = UIView(frame: CGRect(x: 0, y: 0, width: kScreenWidth, height: footerViewLineHight))
        lineView.backgroundColor = UIColor.lightGray
        footerView.addSubview(lineView)
        
        let btn = UIButton(type: .custom)
        btn.frame = CGRect(x: 0, y: footerViewLineHight, width: kScreenWidth, height: footerViewHight-footerViewLineHight)
        footerView.addSubview(btn)
        btn.setTitle("取消", for: .normal)
        btn.titleLabel?.font = UIFont.systemFont(ofSize: titleFont)
        btn.setTitleColor(UIColor.black, for: .normal)
        btn.addTarget(self, action: #selector(cancelBtnDidClick(btn:)), for: .touchUpInside)
        
        return footerView;
    }
}

class TitleCell: UITableViewCell {
    let titleLabel = UILabel()

    override func awakeFromNib() {
        super.awakeFromNib()
    }
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
       super.init(style: style, reuseIdentifier: reuseIdentifier)
        titleLabel.textAlignment = .center
        addSubview(titleLabel)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        titleLabel.frame = self.bounds
    }
}

 

 

调用: 

import UIKit
import SnapKit
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        self.view.backgroundColor = .gray
        let btn = UIButton()
        btn.setTitle("Show Normal", for: UIControl.State())
        btn.setTitleColor(UIColor.black, for: UIControl.State())
        btn.layer.cornerRadius = 3
        self.view.addSubview(btn)
        btn.snp.makeConstraints { (make) -> Void in
            make.left.equalTo(100)
            make.top.equalTo(self.view).offset(100)
        }
        
        let btn2 = UIButton()
        btn2.setTitle("Show List", for: UIControl.State())
        btn2.setTitleColor(UIColor.black, for: UIControl.State())
        btn2.layer.cornerRadius = 3
        self.view.addSubview(btn2)
        btn2.snp.makeConstraints { (make) -> Void in
            make.left.equalTo(140)
            make.top.equalTo(self.view).offset(150)
        }
        btn.addTarget(self, action: #selector(popNormal), for: .touchUpInside)
        btn2.addTarget(self, action: #selector(popList), for: .touchUpInside)
    }
    
    @objc func popNormal()  {
        let acVC = BasePopView()
        present(acVC, animated: true, completion:  nil)
    }
    
    @objc func popList()  {
        let acVC = ListPopViewController(cellTitleList: ["List1", "List2", "List3", "List4"])!
        acVC.valueBlock = { index in
            print(index)
        }
        acVC.cellTitleColor = UIColor.red
        acVC.cellTitleFont = 16
        acVC.titleString = "Lists"
        
        present(acVC, animated: true, completion:  nil)
    }

}

 

 

希望大家高效、愉快撸码

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Swift 4.0中,系统没有提供直接的底部弹窗控件。但是你可以使用UIAlertController和UIAlertAction来创建一个自定义的底部弹窗。下面是一个示例代码: ```swift func showBottomAlert() { let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) let action1 = UIAlertAction(title: "Action 1", style: .default) { (action) in // 处理点击 Action 1 的操作 } alertController.addAction(action1) let action2 = UIAlertAction(title: "Action 2", style: .default) { (action) in // 处理点击 Action 2 的操作 } alertController.addAction(action2) let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (action) in // 处理点击取消按钮的操作 } alertController.addAction(cancelAction) if let popoverPresentationController = alertController.popoverPresentationController { popoverPresentationController.sourceView = self.view popoverPresentationController.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.maxY, width: 0, height: 0) popoverPresentationController.permittedArrowDirections = [] } present(alertController, animated: true, completion: nil) } ``` 在上面的代码中,我们创建了一个UIAlertController,并添加了两个UIAlertAction作为选项,以及一个UIAlertAction作为取消按钮。然后,我们通过present方法将底部弹窗显示在屏幕上。 注意,为了将弹窗显示在底部,我们设置了popoverPresentationController的sourceView为当前的view,并且设置了sourceRect的位置在屏幕底部中间。这样就能够实现底部弹窗的效果。 希望这可以帮助你实现底部弹窗!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值