最近看到QQ上的侧滑菜单特有意思,就自己试着去实现了一下,看上去效果相差不大。
最后的效果图:
首先,需要自定义一个window
DBHWindow.h:
#import <UIKit/UIKit.h>
@interface DBHWindow : UIWindow
/**
显示左侧视图动画
*/
- (void)showLeftViewAnimation;
/**
隐藏左侧视图动画
*/
- (void)hiddenLeftViewAnimation;
/**
显示左侧视图动画
@param excursion 偏移宽度
*/
- (void)showLeftViewAnimationWithExcursion:(CGFloat)excursion;
@end
DBHWindow.m:
#import "DBHWindow.h"
#import "DBHRootViewController.h"
static NSString * const kDBHTableViewCellIdentifier = @"kDBHTableViewCellIdentifier";
@interface DBHWindow ()<UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) UIView *shadeView;
@end
@implementation DBHWindow
#pragma mark - Lifecycle
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setUI];
}
return self;
}
#pragma mark - UI
- (void)setUI {
[self addSubview:self.tableView];
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kDBHTableViewCellIdentifier forIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:@"第%ld行", indexPath.row];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self hiddenLeftViewAnimation];
DBHRootViewController *rootVC = (DBHRootViewController *)self.rootViewController.childViewControllers.firstObject;
rootVC.selectedIndex = indexPath.row;
}
#pragma mark - Event Responds
/**
点击了右侧半透明区域
*/
- (void)respondsToShadeView {
[self hiddenLeftViewAnimation];
}
/**
右侧半透明区域的左滑手势
*/
- (void)respondsToPanGR:(UIPanGestureRecognizer *)panGR {
CGPoint position = [panGR translationInView:self.shadeView];
// 手势触摸结束
if (panGR.state == UIGestureRecognizerStateEnded) {
if (- position.x > MAXEXCURSION * 0.5) {
[self hiddenLeftViewAnimation];
} else {
[self showLeftViewAnimation];
}
return;
}
// 判断是否滑出屏幕外
if (position.x < - MAXEXCURSION || position.x > 0) {
return;
}
[self showLeftViewAnimationWithExcursion:MAXEXCURSION + position.x];
}
#pragma mark - Public Methdos
/**
显示左侧视图动画
*/
- (void)showLeftViewAnimation {
WEAKSELF
[UIView animateWithDuration:0.25 animations:^{
weakSelf.transform = CGAffineTransformTranslate(weakSelf.rootViewController.view.transform, MAXEXCURSION, 0);
weakSelf.shadeView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
[weakSelf addSubview:weakSelf.shadeView];
}];
}
/**
显示左侧视图
@param excursion 偏移大小
*/
- (void)showLeftViewAnimationWithExcursion:(CGFloat)excursion {
self.transform = CGAffineTransformTranslate(self.rootViewController.view.transform, excursion, 0);
self.shadeView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5 * (excursion / MAXEXCURSION)];
if (!self.shadeView.superview) {
[self addSubview:self.shadeView];
}
}
/**
隐藏左侧视图动画
*/
- (void)hiddenLeftViewAnimation {
WEAKSELF
[UIView animateWithDuration:0.25 animations:^{
weakSelf.transform = CGAffineTransformIdentity;
[weakSelf.shadeView removeFromSuperview];
}];
}
#pragma mark - Private Methdos
/**
重写hitTest方法,点击tableView才会响应
*/
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *view = [super hitTest:point withEvent:event];
if (!view) {
CGPoint newPoint = [self.tableView convertPoint:point fromView:self];
if (CGRectContainsPoint(self.tableView.bounds, newPoint)) {
view = self.tableView;
}
}
return view;
}
#pragma mark - Getters And Setters
- (UITableView *)tableView {
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, -MAXEXCURSION, SCREENHEIGHT)];
[_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kDBHTableViewCellIdentifier];
_tableView.dataSource = self;
_tableView.delegate = self;
}
return _tableView;
}
- (UIView *)shadeView {
if (!_shadeView) {
_shadeView = [[UIView alloc] initWithFrame:self.bounds];
_shadeView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToShadeView)];
UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToPanGR:)];
[_shadeView addGestureRecognizer:tapGR];
[_shadeView addGestureRecognizer:panGR];
}
return _shadeView;
}
其次,在主控制器中加上拖动手势,使之看上去看炫
DBHRootViewController.h:
#import <UIKit/UIKit.h>
@interface DBHRootViewController : UIViewController
/**
选中行数
*/
@property (nonatomic, assign) NSInteger selectedIndex;
@end
DBHRootViewController.m:
#import "DBHRootViewController.h"
#import "DBHWindow.h"
@interface DBHRootViewController ()
@property (nonatomic, assign) BOOL isBestLeft; // 是否为最左边
@end
@implementation DBHRootViewController
#pragma mark - Lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"侧滑Demo";
self.view.backgroundColor = [UIColor whiteColor];
[self setUI];
}
#pragma mark - UI
- (void)setUI {
UIBarButtonItem *leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"showLeftView" style:UIBarButtonItemStylePlain target:self action:@selector(respondsToLeftBarButtonItem)];
self.navigationItem.leftBarButtonItem = leftBarButtonItem;
// 添加拖动手势
UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToPanGR:)];
[self.navigationController.view addGestureRecognizer:panGR];
}
#pragma mark - Event Responds
/**
点击showLeftView按钮
*/
- (void)respondsToLeftBarButtonItem {
DBHWindow *window = (DBHWindow *)[UIApplication sharedApplication].keyWindow;
[window showLeftViewAnimation];
}
/**
拖动手势调用的方法
*/
- (void)respondsToPanGR:(UIPanGestureRecognizer *)panGR {
CGPoint clickPoint = [panGR locationInView:self.navigationController.view];
CGPoint position = [panGR translationInView:self.navigationController.view];
// 手势触摸开始
if (panGR.state == UIGestureRecognizerStateBegan) {
// 判断手势起始点是否在最左边区域
self.isBestLeft = clickPoint.x < LEFTMAXWIDTH;
}
DBHWindow *window = (DBHWindow *)[UIApplication sharedApplication].keyWindow;
// 手势触摸结束
if (panGR.state == UIGestureRecognizerStateEnded) {
if (position.x > MAXEXCURSION * 0.5) {
[window showLeftViewAnimation];
} else {
[window hiddenLeftViewAnimation];
}
return;
}
// 判断是否滑出屏幕外或者拖动手势起始点是否在最左侧区域
if (position.x < 0 || position.x > MAXEXCURSION || !self.isBestLeft) {
return;
}
[window showLeftViewAnimationWithExcursion:position.x];
}
#pragma mark - Getters And Setters
- (void)setSelectedIndex:(NSInteger)selectedIndex {
_selectedIndex = selectedIndex;
UIAlertController *alert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"点击了第%ld行", _selectedIndex] message:@"" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
}
@end
时间原因,加上只是想实现一个侧滑的效果,左侧的显示视图就随意放了一个tableView,这里可以根据自己的需要换成其他视图即可。想看源码的可以点击最下面的地址下载。
Demo地址
网友评论