实现IOS版的抽屉效果(点击,拖拽滑动)

本文详细介绍了如何在Android中实现滑动抽屉效果,包括使用SlidingDrawer的便捷方式,以及通过纯UIView操作实现的原理和步骤。文中提供了自定义组件DrawerView的源代码,涵盖手势识别、状态切换及动画效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

好像最近,看到好多Android上的抽屉效果,也忍不住想要自己写一个。在Android里面可以用SlidingDrawer,很方便的实现。IOS上面就只有自己写了。其实原理很简单就是 UIView 的移动,和一些手势的操作。


  1. // 
  2. //  DrawerView.h 
  3. //  DrawerDemo 
  4. // 
  5. //  Created by Zhouhaifeng on 12-3-27. 
  6. //  Copyright (c) 2012年 CJLU. All rights reserved. 
  7. // 
  8.  
  9. #import <UIKit/UIKit.h> 
  10.  
  11. typedef enum 
  12.     DrawerViewStateUp = 0, 
  13.     DrawerViewStateDown 
  14. }DrawerViewState; 
  15.  
  16. @interface DrawerView : UIView<UIGestureRecognizerDelegate> 
  17.     UIImageView *arrow;         //向上拖拽时显示的图片     
  18.   
  19.     CGPoint upPoint;            //抽屉拉出时的中心点 
  20.     CGPoint downPoint;          //抽屉收缩时的中心点 
  21.      
  22.     UIView *parentView;         //抽屉所在的view 
  23.     UIView *contentView;        //抽屉里面显示的内容 
  24.      
  25.     DrawerViewState drawState;  //当前抽屉状态 
  26.  
  27. - (id)initWithView:(UIView *) contentview parentView :(UIView *) parentview; 
  28. - (void)handlePan:(UIPanGestureRecognizer *)recognizer; 
  29. - (void)handleTap:(UITapGestureRecognizer *)recognizer; 
  30. - (void)transformArrow:(DrawerViewState) state; 
  31.  
  32. @property (nonatomic,retain) UIView *parentView; 
  33. @property (nonatomic,retain) UIView *contentView; 
  34. @property (nonatomic,retain) UIImageView *arrow;   
  35. @property (nonatomic) DrawerViewState drawState;  
  36.  
  37. @end 
//
//  DrawerView.h
//  DrawerDemo
//
//  Created by Zhouhaifeng on 12-3-27.
//  Copyright (c) 2012年 CJLU. All rights reserved.
//

#import <UIKit/UIKit.h>

typedef enum
{
    DrawerViewStateUp = 0,
    DrawerViewStateDown
}DrawerViewState;

@interface DrawerView : UIView<UIGestureRecognizerDelegate>
{
    UIImageView *arrow;         //向上拖拽时显示的图片    
 
    CGPoint upPoint;            //抽屉拉出时的中心点
    CGPoint downPoint;          //抽屉收缩时的中心点
    
    UIView *parentView;         //抽屉所在的view
    UIView *contentView;        //抽屉里面显示的内容
    
    DrawerViewState drawState;  //当前抽屉状态
}

- (id)initWithView:(UIView *) contentview parentView :(UIView *) parentview;
- (void)handlePan:(UIPanGestureRecognizer *)recognizer;
- (void)handleTap:(UITapGestureRecognizer *)recognizer;
- (void)transformArrow:(DrawerViewState) state;

@property (nonatomic,retain) UIView *parentView;
@property (nonatomic,retain) UIView *contentView;
@property (nonatomic,retain) UIImageView *arrow;  
@property (nonatomic) DrawerViewState drawState; 

@end

  1. // 
  2. //  DrawerView.m 
  3. //  DrawerDemo 
  4. // 
  5. //  Created by Zhouhaifeng on 12-3-27. 
  6. //  Copyright (c) 2012年 CJLU. All rights reserved. 
  7. // 
  8.  
  9. #import "DrawerView.h" 
  10.  
  11. @implementation DrawerView 
  12. @synthesize contentView,parentView,drawState; 
  13. @synthesize arrow; 
  14.  
  15. - (id)initWithView:(UIView *) contentview parentView :(UIView *) parentview; 
  16.     self = [super initWithFrame:CGRectMake(0,0,contentview.frame.size.width, contentview.frame.size.height+40)]; 
  17.     if (self) { 
  18.         // Initialization code         
  19.         contentView = contentview; 
  20.         parentView = parentview; 
  21.          
  22.         //一定要开启 
  23.         [parentView setUserInteractionEnabled:YES]; 
  24.          
  25.         //嵌入内容区域的背景 
  26.         UIImage *drawer_bg = [UIImage imageNamed:@"drawer_content.png"]; 
  27.         UIImageView *view_bg = [[UIImageView alloc]initWithImage:drawer_bg]; 
  28.         [view_bg setFrame:CGRectMake(0,40,contentview.frame.size.width, contentview.bounds.size.height+40)]; 
  29.         [self addSubview:view_bg]; 
  30.      
  31.         //头部拉拽的区域背景 
  32.         UIImage *drawer_handle = [UIImage imageNamed:@"drawer_handlepng.png"]; 
  33.         UIImageView *view_handle = [[UIImageView alloc]initWithImage:drawer_handle]; 
  34.         [view_handle setFrame:CGRectMake(0,0,contentview.frame.size.width,40)]; 
  35.         [self addSubview:view_handle]; 
  36.          
  37.         //箭头的图片 
  38.         UIImage *drawer_arrow = [UIImage imageNamed:@"drawer_arrow.png"]; 
  39.         arrow = [[UIImageView alloc]initWithImage:drawer_arrow]; 
  40.         [arrow setFrame:CGRectMake(0,0,28,28)]; 
  41.         arrow.center = CGPointMake(contentview.frame.size.width/2, 20); 
  42.         [self addSubview:arrow]; 
  43.          
  44.         //嵌入内容的UIView 
  45.         [contentView setFrame:CGRectMake(0,40,contentview.frame.size.width, contentview.bounds.size.height+40)]; 
  46.         [self addSubview:contentview]; 
  47.          
  48.         //移动的手势 
  49.         UIPanGestureRecognizer *panRcognize=[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];   
  50.         panRcognize.delegate=self;   
  51.         [panRcognize setEnabled:YES];   
  52.         [panRcognize delaysTouchesEnded];   
  53.         [panRcognize cancelsTouchesInView];  
  54.          
  55.         [self addGestureRecognizer:panRcognize]; 
  56.          
  57.         //单击的手势 
  58.         UITapGestureRecognizer *tapRecognize = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleTap:)];   
  59.         tapRecognize.numberOfTapsRequired = 1;   
  60.         tapRecognize.delegate = self;   
  61.         [tapRecognize setEnabled :YES];   
  62.         [tapRecognize delaysTouchesBegan];   
  63.         [tapRecognize cancelsTouchesInView];   
  64.          
  65.         [self addGestureRecognizer:tapRecognize]; 
  66.          
  67.         //设置两个位置的坐标 
  68.         downPoint = CGPointMake(parentview.frame.size.width/2, parentview.frame.size.height+contentview.frame.size.height/2-40); 
  69.         upPoint = CGPointMake(parentview.frame.size.width/2, parentview.frame.size.height-contentview.frame.size.height/2-40); 
  70.         self.center =  downPoint; 
  71.          
  72.         //设置起始状态 
  73.         drawState = DrawerViewStateDown; 
  74.     } 
  75.     return self; 
  76.  
  77.  
  78. #pragma UIGestureRecognizer Handles   
  79. /*   
  80. *  移动图片处理的函数
  81. *  @recognizer 移动手势
  82. */   
  83. - (void)handlePan:(UIPanGestureRecognizer *)recognizer {   
  84.      
  85.     
  86.     CGPoint translation = [recognizer translationInView:parentView];  
  87.     if (self.center.y + translation.y < upPoint.y) { 
  88.         self.center = upPoint; 
  89.     }else if(self.center.y + translation.y > downPoint.y) 
  90.     { 
  91.         self.center = downPoint; 
  92.     }else
  93.         self.center = CGPointMake(self.center.x,self.center.y + translation.y);   
  94.     } 
  95.     [recognizer setTranslation:CGPointMake(0, 0) inView:parentView];   
  96.      
  97.     if (recognizer.state == UIGestureRecognizerStateEnded) {   
  98.         [UIView animateWithDuration:0.75 delay:0.15 options:UIViewAnimationOptionCurveEaseOut animations:^{   
  99.                 if (self.center.y < downPoint.y*4/5) { 
  100.                     self.center = upPoint; 
  101.                     [self transformArrow:DrawerViewStateUp]; 
  102.                 }else 
  103.                 { 
  104.                     self.center = downPoint; 
  105.                     [self transformArrow:DrawerViewStateDown]; 
  106.                 } 
  107.  
  108.         } completion:nil];   
  109.   
  110.     }     
  111. }   
  112.  
  113. /*
  114. *  handleTap 触摸函数
  115. *  @recognizer  UITapGestureRecognizer 触摸识别器
  116. */   
  117. -(void) handleTap:(UITapGestureRecognizer *)recognizer   
  118. {   
  119.         [UIView animateWithDuration:0.75 delay:0.15 options:UIViewAnimationOptionTransitionCurlUp animations:^{   
  120.             if (drawState == DrawerViewStateDown) { 
  121.                 self.center = upPoint; 
  122.                 [self transformArrow:DrawerViewStateUp]; 
  123.             }else 
  124.             { 
  125.                 self.center = downPoint; 
  126.                 [self transformArrow:DrawerViewStateDown]; 
  127.             } 
  128.         } completion:nil];   
  129.   
  130. }  
  131.  
  132. /*
  133. *  transformArrow 改变箭头方向
  134. *  state  DrawerViewState 抽屉当前状态
  135. */  
  136. -(void)transformArrow:(DrawerViewState) state 
  137.         //NSLog(@"DRAWERSTATE :%d  STATE:%d",drawState,state); 
  138.         [UIView animateWithDuration:0.3 delay:0.35 options:UIViewAnimationOptionCurveEaseOut animations:^{   
  139.            if (state == DrawerViewStateUp){    
  140.                     arrow.transform = CGAffineTransformMakeRotation(M_PI); 
  141.                 }else 
  142.                 { 
  143.                      arrow.transform = CGAffineTransformMakeRotation(0); 
  144.                 } 
  145.         } completion:^(BOOL finish){ 
  146.                drawState = state; 
  147.         }];   
  148.          
  149.     
  150.  
  151. @end 
//
//  DrawerView.m
//  DrawerDemo
//
//  Created by Zhouhaifeng on 12-3-27.
//  Copyright (c) 2012年 CJLU. All rights reserved.
//

#import "DrawerView.h"

@implementation DrawerView
@synthesize contentView,parentView,drawState;
@synthesize arrow;

- (id)initWithView:(UIView *) contentview parentView :(UIView *) parentview;
{
    self = [super initWithFrame:CGRectMake(0,0,contentview.frame.size.width, contentview.frame.size.height+40)];
    if (self) {
        // Initialization code        
        contentView = contentview;
        parentView = parentview;
        
        //一定要开启
        [parentView setUserInteractionEnabled:YES];
        
        //嵌入内容区域的背景
        UIImage *drawer_bg = [UIImage imageNamed:@"drawer_content.png"];
        UIImageView *view_bg = [[UIImageView alloc]initWithImage:drawer_bg];
        [view_bg setFrame:CGRectMake(0,40,contentview.frame.size.width, contentview.bounds.size.height+40)];
        [self addSubview:view_bg];
    
        //头部拉拽的区域背景
        UIImage *drawer_handle = [UIImage imageNamed:@"drawer_handlepng.png"];
        UIImageView *view_handle = [[UIImageView alloc]initWithImage:drawer_handle];
        [view_handle setFrame:CGRectMake(0,0,contentview.frame.size.width,40)];
        [self addSubview:view_handle];
        
        //箭头的图片
        UIImage *drawer_arrow = [UIImage imageNamed:@"drawer_arrow.png"];
        arrow = [[UIImageView alloc]initWithImage:drawer_arrow];
        [arrow setFrame:CGRectMake(0,0,28,28)];
        arrow.center = CGPointMake(contentview.frame.size.width/2, 20);
        [self addSubview:arrow];
        
        //嵌入内容的UIView
        [contentView setFrame:CGRectMake(0,40,contentview.frame.size.width, contentview.bounds.size.height+40)];
        [self addSubview:contentview];
        
        //移动的手势
        UIPanGestureRecognizer *panRcognize=[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];  
        panRcognize.delegate=self;  
        [panRcognize setEnabled:YES];  
        [panRcognize delaysTouchesEnded];  
        [panRcognize cancelsTouchesInView]; 
        
        [self addGestureRecognizer:panRcognize];
        
        //单击的手势
        UITapGestureRecognizer *tapRecognize = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleTap:)];  
        tapRecognize.numberOfTapsRequired = 1;  
        tapRecognize.delegate = self;  
        [tapRecognize setEnabled :YES];  
        [tapRecognize delaysTouchesBegan];  
        [tapRecognize cancelsTouchesInView];  
        
        [self addGestureRecognizer:tapRecognize];
        
        //设置两个位置的坐标
        downPoint = CGPointMake(parentview.frame.size.width/2, parentview.frame.size.height+contentview.frame.size.height/2-40);
        upPoint = CGPointMake(parentview.frame.size.width/2, parentview.frame.size.height-contentview.frame.size.height/2-40);
        self.center =  downPoint;
        
        //设置起始状态
        drawState = DrawerViewStateDown;
    }
    return self;
}


#pragma UIGestureRecognizer Handles  
/*    
 *  移动图片处理的函数 
 *  @recognizer 移动手势 
 */  
- (void)handlePan:(UIPanGestureRecognizer *)recognizer {  
    
   
    CGPoint translation = [recognizer translationInView:parentView]; 
    if (self.center.y + translation.y < upPoint.y) {
        self.center = upPoint;
    }else if(self.center.y + translation.y > downPoint.y)
    {
        self.center = downPoint;
    }else{
        self.center = CGPointMake(self.center.x,self.center.y + translation.y);  
    }
    [recognizer setTranslation:CGPointMake(0, 0) inView:parentView];  
    
    if (recognizer.state == UIGestureRecognizerStateEnded) {  
        [UIView animateWithDuration:0.75 delay:0.15 options:UIViewAnimationOptionCurveEaseOut animations:^{  
                if (self.center.y < downPoint.y*4/5) {
                    self.center = upPoint;
                    [self transformArrow:DrawerViewStateUp];
                }else
                {
                    self.center = downPoint;
                    [self transformArrow:DrawerViewStateDown];
                }

        } completion:nil];  
 
    }    
}  

/* 
 *  handleTap 触摸函数 
 *  @recognizer  UITapGestureRecognizer 触摸识别器 
 */  
-(void) handleTap:(UITapGestureRecognizer *)recognizer  
{  
        [UIView animateWithDuration:0.75 delay:0.15 options:UIViewAnimationOptionTransitionCurlUp animations:^{  
            if (drawState == DrawerViewStateDown) {
                self.center = upPoint;
                [self transformArrow:DrawerViewStateUp];
            }else
            {
                self.center = downPoint;
                [self transformArrow:DrawerViewStateDown];
            }
        } completion:nil];  
 
} 

/* 
 *  transformArrow 改变箭头方向
 *  state  DrawerViewState 抽屉当前状态 
 */ 
-(void)transformArrow:(DrawerViewState) state
{
        //NSLog(@"DRAWERSTATE :%d  STATE:%d",drawState,state);
        [UIView animateWithDuration:0.3 delay:0.35 options:UIViewAnimationOptionCurveEaseOut animations:^{  
           if (state == DrawerViewStateUp){   
                    arrow.transform = CGAffineTransformMakeRotation(M_PI);
                }else
                {
                     arrow.transform = CGAffineTransformMakeRotation(0);
                }
        } completion:^(BOOL finish){
               drawState = state;
        }];  
        
   
}

@end

这样就是实现了,图片是从360里面抠出来,处理的不是很好,大家见谅。

Demo的下载地址:http://download.youkuaiyun.com/detail/toss156/4177553

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值