文档章节

QQ界面 抽屉效果

商永祥
 商永祥
发布于 2015/12/15 12:28
字数 1122
阅读 85
收藏 1
点赞 0
评论 0

闲来无事做的一个QQ界面的抽屉,简单地封装了调用的方法,拖到工程里面可以直接使用

方法是最底层的view是你的抽屉列表视图,需要将主页控制器的view直接加到抽屉控制器的view上面。当你侧滑或者是点击右上角按钮的时候,直接改变主页view的坐标系就可以。

在新建的ViewController中封装需要调用的方法

/**
 *  初始化抽屉视图和主页视图
 *
 *  @param
 */
- (instancetype)initWithLeftView:(UIViewController *)leftVC
                     andMainView:(UIViewController *)mainVC{
    self = [super init];
    if (self) {
        self.speedf = 0.7;
        self.leftVC = leftVC;
        self.mainVC = mainVC;
        
        // 滑动手势
        self.pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panGestureAction:)];
        [self.mainVC.view addGestureRecognizer:self.pan];
        
        [self.pan setCancelsTouchesInView:YES];
        self.pan.delegate = self;
        
        self.leftVC.view.hidden = YES;
        [self.view addSubview:self.leftVC.view];
        
        // 蒙版
        UIView * view = [[UIView alloc]initWithFrame:self.leftVC.view.bounds];
        view.backgroundColor = [UIColor blackColor];
        self.contentView = view;
        [self.leftVC.view addSubview:self.contentView];
        
        // 获取左侧TableView
        for (UIView * obj in self.leftVC.view.subviews) {
            if ([obj isKindOfClass:[UITableView class]]) {
                self.leftTableView = (UITableView *)obj;
            }
        }
        
        self.leftTableView.backgroundColor = [UIColor clearColor];
        self.leftTableView.frame = CGRectMake(0, 0, WIDTH - 100, HEIGHT);
        
        [self.view addSubview:self.mainVC.view];
        self.closed = YES;//初始时侧滑窗关闭
    }
    return self;
}

里面的leftVC就是列表的抽屉视图,mainVC就是主页视图。外部初始化一个控制器的时候直接调用这个方法就行。

然后就是在视图将要出现的时候让抽屉视图隐藏

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    self.leftVC.view.hidden = NO;
}

关闭抽屉视图

// 关闭视图
- (void)closeLeftView{
    [UIView beginAnimations:nil context:nil];
    self.mainVC.view.transform = CGAffineTransformScale(CGAffineTransformIdentity,1.0,1.0);
    self.mainVC.view.center = CGPointMake(WIDTH / 2, HEIGHT / 2);
    self.closed = YES;
    
    self.leftTableView.center = CGPointMake(30, HEIGHT * 0.5);
    self.leftTableView.transform = CGAffineTransformScale(CGAffineTransformIdentity,1,1);
    self.contentView.alpha = kLeftAlpha;
    
    [UIView commitAnimations];
}

打开抽屉视图

// 打开左视图
- (void)openLeftView{

    [UIView beginAnimations:nil context:nil];
    self.mainVC.view.transform = CGAffineTransformScale(CGAffineTransformIdentity,1,1);
    self.mainVC.view.center = kMainPageCenter;
    self.closed = NO;
    
    self.leftTableView.center = CGPointMake((WIDTH - 100) * 0.5, HEIGHT * 0.5);
    self.leftTableView.transform = CGAffineTransformScale(CGAffineTransformIdentity,1.0,1.0);
    self.contentView.alpha = 0;
    
    [UIView commitAnimations];
    // [self disableTapButton];
}

设置滑动开关 这里是要让手势不冲突 因为在抽屉视图显现的时候需要将手势关掉

/**
 *  设置滑动开关是否开启
 *
 *  @param enabled YES:支持滑动手势,NO:不支持滑动手势
 */
- (void)setPanEnabled: (BOOL) enabled{

    [self.pan setEnabled:enabled];

}

单击手势

#pragma mark - 单击手势
-(void)handeTap:(UITapGestureRecognizer *)tap{
    
    if ((!self.closed) && (tap.state == UIGestureRecognizerStateEnded))
    {
        [UIView beginAnimations:nil context:nil];
        tap.view.transform = CGAffineTransformScale(CGAffineTransformIdentity,1.0,1.0);
        tap.view.center = CGPointMake([UIScreen mainScreen].bounds.size.width/2,[UIScreen mainScreen].bounds.size.height/2);
        self.closed = YES;
        
        self.leftTableView.center = CGPointMake(30, HEIGHT * 0.5);
        self.leftTableView.transform = CGAffineTransformScale(CGAffineTransformIdentity,0.7,0.7);
        self.contentView.alpha = kLeftAlpha;
        
        [UIView commitAnimations];
        _scalef = 0;
        // [self removeSingleTap];
    }
    
}

下面就是UIPanGestureRecognizer手势的实现方法 里面是将视图的改变封装了起来

// 手势触发事件
- (void)panGestureAction:(UIPanGestureRecognizer *)panAction{

    CGPoint point = [panAction translationInView:self.view];
    _scalef = (point.x * self.speedf + _scalef);

    BOOL needMoveWithTap = YES; // 是否跟随手势移动
    if (((self.mainVC.view.frame.origin.x <= 0) && (_scalef <= 0)) || ((self.mainVC.view.frame.origin.x >= (WIDTH - 100 )) && (_scalef >= 0))) {
        //
        _scalef = 0;
        needMoveWithTap = NO;
    }
    
    // 根据视图位置判断是左滑还是右滑
    if (needMoveWithTap && (panAction.view.frame.origin.x >= 0) && (panAction.view.frame.origin.x <= (WIDTH - 100))) {
        CGFloat panCenterX = panAction.view.center.x + point.x * self.speedf;
        if (panCenterX < WIDTH * 0.5 - 2) {
            panCenterX = WIDTH * 0.5;
        }
        CGFloat panCenterY = panAction.view.center.y;
        panAction.view.center = CGPointMake(panCenterX, panCenterY);
        
        // scale
        CGFloat scale = 1;
        panAction.view.transform = CGAffineTransformScale(CGAffineTransformIdentity, scale, scale);
        [panAction setTranslation:CGPointMake(0, 0) inView:self.view];
        CGFloat leftTabCenterX = 30 + ((WIDTH - 100) * 0.5 - 30) * (panAction.view.frame.origin.x / (WIDTH - 100));
        NSLog(@"%f",leftTabCenterX);
        
        // leftScale
        CGFloat leftScale = 0.7 + (1 - 0.7) * (panAction.view.frame.origin.x / (WIDTH - 100));
        
        self.leftTableView.center = CGPointMake(leftTabCenterX, HEIGHT * 0.5);
        self.leftTableView.transform = CGAffineTransformScale(CGAffineTransformIdentity, leftScale,leftScale);
        
        //tempAlpha kLeftAlpha~0
        CGFloat tempAlpha = kLeftAlpha - kLeftAlpha * (panAction.view.frame.origin.x / (WIDTH - 100));
        self.contentView.alpha = tempAlpha;

    }else{
        //超出范围,
        if (self.mainVC.view.frame.origin.x < 0){
            [self closeLeftView];
            _scalef = 0;
        }
        else if (self.mainVC.view.frame.origin.x > (WIDTH - 100)){
            [self openLeftView];
            _scalef = 0;
        }
    }
    //手势结束后修正位置,超过约一半时向多出的一半偏移
    if (panAction.state == UIGestureRecognizerStateEnded) {
        if (fabs(_scalef) > vCouldChangeDeckStateDistance)
        {
            if (self.closed)
            {
                [self openLeftView];
            }
            else
            {
                [self closeLeftView];
            }
        }
        else
        {
            if (self.closed)
            {
                [self closeLeftView];
            }
            else
            {
                [self openLeftView];
            }
        }
        _scalef = 0;
    }
}

Delegate的实现方法

#pragma mark - Delegate
-(BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer shouldReceiveTouch:(UITouch*)touch {
    
    if(touch.view.tag == vDeckCanNotPanViewTag)
    {
        //        NSLog(@"不响应侧滑");
        return NO;
    }
    else
    {
        //        NSLog(@"响应侧滑");
        return YES;
    }
}

下面是我用到一些宏定义

#define WIDTH [UIScreen mainScreen].bounds.size.width
#define HEIGHT [UIScreen mainScreen].bounds.size.height
#define SIZE [UIScreen mainScreen].bounds.size
#define vCouldChangeDeckStateDistance  (WIDTH - 100) / 2.0 - 40 //滑动距离大于此数时,状态改变(关--》开,或者开--》关)
#define kMainPageCenter  CGPointMake(WIDTH + WIDTH * 1 / 2.0 - 100, HEIGHT / 2)  //打开左侧窗时,中视图中心点
#define vDeckCanNotPanViewTag    20000 // 不响应此侧滑的View的tag

#define kLeftAlpha 0.9  //左侧蒙版的最大值

最后外部调用的时候要在appDelegate中初始化

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window  = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
    [self.window makeKeyAndVisible];
    self.window.backgroundColor = [UIColor whiteColor];
    
    MainViewController * mainVC = [[MainViewController alloc]init];
    self.mainNC = [[RootNavigationController alloc]initWithRootViewController:mainVC];
    
    LeftSortViewController * leftSoutVC = [[LeftSortViewController alloc]init];
    UINavigationController * leftNC = [[UINavigationController alloc]initWithRootViewController:leftSoutVC];
    
    self.leftSlideVC = [[LeftSlideViewController alloc]initWithLeftView:leftNC andMainView:self.mainNC];
    self.leftSlideVC.title = @"抽屉视图";
    
    self.window.rootViewController = self.leftSlideVC;
    
    [[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"BackImage"] forBarMetrics:UIBarMetricsDefault];

    return YES;
}

创建两个视图去实现 还有一点就是在抽屉视图里面的点击方法 需要先调用隐藏的方法,然后push到需要跳转的页面,这里也可以不用push 。 让需要跳转界面的view直接替换掉mainVC的view。

这里是抽屉视图的点击方法

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    AppDelegate *tempAppDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    OtherViewController *vc = [[OtherViewController alloc] init];
    [tempAppDelegate.leftSlideVC closeLeftView];//关闭左侧抽屉
    
    [tempAppDelegate.mainNC pushViewController:vc animated:NO];
}


© 著作权归作者所有

共有 人打赏支持
商永祥
粉丝 0
博文 5
码字总数 3007
作品 0
济南
高仿QQ空间-更新篇

代码下载链接:http://pan.baidu.com/s/1i30F6Rz 更新内容 一 更新了登陆界面 二 增加了输入时密码时和登陆成功后播放音频的效果 三 增加了导航条渐隐的效果(和真实QQ空间的导航条一样,首先...

不孤独的美食家 ⋅ 2015/09/13 ⋅ 2

急事求教,关于抽提效果的问题!!

@晨曦之光 你好,想跟你请教个问题:我看到你的抽屉效果类似QQ好友列表的代码, 但是我把他加入到我的程序中之后不能够实现点开抽屉的效果呢!不知道能不能和你取得联系呢!谢谢了!!我的Q...

YCJ1314 ⋅ 2012/08/26 ⋅ 0

【Android进阶】多抽屉效果 (类似最早QQ使用的效果)

也不知道该怎么取名,暂且就叫他多抽屉效果吧~~ 最早QQ就是这样的效果,点一下,还有声音,呵呵。 一晃,都过去那么多年了... 废话不多说了,看下效果: 这个就是类似抽屉的效果,这边做了三...

晨曦之光 ⋅ 2012/03/01 ⋅ 4

android抽屉实现

今天在手机上实现了抽屉效果,其实很简单,但是效果却很酷。 首先在layout 下设置xml布局文件 <?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.andr...

晨曦之光 ⋅ 2012/03/13 ⋅ 0

iOS开发之抽屉效果实现

iOS开发之抽屉效果实现   说道抽屉效果在iOS中比较有名的第三方类库就是PPRevealSideViewController。一说到第三方类库就自然而然的想到我们的CocoaPods,今天的博客中用CocoaPods引入PPR...

SoulJa ⋅ 2015/07/07 ⋅ 0

盘点2014不容错过的UI源码

好的UI设计不仅是让软件变得有个性有品味,还要让软件的操作变得舒适、简单、自由、充分体现软件的定位和特点。有没有想要的效果还没有实现的,这里有现成的UI源码哦,需要的拿去。 QQ v4.7....

牵着蜗牛去西藏 ⋅ 2014/12/31 ⋅ 4

MMDrawerController左边抽屉push的三种情况

总结了大部分的界面 大概就如下三种情况: 打开左边抽屉,按钮后左边push到center控制器,这个控制器直接显示全部 (类似知乎日报) 思路:设置left的抽屉为center的nav并且关闭抽屉 打开左边抽...

文学振噢 ⋅ 01/04 ⋅ 0

Axure制作app侧面抽屉菜单

在之前的文章中以手机淘宝app的筛选菜单为例,给大家介绍过使用axure制作app侧面滑动菜单的方法,本文继续为大家介绍另外一种app的菜单样式——抽屉菜单。手机qq、酷狗音乐等app都采取了这种...

狄睿鑫老师 ⋅ 2017/04/06 ⋅ 0

Android 实现形态各异的双向侧滑菜单 自定义控件来袭

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/39670935,本文出自:【张鸿洋的博客】 1、概述 关于自定义控件侧滑已经写了两篇了 今天决定把之前的单向改成双向,当然...

lmj623565791 ⋅ 2014/10/08 ⋅ 0

iOS好用的第三方侧边栏控件——MMDrawerController

iOS好用的第三方侧边栏控件——MMDrawerController 一、引言 很多应用程序都采用了侧边栏这样的界面结构,MMDrawerController是一个轻量级的侧边栏抽屉控件,其支持左侧抽屉和右侧抽屉,可以...

珲少 ⋅ 2016/06/29 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Docker系列教程28-实战:使用Docker Compose运行ELK

原文:http://www.itmuch.com/docker/28-docker-compose-in-action-elk/,转载请说明出处。 ElasticSearch【存储】 Logtash【日志聚合器】 Kibana【界面】 答案: version: '2'services: ...

周立_ITMuch ⋅ 41分钟前 ⋅ 0

使用快嘉sdkg极速搭建接口模拟系统

在具体项目研发过程中,一旦前后端双方约定好接口,前端和app同事就会希望后台同事可以尽快提供可供对接的接口方便调试,而对后台同事来说定好接口还仅是个开始、设计流程,实现业务逻辑,编...

fastjrun ⋅ 今天 ⋅ 0

PXE/KickStart 无人值守安装

导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装。 常规的办法有什么? 光盘安装系统 ===> 一...

kangvcar ⋅ 昨天 ⋅ 0

使用Puppeteer撸一个爬虫

Puppeteer是什么 puppeteer是谷歌chrome团队官方开发的一个无界面(Headless)chrome工具。Chrome Headless将成为web应用自动化测试的行业标杆。所以我们很有必要来了解一下它。所谓的无头浏...

小草先森 ⋅ 昨天 ⋅ 0

Java Done Right

* 表示难度较大或理论性较强。 ** 表示难度更大或理论性更强。 【Java语言本身】 基础语法,面向对象,顺序编程,并发编程,网络编程,泛型,注解,lambda(Java8),module(Java9),var(...

风华神使 ⋅ 昨天 ⋅ 0

Linux系统日志

linux 系统日志 /var/log/messages /etc/logrotate.conf 日志切割配置文件 https://my.oschina.net/u/2000675/blog/908189 logrotate 使用详解 dmesg 命令 /var/log/dmesg 日志 last命令,调......

Linux学习笔记 ⋅ 昨天 ⋅ 0

MVC——统一报文格式的异常处理响应

在我们写controller层的时候,常常会有这样的困惑,如果需要返回一个数据是,可能为了统一回去构造一个类似下列的数据格式: { status:true, msg:"保存成功!", data:[]} 而且在写...

alexzhu592 ⋅ 昨天 ⋅ 0

[知乎]SSH框架

网上图书馆管理系统包括管理员管理和图书管理,图书借阅,查询模块等等,网上商城包括前台页面和后台管理页面,两个都是以前别人的实际项目,只是别人用的不是SSH,我把他们改用SSH了,除了S...

颖伙虫 ⋅ 昨天 ⋅ 0

android -------- 打开本地浏览器或指定浏览器加载,打电话,打开第三方app

开发中常常有打开本地浏览器加载url或者指定浏览器加载, 还有打开第三方app, 如 打开高德地图 百度地图等 在Android程序中我们可以通过发送隐式Intent来启动系统默认的浏览器。 如果手机本身...

切切歆语 ⋅ 昨天 ⋅ 0

linux 安装docker

通过以下命令下载安装docker wget -qO- https://get.docker.com | sh 执行以上命令后输出以下内容说明安装成功,注意红框中的内容,docker安装成功后默认只有root能使用,红框中给出的提示是...

haoyuehong ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部