全球领先的IT技术网站 |首页 |Tags |网站地图

您现在正在浏览:首页 » 开发频道 » 移动开发 » IOS » 手机QQ” 侧滑菜单——高仿左视图

RSS订阅

手机QQ” 侧滑菜单——高仿左视图

摘要:本篇文章中,我们将一起使用 Auto Layout 高仿手Q的左侧视图,力争达成从布局到动画的全面类似。由于实现过程繁复,本文将主要讲述思路和心得体会,将不再大段大段地粘贴代码。

  仔细观察,在把主页往右拖动时,左侧菜单有一个平移和放大的结合动画,并且有一层黑色遮罩层,透明度在不断变化,如下图:

开始仿制

 

弄明白手Q的实现细节之后,我们就开始着手实现界面及功能了。

 

使用 StoryBoard 构造左视图

 

在 StoryBoard 中新增一个 View Controller,并新增一个名为 LeftViewController 的 UIViewController 类,并在 StoryBoard 中完成绑定。然后搭建出左视图的界面,并使用 Auto Layout 进行完全约束。

 

注:

 

  • 不熟悉 Auto Layout 的同学可以阅读《Auto Layout 使用心得》系列文章。

  • 在普通 UIViewController 中使用 UITableView 的方法请看:《如何在普通 UIViewController 中使用 UITableView》

 

 

效果图如下:

上图中我为了能够显示出白色的字把 LeftViewController 主 view 的背景调成了绿色,默认使用 Default 即可(透明色)。

 

取出左视图并增加遮罩层

 

代码:https://github.com/johnlui/SwiftSideslipLikeQQ/blob/master/SwiftSideslipLikeQQ/ViewController.swift#L34-L50

 

这里有一点心得体会:为了保证 LeftViewController 中各类事件的正常相应,需要给 ViewController 增加成员变量(对象):

 

var leftViewController: LeftViewController!

 

动画效果:

大家都期待编译的代码吧:代码有点繁多。我会提供给到各位。

源代码:

//
  // ViewController.swift
  // SwiftSideslipLikeQQ
  //
  // Created by JohnLui on 15/4/10.
  // Copyright (c) 2015年 com.lvwenhan. All rights reserved.
  //
   
  import UIKit
   
  class ViewController: UIViewController {
   
  var mainTabBarController: MainTabBarController!
  var tapGesture: UITapGestureRecognizer!
   
  var homeNavigationController: UINavigationController!
  var homeViewController: HomeViewController!
  var leftViewController: LeftViewController!
  var mainView: UIView! // 构造主视图。实现 UINavigationController.view 和 HomeViewController.view 一起缩放。
  var distance: CGFloat = 0
   
  let FullDistance: CGFloat = 0.78
  let Proportion: CGFloat = 0.77
   
  var blackCover: UIView!
   
  var centerOfLeftViewAtBeginning: CGPoint!
  var proportionOfLeftView: CGFloat = 1
  var distanceOfLeftView: CGFloat = 50
   
  override func viewDidLoad() {
  super.viewDidLoad()
   
  // 给主视图设置背景
  let imageView = UIImageView(image: UIImage(named: "back"))
  imageView.frame = UIScreen.mainScreen().bounds
  self.view.addSubview(imageView)
   
  // 通过 StoryBoard 取出 LeftViewController
  leftViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("LeftViewController") as! LeftViewController
  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)
   
  // 通过 StoryBoard 取出 HomeViewController 的 view,放在背景视图上面
  mainView = UIView(frame: self.view.frame)
   
  let nibContents = NSBundle.mainBundle().loadNibNamed("MainTabBarController", owner: nil, options: nil)
  mainTabBarController = nibContents.first as! MainTabBarController
   
  let tabBarView = mainTabBarController.view
  mainView.addSubview(tabBarView)
   
  homeNavigationController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("HomeNavigationController") as! UINavigationController
  homeViewController = homeNavigationController.viewControllers.first as! HomeViewController
  tabBarView.addSubview(homeViewController.navigationController!.view)
  tabBarView.addSubview(homeViewController.view)
   
  tabBarView.bringSubviewToFront(mainTabBarController.tabBar)
   
  self.view.addSubview(mainView)
   
  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)
  }
   
  }

0 »

开发专题

JavaScript成为网络霸主的“绯闻”
JavaScript成为网络霸主的“绯闻”

JavaScript正凭借新型工具与功能提升以极度夸张的速度吞噬整个世界。我们是否应该接受这一无法逆转的趋势? 还记得那些旧日往事吗?很多用户因为担心安全问题而在浏览器中禁用JavaScript。如...

C++是垃圾语言?!
C++是垃圾语言?!

Linux之父对C++进行了炮轰,说它是糟糕程序员的垃圾语言,可谓是一石激起千层浪,引起众多程序员朋友的关注和讨论。本专题给出正反方的讨论观点,供大家评说!另外,给出了编程语言的发展状况...

MySQL数据库入门与精通
MySQL数据库入门与精通

MySQL是一个跨平台的开源关系型数据库管理系统,目前MySQL被广泛地应用在Internet上的中小型网站中。由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,许多中小型网站为了降低...

最新资讯