最近看到QQ上的側(cè)滑菜單特有意思,就自己試著去實(shí)現(xiàn)了一下栗菜,看上去效果相差不大。
最后的效果圖:
首先,需要自定義一個(gè)window
DBHWindow.h:
#import <UIKit/UIKit.h>
@interface DBHWindow : UIWindow
/**
顯示左側(cè)視圖動(dòng)畫
*/
- (void)showLeftViewAnimation;
/**
隱藏左側(cè)視圖動(dòng)畫
*/
- (void)hiddenLeftViewAnimation;
/**
顯示左側(cè)視圖動(dòng)畫
@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
/**
點(diǎn)擊了右側(cè)半透明區(qū)域
*/
- (void)respondsToShadeView {
[self hiddenLeftViewAnimation];
}
/**
右側(cè)半透明區(qū)域的左滑手勢(shì)
*/
- (void)respondsToPanGR:(UIPanGestureRecognizer *)panGR {
CGPoint position = [panGR translationInView:self.shadeView];
// 手勢(shì)觸摸結(jié)束
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
/**
顯示左側(cè)視圖動(dòng)畫
*/
- (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];
}];
}
/**
顯示左側(cè)視圖
@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];
}
}
/**
隱藏左側(cè)視圖動(dòng)畫
*/
- (void)hiddenLeftViewAnimation {
WEAKSELF
[UIView animateWithDuration:0.25 animations:^{
weakSelf.transform = CGAffineTransformIdentity;
[weakSelf.shadeView removeFromSuperview];
}];
}
#pragma mark - Private Methdos
/**
重寫hitTest方法,點(diǎn)擊tableView才會(huì)響應(yīng)
*/
- (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;
}
其次,在主控制器中加上拖動(dòng)手勢(shì)椿争,使之看上去看炫
DBHRootViewController.h:
#import <UIKit/UIKit.h>
@interface DBHRootViewController : UIViewController
/**
選中行數(shù)
*/
@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 = @"側(cè)滑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;
// 添加拖動(dòng)手勢(shì)
UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToPanGR:)];
[self.navigationController.view addGestureRecognizer:panGR];
}
#pragma mark - Event Responds
/**
點(diǎn)擊showLeftView按鈕
*/
- (void)respondsToLeftBarButtonItem {
DBHWindow *window = (DBHWindow *)[UIApplication sharedApplication].keyWindow;
[window showLeftViewAnimation];
}
/**
拖動(dòng)手勢(shì)調(diào)用的方法
*/
- (void)respondsToPanGR:(UIPanGestureRecognizer *)panGR {
CGPoint clickPoint = [panGR locationInView:self.navigationController.view];
CGPoint position = [panGR translationInView:self.navigationController.view];
// 手勢(shì)觸摸開始
if (panGR.state == UIGestureRecognizerStateBegan) {
// 判斷手勢(shì)起始點(diǎn)是否在最左邊區(qū)域
self.isBestLeft = clickPoint.x < LEFTMAXWIDTH;
}
DBHWindow *window = (DBHWindow *)[UIApplication sharedApplication].keyWindow;
// 手勢(shì)觸摸結(jié)束
if (panGR.state == UIGestureRecognizerStateEnded) {
if (position.x > MAXEXCURSION * 0.5) {
[window showLeftViewAnimation];
} else {
[window hiddenLeftViewAnimation];
}
return;
}
// 判斷是否滑出屏幕外或者拖動(dòng)手勢(shì)起始點(diǎn)是否在最左側(cè)區(qū)域
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:@"點(diǎn)擊了第%ld行", _selectedIndex] message:@"" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
}
@end
時(shí)間原因,加上只是想實(shí)現(xiàn)一個(gè)側(cè)滑的效果秘遏,左側(cè)的顯示視圖就隨意放了一個(gè)tableView丘薛,這里可以根據(jù)自己的需要換成其他視圖即可嘉竟。想看源碼的可以點(diǎn)擊最下面的地址下載邦危。
Demo地址