Как создать пользовательское меню слайдов без сторонней библиотеки.?

Я хочу реализовать меню слайдов в моем приложении iOS, таком как ящик (Andriod). Я прошел учебник, но все они используют сторонние библиотеки. Есть ли возможность создать пользовательское меню слайдов. Я попытался создать его со следующим кодом, но он работает только с файлом xib:

- (IBAction)sidemenu:(id)sender
{
    [UIView animateWithDuration:0.50f animations:^{
        view.frame = self.view.frame;
    } completion:^(BOOL finished) {
        swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(SwipGestureLeftAction:)];
        swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
        [self.view addGestureRecognizer:swipeLeft];
    }];
 }

- (void)SwipGestureAction
{
    UISwipeGestureRecognizer *swiperight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(SwipGestureRightAction:)];
    swiperight.direction = UISwipeGestureRecognizerDirectionRight;
    [self.view addGestureRecognizer:swiperight];
}

#pragma mark AddSwipeGestureLeftAndRight
- (void)SwipGestureRightAction:(UISwipeGestureRecognizer *)swipeRight
{
    [UIView animateWithDuration:0.50f animations:^{
        view.frame = self.view.frame;
    } completion:^(BOOL finished) {
        swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(SwipGestureLeftAction:)];
        swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
        [self.view addGestureRecognizer:swipeLeft];
    }];
}

- (void)SwipGestureLeftAction:(UISwipeGestureRecognizer *)swipeRight
{
    [UIView animateWithDuration:0.50f animations:^{
        [view setFrame:CGRectMake(self.view.frame.origin.x - self.view.frame.size.width, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height)];
    } completion:^(BOOL finished){
        [self.view removeGestureRecognizer:swipeLeft];
    }];
}

Ответ 1

Вот что я имею для вас:

Я сделал суперкласс для всех моих меню слайдов во всех проектах. Он управляет отображением и скрытием меню слайдов и обрабатывает изменения ориентации. Он скользит влево сверху текущего вида и частично скрывает оставшуюся часть изображения с темным прозрачным фоном. Если вам когда-либо понадобится другое поведение (например, выталкивание текущего представления), просто переопределите часть анимации. Мое меню слайдов - Singleton, потому что в наших приложениях мы используем только одно меню слайдов на каждом экране.

#import <UIKit/UIKit.h>

@interface IS_SlideMenu_View : UIView <UIGestureRecognizerDelegate>
{
    UIView* transparentBgView;
    BOOL hidden;
    int lastOrientation;
}

@property (strong, nonatomic) UIView *menuContainerV;

+ (id)sharedInstance;

- (BOOL)isShown;
- (void)hideSlideMenu;
- (void)showSlideMenu;

@end


#import "IS_SlideMenu_View.h"

@implementation IS_SlideMenu_View

+ (id)sharedInstance
{
    static id _sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[[self class] alloc] init];
    });

    return _sharedInstance;
}

- (instancetype)initWithFrame:(CGRect)frame
{
    frame = [[[UIApplication sharedApplication] delegate] window].frame;
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor clearColor];

        transparentBgView = [[UIView alloc] initWithFrame:frame];
        [transparentBgView setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0.6]];
        [transparentBgView setAlpha:0];
        transparentBgView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
        UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gestureRecognized:)];
        UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(gestureRecognized:)];
        [transparentBgView addGestureRecognizer:tap];
        [transparentBgView addGestureRecognizer:pan];

        [self addSubview:transparentBgView];

        frame.size.width = 280;
        self.menuContainerV = [[UIView alloc] initWithFrame:frame];
        CALayer *l = self.menuContainerV.layer;
        l.shadowColor = [UIColor blackColor].CGColor;
        l.shadowOffset = CGSizeMake(10, 0);
        l.shadowOpacity = 1;
        l.masksToBounds = NO;
        l.shadowRadius = 10;
        self.menuContainerV.autoresizingMask = UIViewAutoresizingFlexibleHeight;

        [self addSubview: self.menuContainerV];
        hidden = YES;
    }

    //----- SETUP DEVICE ORIENTATION CHANGE NOTIFICATION -----
    UIDevice *device = [UIDevice currentDevice];
    [device beginGeneratingDeviceOrientationNotifications];
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:device];

    lastOrientation = [[UIDevice currentDevice] orientation];

    return self;
}

//********** ORIENTATION CHANGED **********
- (void)orientationChanged:(NSNotification *)note
{
    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];    
    if(orientation == UIDeviceOrientationPortrait || orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight){
        NSLog(@"%ld",orientation);
        if(!hidden && lastOrientation != orientation){
            [self hideSlideMenu];
            hidden = YES;
            lastOrientation = orientation;
        }
    }
}

- (void)showSlideMenu {
    UIWindow* window = [[[UIApplication sharedApplication] delegate] window];
    self.frame = CGRectMake(0, 0, window.frame.size.width, window.frame.size.height);

    [self.menuContainerV setTransform:CGAffineTransformMakeTranslation(-window.frame.size.width, 0)];

    [window addSubview:self];
//    [[UIApplication sharedApplication] setStatusBarHidden:YES];

    [UIView animateWithDuration:0.5 animations:^{
        [self.menuContainerV setTransform:CGAffineTransformIdentity];
        [transparentBgView setAlpha:1];
    } completion:^(BOOL finished) {
        NSLog(@"Show complete!");
        hidden = NO;
    }];
}

- (void)gestureRecognized:(UIGestureRecognizer *)recognizer
{
    if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]) {
        [self hideSlideMenu];
    } else if ([recognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
        static CGFloat startX;
        if (recognizer.state == UIGestureRecognizerStateBegan) {
            startX = [recognizer locationInView:self.window].x;
        } else
        if (recognizer.state == UIGestureRecognizerStateChanged) {
            CGFloat touchLocX = [recognizer locationInView:self.window].x;
            if (touchLocX < startX) {
                [self.menuContainerV setTransform:CGAffineTransformMakeTranslation(touchLocX - startX, 0)];
            }
        } else
        if (recognizer.state == UIGestureRecognizerStateEnded) {
            [self hideSlideMenu];
        }
    }
}

- (void)hideSlideMenu
{
    UIWindow* window = [[[UIApplication sharedApplication] delegate] window];
    window.backgroundColor = [UIColor clearColor];
    [UIView animateWithDuration:0.5 animations:^{
        [self.menuContainerV setTransform:CGAffineTransformMakeTranslation(-self.window.frame.size.width, 0)];
        [transparentBgView setAlpha:0];
    } completion:^(BOOL finished) {
        [self removeFromSuperview];
        [self.menuContainerV setTransform:CGAffineTransformIdentity];

//        [[UIApplication sharedApplication] setStatusBarHidden:NO];
        hidden = YES;
        NSLog(@"Hide complete!");
    }];
}

- (BOOL)isShown
{
    return !hidden;
}

@end

Подклассам нужно только добавить подпрограммы в представление menuContainerV и управлять ими.

Пример:

Я создал подкласс, который имеет представление заголовка и представление таблицы как его содержимое. Я создал представление содержимого в xib, а владельцем xib является этот подкласс. Таким образом, я могу привязывать выходы к xib.

#import "IS_SlideMenu_View.h"

@interface CC_SlideMenu_View : IS_SlideMenu_View<UITableViewDelegate, UITableViewDataSource>

@property (weak, nonatomic) IBOutlet UIView *headerView;

@property (weak, nonatomic) IBOutlet UITableView *tableView;

...

@end

Когда создается меню слайдов, я загружаю xib и добавляю представление содержимого в представление menuContainerV.

#import "CC_SlideMenu_View.h"

@implementation CC_SlideMenu_View

- (instancetype)init
{
    self = [super init];
    if (self) {
        UIView *v = [[[NSBundle mainBundle] loadNibNamed:@"CC_SlideMenu_View" owner:self options:nil] firstObject];
        v.frame = self.menuContainerV.bounds;
        [self.menuContainerV addSubview:v];
        self.tableView.backgroundColor = [UIColor darkGrayColor];
    }
    return self;
}

...

@end

В результате получится что-то вроде this.