手记

IOS APP 侧边栏滑动

import UIKit

// 此 View Controller 为根容器,本身并不包含任何 UI 元素
class ViewController: UIViewController {

// 该 TabBar Controller 不是传统意义上的容器,在此只负责提供 UITabBar 这个 UI 组件var mainTabBarController: MainTabBarController!// 主界面点击手势,用于在菜单划出状态下点击主页后自动关闭菜单var tapGesture: UITapGestureRecognizer!// 首页的 Navigation Bar 的提供者,是首页的容器var homeNavigationController: UINavigationController!// 首页中间的主要视图的来源var homeViewController: HomeViewController!// 侧滑菜单视图的来源var leftViewController: LeftViewController!// 构造主视图,实现 UINavigationController.view 和 HomeViewController.view 一起缩放var mainView: UIView!// 侧滑所需参数var distance: CGFloat = 0let FullDistance: CGFloat = 0.78let Proportion: CGFloat = 0.77var centerOfLeftViewAtBeginning: CGPoint!
var proportionOfLeftView: CGFloat = 1var distanceOfLeftView: CGFloat = 50// 侧滑菜单黑色半透明遮罩层var blackCover: UIView!

override func viewDidLoad() {    super.viewDidLoad()    
    // 给根容器设置背景
    let imageView = UIImageView(image: UIImage(named: "back"))
    imageView.frame = UIScreen.mainScreen().bounds    self.view.addSubview(imageView)    
    // 通过 StoryBoard 取出左侧侧滑菜单视图
    leftViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("LeftViewController") as! LeftViewController    // 适配 4.7 和 5.5 寸屏幕的缩放操作,有偶发性小 bug
    if Common.screenWidth > 320 {
        proportionOfLeftView = Common.screenWidth / 320
        distanceOfLeftView += (Common.screenWidth - 320) * FullDistance / 2
    }
    leftViewController.view.center = CGPointMake(leftViewController.view.center.x - 50, leftViewController.view.center.y)
    leftViewController.view.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.8, 0.8)    
    // 动画参数初始化
    centerOfLeftViewAtBeginning = leftViewController.view.center    // 把侧滑菜单视图加入根容器
    self.view.addSubview(leftViewController.view)    
    // 在侧滑菜单之上增加黑色遮罩层,目的是实现视差特效
    blackCover = UIView(frame: CGRectOffset(self.view.frame, 0, 0))
    blackCover.backgroundColor = UIColor.blackColor()    self.view.addSubview(blackCover)    
    // 初始化主视图,即包含 TabBar、NavigationBar和首页的总视图
    mainView = UIView(frame: self.view.frame)    // 初始化 TabBar
    let nibContents = NSBundle.mainBundle().loadNibNamed("MainTabBarController", owner: nil, options: nil)
    mainTabBarController = nibContents.first as! MainTabBarController    // 取出 TabBar Controller 的视图加入主视图
    let tabBarView = mainTabBarController.view
    mainView.addSubview(tabBarView)    // 从 StoryBoard 取出首页的 Navigation Controller
    homeNavigationController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("HomeNavigationController") as! UINavigationController
    // 从 StoryBoard 初始化而来的 Navigation Controller 会自动初始化他的 Root View Controller,即 HomeViewController
    // 我们将其(指针)取出,赋给容器 View Controller 的成员变量 homeViewController
    homeViewController = homeNavigationController.viewControllers.first as! HomeViewController    // 分别将 Navigation Bar 和 homeViewController 的视图加入 TabBar Controller 的视图
    tabBarView.addSubview(homeViewController.navigationController!.view)
    tabBarView.addSubview(homeViewController.view)    
    // 在 TabBar Controller 的视图中,将 TabBar 视图提到最表层
    tabBarView.bringSubviewToFront(mainTabBarController.tabBar)    
    // 将主视图加入容器
    self.view.addSubview(mainView)    
    // 分别指定 Navigation Bar 左右两侧按钮的事件
    homeViewController.navigationItem.leftBarButtonItem?.action = Selector("showLeft")
    homeViewController.navigationItem.rightBarButtonItem?.action = Selector("showRight")    
    // 给主视图绑定 UIPanGestureRecognizer
    let panGesture = homeViewController.panGesture
    panGesture.addTarget(self, action: Selector("pan:"))
    mainView.addGestureRecognizer(panGesture)    
    // 生成单击收起菜单手势
    tapGesture = UITapGestureRecognizer(target: self, action: "showHome")
}

override func didReceiveMemoryWarning() {    super.didReceiveMemoryWarning()    // Dispose of any resources that can be recreated.}// 响应 UIPanGestureRecognizer 事件func pan(recongnizer: UIPanGestureRecognizer) {
    let x = recongnizer.translationInView(self.view).x
    let trueDistance = distance + x // 实时距离
    let trueProportion = trueDistance / (Common.screenWidth*FullDistance)    
    // 如果 UIPanGestureRecognizer 结束,则激活自动停靠
    if recongnizer.state == UIGestureRecognizerState.Ended {        if trueDistance > Common.screenWidth * (Proportion / 3) {
            showLeft()
        } else if trueDistance < Common.screenWidth * -(Proportion / 3) {
            showRight()
        } else {
            showHome()
        }        
        return
    }    // 计算缩放比例
    var proportion: CGFloat = recongnizer.view!.frame.origin.x >= 0 ? -1 : 1
    proportion *= trueDistance / Common.screenWidth
    proportion *= 1 - Proportion
    proportion /= FullDistance + Proportion/2 - 0.5
    proportion += 1
    if proportion <= Proportion { // 若比例已经达到最小,则不再继续动画
        return
    }    // 执行视差特效
    blackCover.alpha = (proportion - Proportion) / (1 - Proportion)    // 执行平移和缩放动画
    recongnizer.view!.center = CGPointMake(self.view.center.x + trueDistance, self.view.center.y)
    recongnizer.view!.transform = CGAffineTransformScale(CGAffineTransformIdentity, proportion, proportion)    
    // 执行左视图动画
    let pro = 0.8 + (proportionOfLeftView - 0.8) * trueProportion
    leftViewController.view.center = CGPointMake(centerOfLeftViewAtBeginning.x + distanceOfLeftView * trueProportion, centerOfLeftViewAtBeginning.y - (proportionOfLeftView - 1) * leftViewController.view.frame.height * trueProportion / 2 )
    leftViewController.view.transform = CGAffineTransformScale(CGAffineTransformIdentity, pro, pro)
}// 封装三个方法,便于后期调用// 展示左视图func showLeft() {    // 给首页 加入 点击自动关闭侧滑菜单功能
    mainView.addGestureRecognizer(tapGesture)    // 计算距离,执行菜单自动滑动动画
    distance = self.view.center.x * (FullDistance*2 + Proportion - 1)
    doTheAnimate(self.Proportion, showWhat: "left")
    homeNavigationController.popToRootViewControllerAnimated(true)
}// 展示主视图func showHome() {    // 从首页 删除 点击自动关闭侧滑菜单功能
    mainView.removeGestureRecognizer(tapGesture)    // 计算距离,执行菜单自动滑动动画
    distance = 0
    doTheAnimate(1, showWhat: "home")
}// 展示右视图func showRight() {    // 给首页 加入 点击自动关闭侧滑菜单功能
    mainView.addGestureRecognizer(tapGesture)    // 计算距离,执行菜单自动滑动动画
    distance = self.view.center.x * -(FullDistance*2 + Proportion - 1)
    doTheAnimate(self.Proportion, showWhat: "right")
}// 执行三种动画:显示左侧菜单、显示主页、显示右侧菜单func doTheAnimate(proportion: CGFloat, showWhat: String) {    UIView.animateWithDuration(0.3, delay: 0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { () -> Void in
        // 移动首页中心
        self.mainView.center = CGPointMake(self.view.center.x + self.distance, self.view.center.y)        // 缩放首页
        self.mainView.transform = CGAffineTransformScale(CGAffineTransformIdentity, proportion, proportion)        if showWhat == "left" {            // 移动左侧菜单的中心
            self.leftViewController.view.center = CGPointMake(self.centerOfLeftViewAtBeginning.x + self.distanceOfLeftView, self.leftViewController.view.center.y)            // 缩放左侧菜单
            self.leftViewController.view.transform = CGAffineTransformScale(CGAffineTransformIdentity, self.proportionOfLeftView, self.proportionOfLeftView)
        }        // 改变黑色遮罩层的透明度,实现视差效果
        self.blackCover.alpha = showWhat == "home" ? 1 : 0

        // 为了演示效果,在右侧菜单划出时隐藏漏出的左侧菜单,并无实际意义
        self.leftViewController.view.alpha = showWhat == "right" ? 0 : 1
        }, completion: nil)
}

}

import UIKit

// 侧滑菜单 View Controller
class LeftViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

let titlesDictionary = ["开通会员", "QQ钱包", "网上营业厅", "个性装扮", "我的收藏", "我的相册", "我的文件"]

@IBOutlet weak var settingTableView: UITableView!
@IBOutlet weak var avatarImageView: UIImageView!

@IBOutlet weak var heightLayoutConstraintOfSettingTableView: NSLayoutConstraint!

override func viewDidLoad() {    super.viewDidLoad()
    
    settingTableView.delegate = self
    settingTableView.dataSource = self
    settingTableView.tableFooterView = UIView()
    
    heightLayoutConstraintOfSettingTableView.constant = Common.screenHeight < 500 ? Common.screenHeight * (568 - 221) / 568 : 347
    self.view.frame = CGRectMake(0, 0, 320 * 0.78, Common.screenHeight)
}

override func didReceiveMemoryWarning() {    super.didReceiveMemoryWarning()    // Dispose of any resources that can be recreated.}// 处理点击事件func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let viewController = Common.rootViewController
    viewController.homeViewController.titleOfOtherPages = titlesDictionary[indexPath.row]
    viewController.homeViewController.performSegueWithIdentifier("showOtherPages", sender: self)
    Common.contactsVC.view.removeFromSuperview()
    viewController.mainTabBarController.tabBar.hidden = true
    viewController.mainTabBarController.selectedIndex = 0
    viewController.showHome()
    tableView.deselectRowAtIndexPath(indexPath, animated: false)
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {    return 7}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {    return 1}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("leftViewCell", forIndexPath: indexPath) 
    
    cell.backgroundColor = UIColor.clearColor()
    cell.textLabel!.text = titlesDictionary[indexPath.row]    
    return cell
}/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}
*/

}



作者:二月长河
链接:https://www.jianshu.com/p/11e6aedb75c5


0人推荐
随时随地看视频
慕课网APP