QQ界面 抽屉效果
QQ界面 抽屉效果
商永祥 发表于2年前
QQ界面 抽屉效果
  • 发表于 2年前
  • 阅读 81
  • 收藏 1
  • 点赞 0
  • 评论 0

腾讯云 新注册用户 域名抢购1元起>>>   

摘要: 封装的抽屉效果方法 简单的做了一个QQ抽屉效果

闲来无事做的一个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
×
商永祥
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: