iOS侧滑菜单实现

这个是参照鸿洋的android侧滑菜单实现的,同样利用scrollview实现,很简单,这是鸿洋侧滑的实现链接打造最简单的自定义侧滑菜单

第一种测滑

#import <UIKit/UIKit.h>

@interface SlideMenu : UIScrollView
@property (nonatomic, assign) BOOL isMenuOpen;
/**设置菜单和内容*/
-(void)setMenuView:(UIView*)menuView withContentView:(UIView*)contentView;
/**关闭菜单*/
-(void)closeMenuWithAnimation:(BOOL)animated;
/**打开菜单*/
-(void)openMenuWithAnimaton:(BOOL)animated;
/**菜单打开与关闭切换*/
-(void)toggleMenu;
@end
#import "SlideMenu.h"
#define menu_ratio 0.7f

@interface SlideMenu()<UIScrollViewDelegate>
@end

@implementation SlideMenu
{
    float _menuWidth;
    UIView *_menuViewContainer;
    UIView *_contentViewContainer;
    UIView *_menuView;
    UIView *_contentView;
}

-(instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if(self)
    {
        [self setUp];
    }
    return self;
}

-(void)setUp
{
    _menuViewContainer = [UIView new];
    _contentViewContainer = [UIView new];
    [self addSubview:_menuViewContainer];
    [self addSubview:_contentViewContainer];
    self.delegate = self;
    //不显示滚动条
    self.showsHorizontalScrollIndicator = false;
    //不显示弹簧效果
    self.bounces = false;
    _isMenuOpen = true;

    if(!CGRectEqualToRect(self.frame, CGRectZero))
    {
        [self initFrame];
    }
}

-(void)setFrame:(CGRect)frame
{
    [super setFrame:frame];
    [self initFrame];
}

-(void)initFrame
{
    //放置菜单的位置
    _menuViewContainer.frame = CGRectMake(0, 0, self.frame.size.width * menu_ratio, self.frame.size.height);
    _menuWidth = _menuViewContainer.frame.size.width;

    //放置content的位置
    _contentViewContainer.frame = CGRectMake(CGRectGetMaxX(_menuViewContainer.frame), 0, self.frame.size.width, self.frame.size.height);
    //设置可滚动区域
    self.contentSize = CGSizeMake(_menuViewContainer.frame.size.width + _contentViewContainer.frame.size.width, 0);
    //初始关闭菜单
    [self closeMenuWithAnimation:false];

    if(_menuView != nil)
    {
        _menuView.frame = _menuViewContainer.bounds;
    }
    if(_contentView != nil)
    {
        _contentView.frame = _contentViewContainer.bounds;
    }
}

//设置菜单和内容
-(void)setMenuView:(UIView *)menuView withContentView:(UIView *)contentView
{
    //添加菜单
    if(_menuView != nil)
    {
        return;
    }
    _menuView = menuView;
    [_menuViewContainer addSubview:menuView];

    //添加内容
    if(_contentView != nil)
    {
        return;
    }
    _contentView = contentView;
    [_contentViewContainer addSubview:contentView];

    //设置实际菜单位置,填充菜单容器
    _menuView.frame = _menuViewContainer.bounds;
    //设置实际内容位置,填充内容容器
    _contentView.frame = _contentViewContainer.bounds;

}


//拖动松开时会调用,第二个参数表示拖动松开后是否会自动减速滑动
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    //判断应该显示菜单还是内容
    float offset = scrollView.contentOffset.x;
    if(decelerate)
    {
        //如果松开后自动减速滚动,什么也不做
        return;
    }
    if(offset > _menuWidth / 2.0f)
    {
        [self closeMenuWithAnimation:true];
    }
    else
    {
        [self openMenuWithAnimaton:true];
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    //判断应该显示菜单还是内容
    float offset = scrollView.contentOffset.x;

    if(offset > _menuWidth / 2.0f)
    {
        [self closeMenuWithAnimation:true];
    }
    else
    {
        [self openMenuWithAnimaton:true];
    }

}


//关闭菜单
-(void)closeMenuWithAnimation:(BOOL)animated
{
    _isMenuOpen = false;
    [self setContentOffset:CGPointMake(_menuWidth, 0) animated:animated];
}
//打开菜单
-(void)openMenuWithAnimaton:(BOOL)animated
{
    _isMenuOpen = true;
    [self setContentOffset:CGPointMake(0, 0) animated:animated];
}

//菜单切换
-(void)toggleMenu
{
    if(_isMenuOpen)
    {
        [self closeMenuWithAnimation:true];
    }
    else
    {
        [self openMenuWithAnimaton:true];
    }
}

第二种侧滑

#import <UIKit/UIKit.h>

@interface SlideMenu2 : UIScrollView
@property (nonatomic, assign) BOOL isMenuOpen;
/**设置菜单和内容*/
-(void)setMenuView:(UIView*)menuView withContentView:(UIView*)contentView;
/**关闭菜单*/
-(void)closeMenuWithAnimation:(BOOL)animated;
/**打开菜单*/
-(void)openMenuWithAnimaton:(BOOL)animated;
/**菜单打开与关闭切换*/
-(void)toggleMenu;
@end
#import "SlideMenu2.h"
#define menu_ratio 0.70f

@interface SlideMenu2()<UIScrollViewDelegate>
@end

@implementation SlideMenu2
{
    float _menuWidth;
    UIView *_menuViewContainer;
    UIView *_contentViewContainer;
    UIView *_menuView;
    UIView *_contentView;
}

-(instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if(self)
    {
        [self setUp];
    }
    return self;
}

-(void)setUp
{
    _menuViewContainer = [UIView new];
    _contentViewContainer = [UIView new];
    [self addSubview:_menuViewContainer];
    [self addSubview:_contentViewContainer];
    self.delegate = self;
    //不显示滚动条
    self.showsHorizontalScrollIndicator = false;
    //不显示弹簧效果
    self.bounces = false;
    _isMenuOpen = true;

    if(!CGRectEqualToRect(self.frame, CGRectZero))
    {
        [self initFrame];
    }
}

-(void)setFrame:(CGRect)frame
{
    [super setFrame:frame];
    [self initFrame];
}


-(void)initFrame
{
    //放置菜单的位置
    _menuViewContainer.frame = CGRectMake(0, 0, self.frame.size.width * menu_ratio, self.frame.size.height);
    _menuWidth = _menuViewContainer.frame.size.width;

    //放置content的位置
    _contentViewContainer.frame = CGRectMake(CGRectGetMaxX(_menuViewContainer.frame), 0, self.frame.size.width, self.frame.size.height);
    //设置可滚动区域
    self.contentSize = CGSizeMake(_menuViewContainer.frame.size.width + _contentViewContainer.frame.size.width, 0);
    //初始关闭菜单
    [self closeMenuWithAnimation:false];

    if(_menuView != nil)
    {
        _menuView.frame = _menuViewContainer.bounds;
    }
    if(_contentView != nil)
    {
        _contentView.frame = _contentViewContainer.bounds;
    }
}

//设置菜单和内容
-(void)setMenuView:(UIView *)menuView withContentView:(UIView *)contentView
{
    //添加菜单
    if(_menuView != nil)
    {
        return;
    }
    _menuView = menuView;
    [_menuViewContainer addSubview:menuView];

    //添加内容
    if(_contentView != nil)
    {
        return;
    }
    _contentView = contentView;
    [_contentViewContainer addSubview:contentView];

    //设置实际菜单位置,填充菜单容器
    _menuView.frame = _menuViewContainer.bounds;
    //设置实际内容位置,填充内容容器
    _contentView.frame = _contentViewContainer.bounds;

}


//拖动松开时会调用,第二个参数表示拖动松开后是否会自动减速滑动
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    //判断应该显示菜单还是内容
    float offset = scrollView.contentOffset.x;
    if(decelerate)
    {
        //如果松开后自动减速滚动,什么也不做
        return;
    }
    if(offset > _menuWidth / 2.0f)
    {
        [self closeMenuWithAnimation:true];
    }
    else
    {
        [self openMenuWithAnimaton:true];
    }
}
//滚动停止后调用
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    //判断应该显示菜单还是内容
    float offset = scrollView.contentOffset.x;

    if(offset > _menuWidth / 2.0f)
    {
        [self closeMenuWithAnimation:true];
    }
    else
    {
        [self openMenuWithAnimaton:true];
    }

}

//正在滚动时调用,频繁调用
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    //计算菜单移动比例
    float ratio = scrollView.contentOffset.x * 1.0f / _menuWidth;
    _menuViewContainer.transform = CGAffineTransformMakeTranslation(_menuWidth * ratio, 0);
}


//关闭菜单
-(void)closeMenuWithAnimation:(BOOL)animated
{
    _isMenuOpen = false;
    [self setContentOffset:CGPointMake(_menuWidth, 0) animated:animated];
}
//打开菜单
-(void)openMenuWithAnimaton:(BOOL)animated
{
    _isMenuOpen = true;
    [self setContentOffset:CGPointMake(0, 0) animated:animated];
}

//菜单切换
-(void)toggleMenu
{
    if(_isMenuOpen)
    {
        [self closeMenuWithAnimation:true];
    }
    else
    {
        [self openMenuWithAnimaton:true];
    }
}


@end

仿QQ侧滑

#import <UIKit/UIKit.h>

@interface SlideMenu3 : UIScrollView
@property (nonatomic, assign) BOOL isMenuOpen;
/**设置菜单和内容*/
-(void)setMenuView:(UIView*)menuView withContentView:(UIView*)contentView;
/**关闭菜单*/
-(void)closeMenuWithAnimation:(BOOL)animated;
/**打开菜单*/
-(void)openMenuWithAnimaton:(BOOL)animated;
/**菜单打开与关闭切换*/
-(void)toggleMenu;
@end
#import "SlideMenu3.h"
#define menu_ratio 0.70f

@interface SlideMenu3()<UIScrollViewDelegate>
@end

@implementation SlideMenu3
{
    float _menuWidth;
    UIView *_menuViewContainer;
    UIView *_contentViewContainer;
    UIView *_menuView;
    UIView *_contentView;
}

-(instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if(self)
    {
        [self setUp];
    }
    return self;
}

-(void)setUp
{
    _menuViewContainer = [UIView new];
    _contentViewContainer = [UIView new];
    [self addSubview:_menuViewContainer];
    [self addSubview:_contentViewContainer];
    self.delegate = self;
    //这两行代码主要是为了确定缩放点,如果不设置是绕view的中心缩放
//    _contentViewContainer.layer.anchorPoint = CGPointMake(0, 0.5f);
//    _contentViewContainer.layer.position = CGPointMake(0, 0.5f);

    //不显示滚动条
    self.showsHorizontalScrollIndicator = false;
    //不显示弹簧效果
    self.bounces = false;
    _isMenuOpen = true;

    if(!CGRectEqualToRect(self.frame, CGRectZero))
    {
        [self initFrame];
    }
}

-(void)setFrame:(CGRect)frame
{
    [super setFrame:frame];
    [self initFrame];
}

-(void)initFrame
{
    //放置菜单的位置
    _menuViewContainer.frame = CGRectMake(0, 0, self.frame.size.width * menu_ratio, self.frame.size.height);
    _menuWidth = _menuViewContainer.frame.size.width;

    //放置content的位置
    _contentViewContainer.frame = CGRectMake(CGRectGetMaxX(_menuViewContainer.frame), 0, self.frame.size.width, self.frame.size.height);
    //设置可滚动区域
    self.contentSize = CGSizeMake(_menuViewContainer.frame.size.width + _contentViewContainer.frame.size.width, 0);
    //初始关闭菜单
    [self closeMenuWithAnimation:false];

    if(_menuView != nil)
    {
        _menuView.frame = _menuViewContainer.bounds;
    }
    if(_contentView != nil)
    {
        _contentView.frame = _contentViewContainer.bounds;
    }
}

//设置菜单和内容
-(void)setMenuView:(UIView *)menuView withContentView:(UIView *)contentView
{
    //添加菜单
    if(_menuView != nil)
    {
        return;
    }
    _menuView = menuView;
    [_menuViewContainer addSubview:menuView];

    //添加内容
    if(_contentView != nil)
    {
        return;
    }
    _contentView = contentView;
    [_contentViewContainer addSubview:contentView];

    //设置实际菜单位置,填充菜单容器
    _menuView.frame = _menuViewContainer.bounds;
    //设置实际内容位置,填充内容容器
    _contentView.frame = _contentViewContainer.bounds;
}


//拖动松开时会调用,第二个参数表示拖动松开后是否会自动减速滑动
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    //判断应该显示菜单还是内容
    float offset = scrollView.contentOffset.x;
    if(decelerate)
    {
        //如果松开后自动减速滚动,什么也不做
        return;
    }
    if(offset > _menuWidth / 2.0f)
    {
        [self closeMenuWithAnimation:true];
    }
    else
    {
        [self openMenuWithAnimaton:true];
    }
}
//正在滚动时调用,频繁调用
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    //计算菜单移动比例
    float ratio = scrollView.contentOffset.x * 1.0f / _menuWidth;
    //计算缩放比例
    float contentScale = ratio * 0.2f + 0.8f;
    float menuScale = 1.0f - ratio * 0.3f;
    float alpha = 1.0f - ratio * 0.4f;

    //缩放内容区
    _contentViewContainer.transform = CGAffineTransformMakeScale(contentScale, contentScale);
    //处理菜单
    CGAffineTransform scaleTransform = CGAffineTransformMakeScale(menuScale, menuScale);
     _menuViewContainer.transform = CGAffineTransformTranslate(scaleTransform,_menuWidth * ratio * 0.6, 0.0f);
    //菜单alpha
    _menuViewContainer.alpha = alpha;

}

//滚动停止后调用
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    //判断应该显示菜单还是内容
    float offset = scrollView.contentOffset.x;

    if(offset > _menuWidth / 2.0f)
    {
        [self closeMenuWithAnimation:true];
    }
    else
    {
        [self openMenuWithAnimaton:true];
    }

}


//关闭菜单
-(void)closeMenuWithAnimation:(BOOL)animated
{
    _isMenuOpen = false;
    [self setContentOffset:CGPointMake(_menuWidth, 0) animated:animated];
}

//打开菜单
-(void)openMenuWithAnimaton:(BOOL)animated
{
    _isMenuOpen = true;
    [self setContentOffset:CGPointMake(0, 0) animated:animated];
}

//菜单切换
-(void)toggleMenu
{
    if(_isMenuOpen)
    {
        [self closeMenuWithAnimation:true];
    }
    else
    {
        [self openMenuWithAnimaton:true];
    }
}
@end

Demo下载地址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值