HardBirch

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

时间:12-03-27 栏目:iOS游戏开发技术 作者:张飞不张,文采横飞 评论:9 点击: 5,074 次

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


//
//  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

//
//  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.csdn.net/detail/toss156/4177553

【IOS】实现IOS版的抽屉效果(点击,拖拽滑动):目前有9 条留言

  1. 9楼
    ck89757:

    怎么能让箭头默认在上边,然后是从上往下滑动,再点击,收缩回去

    2012-07-10 17:14 [回复]
  2. 8楼
    toss156:

    [reply]ck89757[/reply]
    修改下初始的位置和状态就可以了

    2012-07-12 19:47 [回复]
  3. 7楼
    ck89757:

    能不能指导一下,在哪里修改,谢谢了[reply]toss156[/reply]

    2012-07-17 09:31 [回复]
  4. 6楼
    toss156:

    [reply]ck89757[/reply]
    //设置两个位置的坐标
    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;
    上下两个位置的坐标调换一下,然后初始状态改一下

    2012-07-17 10:18 [回复]
  5. 5楼
    ck89757:

    这样我试了,这样只是吧初始化的位置放在了最上边,我的意思,你现在写这个是从下往上可以拖动,我的意思是默认是从下往上拖动,和你的这个刚刚是相反的。

    //设置两个位置的坐标
    upPoint = CGPointMake(parentview.frame.size.width/2, parentview.frame.size.height+contentview.frame.size.height/2-40);
    downPoint = CGPointMake(parentview.frame.size.width/2, parentview.frame.size.height-contentview.frame.size.height/2-40);
    self.center = downPoint;

    //设置起始状态
    drawState = DrawerViewStateUp;
    [reply]toss156[/reply]

    2012-07-17 11:27 [回复]
  6. 4楼
    toss156:

    [reply]ck89757[/reply]
    你的意思是 像android里面的上面状态栏一样,可以拉下来的那种?

    2012-07-17 12:18 [回复]
  7. 地板
    toss156:

    [reply]ck89757[/reply]
    http://download.csdn.net/detail/toss156/4433697 修改好的版本

    2012-07-17 12:51 [回复]
  8. 板凳
    ck89757:

    嗯,是你的这个效果,十分感谢![reply]toss156[/reply]

    2012-07-17 13:12 [回复]
  9. 沙发
    br_akasha:

    谢谢

    2012-08-21 14:58 [回复]

发表评论


QQ群互动

Linux系统与内核学习群:194051772

WP建站技术学习交流群:194062106

魔豆之路QR

魔豆的Linux内核之路

魔豆的Linux内核之路

优秀工程师当看优秀书籍

优秀程序员,要看优秀书!

赞助商广告

友荐云推荐