类似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 升级到 ...
随机推荐
- C#类型基础——学习笔记一
1.C#中的类型一共分两类,一类是值类型,一类是引用类型.2.结构类型变量本身就相当于一个实例.3.调用结构上的方法前,需要对其所有的字段进行赋值.4.所有元素使用前都必须初始化.5.(结构类型)ne ...
- c#类似单片机的8bit或运算
1.正确 PWMSUBM0 &= (byte)(PWMSUBM0 | 0xfc); PWMSUBM0 &= (byte)(PWMSUBM0 | (byte)0xfc); 2.不能编译的 ...
- javaWeb--jsp & jQuery
jsp页面的基本构成:指令标签HTML标记语言注释 <!-- html注释 --> <%-- java代码注释 --> //html注释对jsp嵌入的代码不起作用,因 ...
- php json_encode数据格式化2种格式[]和{}
在php中,json格式化数据后,会出现2种形式数据: 1.当array是一个从0开始的连续数组时,json_encode的结果是一个由[]括起来的字符串 $arr = array('a' , 'b' ...
- Django的 select_related 和 prefetch_related 函数对 QuerySet 查询的优化(三)
4.一些实例 如果我们想要获得所有家乡是湖北的人,最无脑的做法是先获得湖北省,再获得湖北的所有城市,最后获得故乡是这个城市的人.就像这样: 1 2 3 4 5 >>> hb = Pr ...
- 关于Fragment与Activity的想法
View,Fragment,Activity,ListView等都会涉及到Layout文件 不要从Layout来考虑,而是从Activity,Fragment,来考虑,Layout只是他们的一个属性 ...
- JS 浮点计算BUG
最近做项目的时候遇到一个比较纠结的js浮点计算问题. 当时是做利率计算,因为利率大多数涉及到小数点,精度要求也很高. 0.6+0.1+0.1=? 结果出现:0.7999999999999 网上查找了一 ...
- 如何成为一个牛逼的C/C++程序员?
这个题目的噱头太大,要真的写起来, 足够写一本书了. 本人是过来人, 结合自身的体会和大家交流一下,希望新人能少走弯路. 每个人的情况不一样,我下面的描述可能并不适合每一个看到这篇文章的人. 一.C/ ...
- Socket,非阻塞,fcntl
一.fcntl 用以下方法将socket设置成为非阻塞方式 int flags = fcntl(socket,F_GETFL,0); fcntl(socket,F_SETFL,flags|O_NON ...
- linux下的守护进程及会话、进程组
守护进程.会话.进程组网上有许多不错的资料.我也是网上搜罗了一堆,加上自己的理解.不敢说原创,只是写在这怕自己忘记罢了.才疏学浅,难免有错误,欢迎大家指正.下面这篇写很不错,大家可以去看看:http: ...