类似QQ侧滑菜单功能实现
之前的那文章简单实现了菜单侧拉功能,但是做不到像QQ那样导航条和tabBar一起移动。。。之后在网上找资料,有了思路,就自个写了个demo试试水。
先创建QHLMainController控制器,并把它设置成app的根控制器。
在QHLMainController控制器中,懒加载添加一个tableView,并对tableView设置相对应的属性以及frame(frame的x设置为一个负值)!!添加一个tabBar控制器,并
为tabBar控制器添加4个子控制器(分别为first,two,three,four)!!!并对tabBar控制器的view的frame 添加一个KVO监听,监听当tabBar控制器 的view的frame的改
变,并执行相对应的代码。在tabBar控制器的第一个子控制器first控制器中,添加拖动手势,当拖动时候,根据拖动的偏移量来改变自身tabBar控制器的view的frame的
值。当偏移量达到最大的时候 给view添加点击手势,当点击时候,使view的frame变回初始值!!当frame变回初值的时候,移除点击手势。
在QHLMainController控制器中
- (void)viewDidLoad {
[super viewDidLoad];
//添加懒加载的tableView
[self.view addSubview:self.tableView];
//设置主界面
[self setUpMainUI];
}
/**
* 设置主界面
*/
- (void)setUpMainUI {
//创建tabBar控制器并添加到根控制器中
QHLTabBarController *tabVc = [[QHLTabBarController alloc] init];
self.tabVc = tabVc;
[self addChildViewController:tabVc];
[self.view addSubview:tabVc.view];
//对tabBar控制器view的frame属性添加一个监听
[tabVc.view addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
}
/**
* tabBar控制器view的frame属性的监听事件
*/
#define QHLViewControllerMaxOffsetX 250
#define QHLLeftViewOriginX -50
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
//计算偏移量
CGFloat offsetX =QHLLeftViewOriginX - QHLLeftViewOriginX * (self.tabVc.view.frame.origin.x) / QHLViewControllerMaxOffsetX;
//改变tableView的frame
CGRect frame = self.tableView.frame;
frame.origin.x = offsetX;
self.tableView.frame = frame;
}
tableView的懒加载和dataSource方法就不放上来了。
在tabBar控制器的子控制器first控制器中,先添加枚举型的结构体
typedef NS_ENUM(NSInteger, QHLViewControllerState) {
QHLViewControllerStateClosed = ,
QHLViewControllerStateOpening,
QHLViewControllerStateOpened,
QHLViewControllerStateClosing
};
首先在viewWillAppear:中添加拖动手势,并添加到当前view中,然后在viewWillDisappear:方法中把拖动手势移除掉。
在viewDidLoad方法中:
1.把自身的state状态设置成QHLViewControllerStateClosed
2.添加navigationItem的leftBarButtonItem:封装一个UIButton,设置相关的属性设置、一个背景色以及添加一个点击方法
点击方法如下:
/**
* leftItem的点击事件
*/
- (void)leftItemDidClick:(UIButton *)leftItem {
if (self.state == QHLViewControllerStateClosed) {
[self animatingOpen];
} else {
[self animatingClose];
}
}
拖动手势事件方法实现:
/**
* 拖动手势的实现方法
*/
- (void)panGestureRecognized:(UIPanGestureRecognizer *)panGestureRecognizer {
CGPoint location = [panGestureRecognizer translationInView:self.view]; //位置
CGRect frame = self.tabBarController.view.frame;
//获取当前拖动手势的状态
UIGestureRecognizerState state = panGestureRecognizer.state; switch (state) {
//拖动手势开始时候
case UIGestureRecognizerStateBegan:
self.beginLocation = location; //开始位置
if (self.state == QHLViewControllerStateClosed) { [self willOpen];
} else { [self willClose];
}
break;
//拖动手势进行中
case UIGestureRecognizerStateChanged:
{
CGFloat offsetX = ; //偏移量X //根据自身的state来设置不同的offsetX
if (self.state == QHLViewControllerStateOpening) { //正在打开
offsetX = location.x - self.beginLocation.x;
} else { //正在关闭
offsetX = QHLViewControllerMaxOffsetX - (self.beginLocation.x - location.x);
} if (offsetX >= QHLViewControllerMaxOffsetX) { //偏移量超过最大偏移值时
frame.origin.x = QHLViewControllerMaxOffsetX;
} else if (offsetX <= ) { //只有在关闭时候才会出现偏移量小于0的情况,而此种情况下,偏移量小于0,会使自身的x值小于0
frame.origin.x = ;
} else { //正在打开或者正在关闭
frame.origin.x = offsetX;
} //计算透明度
CGFloat alpha = - offsetX / QHLViewControllerMaxOffsetX;
self.leftItem.alpha = alpha; //设置导航条左侧item的透明度
self.tabBarController.view.frame = frame;
break;
}
//拖动手势结束时
case UIGestureRecognizerStateEnded:
if (self.state == QHLViewControllerStateOpening) { //正在打开
if (frame.origin.x >= QHLViewControllerMaxOffsetX / ) { //判断此时的偏移量
[self animatingOpen];
} else {
[self animatingClose];
} } else { //正在关闭
if (frame.origin.x >= QHLViewControllerMaxOffsetX / ) { //判断此时的偏移量
[self animatingOpen];
} else {
[self animatingClose];
}
}
break; default:
break;
}
}
点击手势事件方法实现:
- (void)tapGestureRecognized:(UITapGestureRecognizer *)tapGestureRecognizer {
//点击事件 自动缩回侧拉界面
[self animatingClose];
}
当tabBar控制器的view在偏移的时候,会调用下面的几个方法:
/**
* willOpen
*/
- (void)willOpen {
self.state = QHLViewControllerStateOpening;
} /**
* opened
*/
- (void)opened {
self.state = QHLViewControllerStateOpened; //设置点击手势
self.tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureRecognized:)];
[self.view addGestureRecognizer:self.tapGestureRecognizer];
} /**
* willClose
*/
- (void)willClose {
self.state = QHLViewControllerStateClosing;
} /**
* closed
*/
- (void)closed {
self.state = QHLViewControllerStateClosed;
[self.view removeGestureRecognizer:self.tapGestureRecognizer];
} /**
* 以动画形式打开
*/
- (void)animatingOpen {
[UIView animateWithDuration:0.5 delay: usingSpringWithDamping:1.0 initialSpringVelocity:0.7 options:UIViewAnimationOptionCurveLinear animations:^{
self.tabBarController.view.frame = CGRectMake(QHLViewControllerMaxOffsetX, , self.view.frame.size.width, self.view.frame.size.height); self.leftItem.alpha = ;
} completion:^(BOOL finished) {
[self opened];//改变自身的state状态以及移除点击手势
}];
} /**
* 以动画形式关闭
*/
- (void)animatingClose {
[UIView animateWithDuration:0.5 delay: usingSpringWithDamping:1.0 initialSpringVelocity:0.7 options:UIViewAnimationOptionCurveLinear animations:^{
self.tabBarController.view.frame = CGRectMake(, , self.view.frame.size.width, self.view.frame.size.height); self.leftItem.alpha = ;
} completion:^(BOOL finished) {
[self closed]; //改变自身的state状态以及添加点击手势
}];
}
模拟器测试了下,基本实现了和QQ左上角的导航条item点击触发的相类似的功能~。~
如果路过的大神有更好的实现方法求指导下!!!!
类似QQ侧滑菜单功能实现的更多相关文章
- 再造 “手机QQ” 侧滑菜单(三)——视图联动
代码示例:https://github.com/johnlui/SwiftSideslipLikeQQ 本 文中,我们将一起使用 UINavigationController 来管理主视图,并实现点击 ...
- 自定义控件?试试300行代码实现QQ侧滑菜单
Android自定义控件并没有什么捷径可走,需要不断得模仿练习才能出师.这其中进行模仿练习的demo的选择是至关重要的,最优选择莫过于官方的控件了,但是官方控件动辄就是几千行代码往往可能容易让人望而却 ...
- iOS仿QQ侧滑菜单、登录按钮动画、仿斗鱼直播APP、城市选择器、自动布局等源码
iOS精选源码 QQ侧滑菜单,右滑菜单,QQ展开菜单,QQ好友分组 登录按钮 3分钟快捷创建高性能轮播图 ScrollView嵌套ScrolloView(UITableView .UICollecti ...
- 再造 “手机QQ” 侧滑菜单(一)——实现侧滑效果
本系列文章中,我们将尝试再造手机QQ的侧滑菜单,力争最大限度接近手Q的实际效果,并使用 Auto Layout 仿造左侧菜单,实现和主视图的联动. 代码示例:https://github.com/jo ...
- Swift实战-小QQ(第2章):QQ侧滑菜单
QQ侧滑实现架构:需要建立以下几个ViewController:1.XQBaseViewController 2.LeftViewController3.RightViewController4.Co ...
- 仿QQ侧滑菜单<大自然的搬运工-代码不是我的>
1.记录下效果图 2.二个工具类 package myapplication.com.myapplicationfortest.utils; import android.util.Log; /** ...
- 再造 “手机QQ” 侧滑菜单(二)——高仿左视图
代码示例:https://github.com/johnlui/SwiftSideslipLikeQQ 本篇文章中,我们将一起使用 Auto Layout 高仿手Q的左侧视图,力争达成从布局到动画的全 ...
- 实现“手机qq”侧滑菜单 -- 吴欧
基本数据采集 经过体验,手机QQ采用的应该是线性动画,即视图缩放比例等随手指在屏幕上滑动的距离以一次方程的形式变化. 提取基本数据,向右侧滑达到最大幅度时: 1. 右侧主视图左边界距离屏幕左边界的 ...
- 今日推荐(三)AndroidResideMenu类似QQ侧滑效果
效果图: DEMO 本代码即是DEMO,您可以下载后选择您喜欢的IDE运行.SDK版本建议使用4.0以上 Version Migration 从 v1.0, v1.1, v1.2, v1.3 升级到 ...
随机推荐
- DTO学习系列之AutoMapper(三)
本篇目录: Custom Type Converters-自定义类型转换器 Custom Value Resolvers-自定义值解析器 Null Substitution-空值替换 Containe ...
- 13 java 设计模式--单例模式
/** * 单例 */ public class JobSchedulerService { //防止类外部通过new实例化该类 private JobSchedulerService() { } / ...
- hdu 1262寻找素数对
Problem Description 哥德巴赫猜想大家都知道一点吧.我们现在不是想证明这个结论,而是想在程序语言内部能够表示的数集中,任意取出一个偶数,来寻找两个素数,使得其和等于该偶数. 做好了这 ...
- C#定义委托函数实现在别的窗体中操作主窗体中的SerialPort控件
1.在主窗体(含有serialPort的窗体)中 //先定义委托 public delegate void OpenPort(); public delegate void ClosePort(); ...
- C语言--位运算符
一.位运算符 1.按位与:& 1> 功能 * 只有对应的两个二进制位为1时,结果位才为1,否则为0 * 举例:10用二进制表示为1010, 7用二进制表示为0111.对两个数值进行&a ...
- Java学习笔记--多线程
rollenholt的博文:http://www.cnblogs.com/rollenholt/archive/2011/08/28/2156357.html 弹球例子: 0. 创建Bounce框架 ...
- 启动安卓模拟器报错 emulator: ERROR: x86_64 emulation currently requires hardware acceleration! CPU acceleration status:HAXM must be updated(version 1.1.1<6.0.1) 解决办法
启动安卓模拟器报错 emulator: ERROR: x86_64 emulation currently requires hardware acceleration! CPU accelerat ...
- 执行yiic webapp命令时报错:php.exe不是内部或外部命令,也不是可运行的程序
在执行 yiic webapp ../abc 命令时报错: “php.exe”不是内部或外部命令,也不是可运行的程序 或批处理文件. 这是因为yiic批处理程序找不到php.exe的执行路径引起的. ...
- hdu 3191 How Many Paths Are There
http://acm.hdu.edu.cn/showproblem.php?pid=3191 这道题求次短路经和路径数 #include <cstdio> #include <cst ...
- 25045操作标准子程序集41.C
/* ;程 序 最 后 修 改 时 间 0-4-3 23:43 ;软 件 标 题:25045操作标准子程序集41 ;软 件 说 明:25045 I2C 串行EEPROM 驱动 ;___________ ...