1. 程式人生 > >ios:點選tabbar中間按鈕彈出選單(swift 3實現)

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<String> = {
        var tempAry:Array<String> = []
        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)

    }  
}

原始碼:點我下載