ios:点击tabbar中间按钮弹出菜单(swift 3实现)

先上一张图看看效果:

最近在自学swift3,就用swift3重写了这个小demo,在项目开发中像这种弹出菜单使用的几率还是很大的,在这里仅仅做一个简单的分享,本例子中没有难度大高深的代码,纯属练练手,如有不严谨的地方,还请多多指正!
下面mark一下一些关键的代码:

ViewController.swift

//
//  ViewController.swift
//  SwiftDemo
//
//  Created by turbomx on 2016/11/26.
//  Copyright © 2016年 xiazy. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var footView: UIView!
    @IBOutlet weak var popBtn: UIButton!

    @IBAction func popBtnClicked(_ sender: Any) {
        let bgImg :UIImage? = UIImage.imageWithCaptureView(view: self.view)
        let popVC : MXPopMenuVC = MXPopMenuVC()
        popVC.bgImg = bgImg
        self.navigationController?.pushViewController(popVC, animated: true)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.title = "首页"
        let bgImgView :UIImageView = UIImageView(image: UIImage(named:"bg.png")!)
        bgImgView.frame = UIScreen.main.bounds
        self.view.insertSubview(bgImgView, belowSubview: self.footView)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

extension UIImage{
    //截屏
    class func imageWithCaptureView(view:UIView)->UIImage?{
        let size:CGSize = CGSize(width: view.bounds.size.width, height: view.bounds.size.height-40)
        //开启位图上下文
        UIGraphicsBeginImageContextWithOptions(size,false, 0)
        //获取上下文
        let ctx :CGContext? = UIGraphicsGetCurrentContext()
        //把控件的图层渲染到上下文,layer只能渲染
        view.layer .render(in: ctx!)
        //生成新图片
        let image:UIImage? = UIGraphicsGetImageFromCurrentImageContext()
        //关闭上下文
        UIGraphicsEndImageContext()
        return image;
    }
}

MXPopMenuVC.swift

//
//  MXPopMenuVC.swift
//  SwiftDemo
//
//  Created by turbomx on 2016/11/28.
//  Copyright © 2016年 xiazy. All rights reserved.
//


import UIKit

class MXPopMenuVC : UIViewController{

    var upIndex:Int = 0
    var downIndex:Int = 0
    var closeImgView:UIImageView?
    var myTimer:Timer?
    var bgImg:UIImage?

    lazy var itemButtons :[MXMenuButton] = {
        return []
    }()

    lazy var ary:Array = {
        var tempAry:Array = []
        for i in 18001...18006{
            tempAry.append("\(i)")
        }
        return tempAry
    }()

    lazy var titleAry:[String]={
        return ["学习","交流","关注","sina","围脖:","turbomx"];
    }()
    //代码生成视图
    override func loadView() {
        super.loadView()
        self.navigationItem.setHidesBackButton(true, animated: false)
        let contentView:UIView = UIView(frame: UIScreen.main.bounds)
        contentView.backgroundColor = UIColor.white
        let imgView:UIImageView = UIImageView(image: self.bgImg!)
        //创建蒙板
        let bgView:UIView = UIView(frame: UIScreen.main.bounds)
        bgView.backgroundColor = UIColor(white: 0.9, alpha: 0.8)
        imgView.addSubview(bgView)
        contentView.addSubview(imgView)
        self.view = contentView
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        self.addMenu()
        self.addCloseImg()
        //设置定时器,弹出逐个弹出菜单按钮
        self.myTimer = Timer(timeInterval: 0.1, target: self, selector: #selector(popupBtn), userInfo: nil, repeats: true)
        //将定时器添加到运行循环
        RunLoop.current.add(myTimer!, forMode: .commonModes)

        let singleTap :UIGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(backAction))
        self.view.isUserInteractionEnabled = true
        self.view.addGestureRecognizer(singleTap)
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        UIView.animate(withDuration: 0.6, animations: {()->Void in
            self.closeImgView?.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI))
        })
    }

    //添加菜单按钮
    fileprivate func addMenu(){

        let cols:Int = 3
        var col:Int = 0
        var row:Int = 0
        var x:CGFloat = 0
        var y:CGFloat = 0
        let wh:CGFloat = 90
        let margin:CGFloat = (UIScreen.main.bounds.size.width - CGFloat(cols) * wh )/(CGFloat(cols) + 1)
        let oriY:CGFloat = 300

        for i in 0 ..< ary.count{
            let btn : MXMenuButton = MXMenuButton(type: .custom)
            let img :UIImage = UIImage.init(named: "\(ary[i])")!
            btn.setImage(img, for: .normal)
            btn.setTitle(titleAry[i], for: .normal)
            col = i % cols //当前列
            row = i / cols //当前行
            x = margin + CGFloat(col)*(margin+wh)
            y = CGFloat(row) * (margin + wh) + oriY
            btn.frame = CGRect(x:x,y:y,width:wh,height:wh)
            //每次都是以最初位置的中心点为起始参照
            btn.transform = CGAffineTransform(translationX: 0, y: self.view.bounds.size.height);
            btn.tag = 1000 + i
            btn.addTarget(self, action: #selector(btnClicked(btn:)), for: .touchUpInside)
            itemButtons.append(btn)
            self.view.addSubview(btn)
        }
    }

    //添加closeImg
    fileprivate func addCloseImg(){
        let imgView : UIImageView = UIImageView(image: UIImage(named:"closeImg"))
        imgView.frame = CGRect(x:self.view.center.x-15 ,y:self.view.frame.height-30 ,width:30 ,height:30)
        self.view .addSubview(imgView)
        self.closeImgView = imgView
    }

    //菜单按钮点击事件
    func btnClicked(btn:MXMenuButton){
        switch btn.tag {
        case 1000:
            if let str = btn.titleLabel?.text{
                print(str)
            }
        case 1001:
            print(""+(btn.titleLabel?.text)!)
        case 1002:
            print(""+(btn.titleLabel?.text)!)
        case 1003:
            print(""+(btn.titleLabel?.text)!)
        case 1004:
            print(""+(btn.titleLabel?.text)!)
        case 1005:
            print(""+(btn.titleLabel?.text)!)
        default:
            print(""+(btn.titleLabel?.text)!)
        }
        UIView.animate(withDuration: 0.5, animations: {()->Void in
            btn.transform = CGAffineTransform(scaleX: 2.0, y: 2.0)
        }, completion: {(finished:Bool)->Void in
            //使用首尾式动画区分闭包
            UIView.beginAnimations("", context: nil)
            UIView.setAnimationDuration(0.3)
            btn.transform = .identity
            UIView.commitAnimations();
        })
    }
    //弹出菜单
    func popupBtn(){

        if self.upIndex == self.itemButtons.count{
            self.downIndex = self.itemButtons.count - 1
            self.myTimer?.invalidate()
            self.upIndex = 0
            return;
        }
        let tempBtn:MXMenuButton = self.itemButtons[self.upIndex]
        self.setUpOneBtnAnim(btn:tempBtn)
        self.upIndex+=1
    }

    //设置按钮从第一个开始向上滑动显示
    func setUpOneBtnAnim(btn:MXMenuButton){
        UIView.animate(withDuration: 0.8, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0, options: .curveEaseIn, animations: {()->Void in
            btn.transform = .identity;
        }, completion: nil)
    }
    //返回
    func backAction(){
        self.myTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(popdownBtn), userInfo: nil, repeats: true)
        //设置关闭动画
        UIView.animate(withDuration: 0.3, animations: {()->Void in
            print(CGFloat(-M_PI_2*1.5))
            self.closeImgView?.transform = CGAffineTransform(rotationAngle:  CGFloat(-M_PI_4))
        })
    }
    //设置按钮从最后一个开始向下滑动显示
    func popdownBtn(){
        if self.downIndex == -1{
            //pop当前页面
            _ = self.navigationController?.popViewController(animated: true)
            self.myTimer?.invalidate()
            return
        }
        let tempBtn:MXMenuButton = self.itemButtons[self.downIndex]
        self.setDownOneBtnAnim(btn:tempBtn)
        self.downIndex -= 1
    }
    //设置动画
    func setDownOneBtnAnim(btn:MXMenuButton){
        UIView.animate(withDuration: 0.6, animations: {()->Void in
            btn.transform = CGAffineTransform(translationX: 0, y: self.view.bounds.size.height)
        }, completion: nil)
    }
    //析构函数
    deinit {
        print("执行析构函数")
    }
}

MXMenuButton.swift

//
//  MXMenuButton.swift
//  SwiftDemo
//
//  Created by turbomx on 2016/11/28.
//  Copyright © 2016年 xiazy. All rights reserved.
//

import UIKit
open class MXMenuButton:UIButton{
    override init(frame:CGRect){
        super.init(frame: frame)
        self.imageView?.contentMode = .center
        self.titleLabel?.textAlignment = .center
        self.setTitleColor(UIColor.black, for: .normal)
        self.titleLabel?.font = UIFont.systemFont(ofSize: 12)
    }

    required public init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override open func layoutSubviews() {
        super.layoutSubviews()
        let imageX:CGFloat = 0
        let imageY:CGFloat = 0
        let imageW:CGFloat = self.bounds.size.width
        let imageH:CGFloat = self.bounds.size.height * 0.8
        self.imageView?.frame = CGRect(x:imageX,y:imageY,width:imageW,height:imageH)

        let labelY:CGFloat = imageH
        let labelH:CGFloat = self.bounds.size.height - labelY
        self.titleLabel?.frame = CGRect(x:imageX,y:labelY,width:imageW,height:labelH)

    }  
}

源码:点我下载

你可能感兴趣的:(iOS,swift)