再造 “手机QQ” 侧滑菜单(三)——视图联动

2015-4-12   /   阅读数:14796   /   分类: iOS & Swift

代码示例:https://github.com/johnlui/SwiftSideslipLikeQQ

本文中,我们将一起使用 UINavigationController 来管理主视图,并实现点击左视图中菜单时,主视图自动联动的功能。本文是本系列文章的终结篇,也是最有难度的一篇,我已经为此编写了 10 小时的代码,前八小时一直在试错。毕竟我只是一个只有三个多月 iOS 开发经验的新手 (~ o ~)Y

给主视图装上 NavigationBar

给 HomeViewController 增加 UINavigationController 父视图

操作如下图:

Image

修改主视图载入逻辑

  1. 使用一个 UIView 对象将 homeViewController.navigationController!.view 和 homeViewController.view 包裹,再加入 self.view。
  2. 为了能取到带 navigationController 的 HomeViewController,需要先从 StoryBoard 取出 UINavigationController,再取其第一个 UIViewController 作为 HomeViewController。


代码如下:

mainView = UIView(frame: self.view.frame)
homeNavigationController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("HomeNavigationController") as! UINavigationController
homeViewController = homeNavigationController.viewControllers.first as! HomeViewController
mainView.addSubview(homeViewController.navigationController!.view)
mainView.addSubview(homeViewController.view)
self.view.addSubview(mainView)

tips: homeNavigationController 也要设置成 ViewController 的成员变量,这样才能在这种特殊架构下实现对 HomeViewController 的 navigationController 的操作。

给 mainView 赋予拖动手势事件

// 绑定 UIPanGestureRecognizer
let panGesture = homeViewController.panGesture
panGesture.addTarget(self, action: Selector("pan:"))
mainView.addGestureRecognizer(panGesture)

修改自动归位动画

修改 doTheAnimate 函数中的 homeViewController.view 为 mainView:

self.mainView.center = CGPointMake(self.view.center.x + self.distance, self.view.center.y)
self.mainView.transform = CGAffineTransformScale(CGAffineTransformIdentity, proportion, proportion)

得益于之前良好的封装,安装 NavigationBar 的工作已经完成

实现联动

建立 HomeViewController 的子视图控制器

拖放一个 View Controller,并新建一个 OtherPageViewController: UIViewController 类,将两者绑定:

Image

使用 segue 连接 HomeViewController 和 OtherPageViewController

Image

在 LeftViewController 中相应单击事件,实现联动!

修改 LeftViewController 中的 didSelectRowAtIndexPath 方法:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let viewController = UIApplication.sharedApplication().keyWindow?.rootViewController as! ViewController

    viewController.homeViewController.titleOfOtherPages = titlesDictionary[indexPath.row]
    viewController.homeViewController.performSegueWithIdentifier("showOtherPages", sender: self)
    
    viewController.showHome()
    
    tableView.deselectRowAtIndexPath(indexPath, animated: false)
}

修改 HomeViewController,传递数据

import UIKit

class HomeViewController: UIViewController {
    
    var titleOfOtherPages = ""

    @IBOutlet var panGesture: UIPanGestureRecognizer!
    override func viewDidLoad() {
        super.viewDidLoad()
    }

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

    
    // 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?) {
        if segue.identifier == "showOtherPages" {
            if let a = segue.destinationViewController as? OtherPageViewController {
                a.PageTitle = titleOfOtherPages
            }
        }
    }

}

视图联动已经实现!

收尾工作

主要功能实现了以后,我们还要做一些收尾工作,如首页的 segmentView、各种用户友好的单击事件等。

设置 segmentView

在 HomeViewController 内:

// 设置中间 segmentView 视图
let segmentView = UISegmentedControl(items: ["消息", "电话"])
segmentView.selectedSegmentIndex = 0
segmentView.setWidth(60, forSegmentAtIndex: 0)
segmentView.setWidth(60, forSegmentAtIndex: 1)
self.navigationItem.titleView = segmentView

给 NavigationBar 的左侧头像和右侧星星增加单击打开左、右视图的功能

直接从 Xcode 右下角拖放图片资源到相应的位置即可完成图片设置,之后在 ViewController 的合适位置增加下面两行代码:

homeViewController.navigationItem.leftBarButtonItem?.action = Selector("showLeft")
homeViewController.navigationItem.rightBarButtonItem?.action = Selector("showRight")

给主视图增加点击会主视图功能:

在 ViewController 的合适位置增加以下代码:

// 绑定单击收起菜单
let tapGesture = UITapGestureRecognizer(target: self, action: "showHome")
mainView.addGestureRecognizer(tapGesture)

修正 OtherPageViewController 中返回按钮不能正常相应的问题

override func viewDidLoad() {
    super.viewDidLoad()

    self.title = PageTitle
    mainLabel.text = PageTitle

    // 自定义返回按钮
    let backButton = UIBarButtonItem(title: "く返回", style: UIBarButtonItemStyle.Plain, target: self, action: "goBack")
    self.navigationItem.leftBarButtonItem = backButton
    
    // 弥补因为返回按钮被替换导致的边缘滑入手势失效的问题
    let gesture = UIPanGestureRecognizer(target: self, action: "goBack")
    self.view.addGestureRecognizer(gesture)
}

func goBack() {
    self.navigationController?.popViewControllerAnimated(true)
}

查看效果

Image

《再造 “手机QQ” 侧滑菜单》系列文章到此结束,谢谢大家!

WRITTEN BY

avatar

评论:

盗跖
2016-01-20 16:24
博主 问下 我如果在homeVC 中放 tableview datasource delegate 设为 homeVC  为啥 homeVC中的点击 并不能接收到 但是 homeVC可以布局tableview
盗跖
2016-01-16 11:32
你好,我设置mainview 添加 home 的navcontroller 的view 以后 navcontroller 并没有跟着homeVC 走啊
kissingsky
2015-12-29 16:44
视图联动可以用代理来实现,获取根视图怎么也感觉有点危险
我是一只羊
2015-11-14 12:02
大神,我想问问,为啥我的左视图背景甚至没有效果,看了半天没发现问题
龙龙
2015-11-10 19:09
按照楼主的方法好难啊,直接用Container View解决问题
mungo
2015-10-24 17:37
当Home页push出新页面 .在新页面也能侧滑出菜单.这个该怎么解决?
mungo
2015-10-24 11:37
原因是我只保留左边侧滑菜单
mungo
2015-10-24 11:20
使用panGesture只能应对慢速的手势,手势若很快,会卡住.若使用swipeGesture则不能使用拖动效果.不知道怎么解决呢
章鱼卷
2015-09-29 18:32
搂主的这个真的超级棒的   32赞 如果我切换到“电话”这个界面,不想左划出现左边的界面,应该怎么改进?
JohnLui
2015-09-29 18:36
@章鱼卷:临时禁用左滑手势就可以了。
hhkk
2015-09-16 11:58
求OC版。加上UITabBarController。
lk
2015-08-29 11:14
您好请问segmentView如何做视图切换呢 我现在想做qq那样的视图切换 发现切换不了...
蓝色海豚音
2015-07-13 11:53
楼主棒棒哒!
初学 swift. 通过这个直接加深了我对 View subview 以及 Navigation 的理解。
よう
2015-07-02 15:13
您好 非常荣幸看到了您的文章,我刚刚接触swift 最近的工作就是做菜单侧滑。 希望多多指教,
spadeking
2015-06-12 11:13
不错的学习资料,请问怎么使用图片定制uinavigationbar的背景
JohnLui
2015-06-12 11:16
@spadeking:没做过o(╯□╰)o
holylight
2015-07-17 14:34
@spadeking:不是有个 setbackgroudimage么。
谢谢分享
2015-05-27 17:07
谢谢分享
main
2015-04-13 18:09
厉害厉害。
lion
2015-04-13 16:34
能不能搞个OC版的啊。。。。
群友
2015-04-13 09:07
特定来支持你一下,不错学习了
JohnLui
2015-04-13 09:51
@群友:谢谢
yy
2015-05-10 10:48
@JohnLui:求OC版

发表评论:

© 2011-2019 岁寒  |  Powered by Emlog