Який найкращий спосіб розробити меню з боковин, як у новому додатку для iOS у Facebook?


155

Здається, що бічні панелі меню стають все більш поширеним елементом інтерфейсу, оскільки в кожну програму iPhone додається більше інформації. Facebook включив його до своєї останньої версії, і, як видається, додає нову програму Gmail . Мені було цікаво, чи хтось задумувався над найефективнішим способом розробити щось подібне, оскільки це стає більш поширеним елементом інтерфейсу. Хоча я маю власні думки щодо того, як це побудувати, мені цікаво почути, що думають інші.

Перемістіть навігацію по Facebook


Я помітив, що коли ввімкнено меню "Sidewipe", ви не можете нічого робити із висунутою частиною подання. Моя ідея полягала в тому, щоб відобразити поточний вигляд у зображенні та відобразити його частину, коли активізується Sidewipe
Денис

5
У чий профіль у Facebook ви зазирнули, Нік О'Нілл? :-p
Константіно Царухас

1
можливий дублікат SplitView, але на iPhone
JosephH

1
@Zoidberg Мені цікаво більше про це почути. Особисто мені подобаються сидени! Але я розробник, а не дизайнер. Що робить цей UX бідним?
Роберт Карл

3
Будь ласка, будь-хто дивіться Проектування інтуїтивного досвіду користувачів, щоб дізнатись, які проблеми яблуко визначило з цим так званим "меню гамбургерів"
vikingosegundo

Відповіді:


34

Нещодавно я натрапив на це, насправді не подивився на код і не перевірив контроль, але схоже, що це може бути дуже пристойною відправною точкою.

jtrevealsidebar

Редагувати: Читач також повинен переглянути інші відповіді :)


Не дозволяє користувачеві ковзати
cannyboy

6
Якщо ви шукаєте функцію проведення пальцем Вставте розпізнавальник жестів у подання, а потім замініть перемикач на розпізнавальник жестів.
CJ Teuben

Але що робити, якщо ви хочете провести пальцем і мати можливість перемикання?
jsetting32

Це припинено, тому я би переїхав в інше місце.
Майк Флінн

84

Для цього існує велика бібліотека Тома Адріанссена : Inferis / ViewDeck

Він дуже простий у використанні та має досить велику кількість наступних.

Редагувати:

Щось трохи легше, перегляньте: dualmobile / MMDrawerController

Він не має всіх функцій ViewDeck, але його простіше змінювати та розширювати.


6
Я рекомендую всім користуватися цим.
Алмас Адільбек

3
найкраще рішення: гнучка та проста у використанні
HotJard

2
Я спробував це і знайшов у своєму прикладі багато помилок. Після декількох швидких клацань контролери перегляду вирівнюються
Torsten B

13
Ми використовували його для кількох додатків, але підтримувати та додавати до нього нові функції було дуже важко. Вона також постраждала від спроб впровадити занадто багато. Ми вирішили написати власний під назвою MMDrawerController. Легкий і зосереджений: github.com/mutualmobile/MMDrawerController
kcharwood

1
MMDrawerController - це дуже хороша бібліотека. Також підтримує універсальний додаток. програми для iphone та ipad
Ерхан Демірчі

48

Я створив для цього бібліотеку. Він називається MFSideMenu .

Крім усього іншого, вона включає підтримку iphone + ipad, портрет + пейзаж, меню зліва або справа, UITabBarController та жести панорами.


Це чудовий проект .. але він не підтримує ландшафтний режим. Чи можете ви дати нам підказку, щоб використовувати його і в ландшафтному режимі? .. Дякую
Sameera Chathuranga

Дякую @SameeraChathuranga Я сподіваюся додати підтримку пейзажу, якщо отримаю трохи часу. Єдина частина, яка не підтримує пейзаж - це SideMenuViewController ... Я вважаю, що вам доведеться зробити щось подібне до другої відповіді тут: stackoverflow.com/questions/2508630/… . Не соромтеся розщедритися та внести свій внесок у репо!
Майкл Фредерік

І я рекомендую це відповідь на це питання .. не на вищезгадане .. його занадто складне .. з цим дуже легко впоратися :) Якщо хтось хоче, я можу розмістити код, як працювати з орієнтацією ..: )
Sameera Chathuranga

6
Для всіх, хто цікавиться, я просто додав бібліотечну підтримку до бібліотеки.
Майкл Фредерік

1
@AlmasAdilbek, чи можете ви пояснити, які частини вашої програми відчули зниження продуктивності? Я був би радий зробити будь-які необхідні оптимізації.
Майкл Фредерік

29

Перевірте MMDrawerController:

MMDrawerController

Ми не змогли знайти бібліотеку, яка нам сподобалася, тому ми просто розкрутили власну.


10
Просто хотів сказати, що це НАЙДОЛО найкраща реалізація, перерахована тут. Люди, які не знайомі з цією темою: використовують MMDrawerController.
mxcl

Вдячні за добрі слова!
kcharwood

Я використовував ViewDeck за останній рік, але нещодавно перейшов на MMDrawerController, і рекомендую всім користуватися цим. Одне з найкращих втілення в цілому бібліотеках. Дякую Кевін :)
Tariq

Перевірив цей MMDrawerController і хочу сказати, що це дійсно найкращий варіант для бічного меню. Вдячний! Велике спасибі @Michael Frederick
Resty

Чи підтримує це iOS8? Спасибі
Бреду Томасу

12

Основна ідея , що ви повинні кадру або центр набору self.navigationController.view в . Є дві події, з якими вам доведеться впоратися. (1) barButtonItem press . (2) жест панорами через промахування.

Ви можете надіслати контролер перегляду на задній план таким чином:

[self.view sendSubviewToBack:menuViewController.view];

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIBarButtonItem *barButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(buttonPressed:)];
    UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
    [self.navigationController.view addGestureRecognizer:panGestureRecognizer];
    self.navigationItem.leftBarButtonItem = barButtonItem;
}

- (void)buttonPressed:(id)sender {

    CGRect destination = self.navigationController.view.frame;

    if (destination.origin.x > 0) {
        destination.origin.x = 0;
    } else {
        destination.origin.x = 320;
    }

    [UIView animateWithDuration:0.25 animations:^{
        self.navigationController.view.frame = destination;
    }];
}

- (void)handlePan:(UIPanGestureRecognizer *)recognizer
{
    static CGPoint originalCenter;

    if (recognizer.state == UIGestureRecognizerStateBegan)
    {
        originalCenter = recognizer.view.center;

    } else if (recognizer.state == UIGestureRecognizerStateChanged)
    {
        CGPoint translation = [recognizer translationInView:self.view];

        recognizer.view.center = CGPointMake(originalCenter.x + translation.x, originalCenter.y);
    }
    else if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled || recognizer.state == UIGestureRecognizerStateFailed)
    {
        if (recognizer.view.frame.origin.x < 160) {
            [UIView animateWithDuration:0.25 animations:^{
                recognizer.view.center = CGPointMake(384, 487.5);
            }];
        } else {
            [UIView animateWithDuration:0.25 animations:^{
                recognizer.view.center = CGPointMake(384 + 320, 487.5);
            }];
        }
    }
}

Працює ідеально і без зайвого коду. Вам потрібно лише вказати межі, на які користувач може розмістити панораму, щоб переглянути ваш погляд
Moisés Olmedo

@Janos сер ласкаво допоможіть мені не вистачає цього більше днів
Рагуль,

Я створив меню в сторону за допомогою вашого вищевказаного коду, коли при висуванні на задній стороні видно лише темний колір, не перегляд люб'язно мені допомагає
Ragul

Сер, це добре працює, я використовую лише цей вище код. єдине, що фоновий вигляд не показує, я його застосував, будь ласка, допоможіть мені показати фоновий вигляд
Рагул,

@ János і де використовувати цей рядок коду [self.view sendSubviewToBack: menuViewController.view];
Рагуль


11

Реалізація Facebook розміщує UIPanGestureRecognizer на UINavigationBar. Тим самим дозволяючи ловити пальці там, де це потрібно.

Це дозволяє виконувати такі дії, як, безпосередньо розпізнаючи напрямок дотику в x / z, а також швидкість, з якою вони мали місце.

Крім того, такий тип майстерності з UIViews (більше одного на екрані одночасно з очевидно різними завданнями -> таким чином, різні контролери) повинен (я спокусився сказати, повинен) використовувати iOS нові функції ViewController-Containment. Кожна реалізація без цього просто погана, оскільки хизується ієрархією перегляду таким чином, який не передбачав Apple.

З боку: Якщо вам дуже цікаво, як це можна зробити якомога ближче до шляху Facebook, перегляньте проект, який я відкриваю на Github PKRevealController .


Немає нічого поганого (або HIG-несумісного) з керуванням користувацьким інтерфейсом на основі UIView. Обмеження контролера перегляду було надто пізно, тому було використано безліч інших підходів. Пов'язана стаття: blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers
Джейкоб Дженнінгс

1
Основні розробки довгий час не будуть орієнтовані на мінімальну версію iOS 5, оскільки велика кількість користувачів не буде модернізуватись дуже довго. Хоча багато хто з них є "хаками", як ви кажете, це, безумовно, можна зробити правильно. Перебування в рамках - це, безумовно, безпечна ставка, але іноді для унікального та користувальницького інтерфейсу потрібно більше.
Джейкоб Дженнінгс

8

Є десятки різних бібліотек, які розробники створили для реалізації навігації у стилі Facebook / Path для додатків iOS. Я можу перерахувати їх, але, як ви попросили найкращого, ось два мої варіанти, які я використовую для реалізації навігаційного меню бічного пальця:

1) ECSlidingViewController Його дуже просто в застосуванні та використанні. У мене не було жодних проблем з його реалізацією, не було отримано помилок чи подібного. Надане я посилання має майже все пояснення для того, щоб його використовувати.

2) SWRevealViewController Ця бібліотека проста у використанні, і ви можете знайти підручник ТУТ , який показує, як реалізувати її з усіма поясненнями разом із зображеннями. Ви можете просто слідувати підручнику і подякувати мені пізніше.


1
SWRevealViewController є найпростішим, він використовує його, жодна помилка не працює добре
vishal dharankar

7

Ще один варіант - використовувати Scringo . Це дає вам побічне меню, як у програмах youtube / facebook, а також всі види вбудованих функцій у меню, які ви можете вибрати, щоб додати (наприклад, чат, запросити друзів тощо).

Додавати бічне меню просто зателефонувавши [ScringoAgent startSession ...], і все налаштування можна виконати на сайті.



4

Це питання досить популярне, але все зводилося до простого імпорту та використання для мене ... Ось що я використовую ... SWRevealController .

Я здивований, що люди це сумують ... Це дійсно ВЕЛИКО !!! і простий у використанні. Розробник навіть включає кілька прикладних проектів, які дозволяють побачити, як його використовувати в різних сценаріях.



2

І Gmail, і Facebook активно використовують перегляди в Інтернеті, тому важко сказати, що таке кодовий код і що надає HTML. Однак, дивлячись на інтерфейс, схоже, вони розмістили UITableView із шириною, вужчою, ніж ширина екрана (320пт) під UIView, що містить вміст, який вони хочуть відображати. Вибір різних рядків перегляду таблиці, ймовірно, замінює підпогляд подання вмісту.

Принаймні, саме так я підійшов би до проблеми. Важко продиктувати, яким воно має бути. Просто заскочіть прямо та починайте експериментувати!


ей, може хто-небудь розповість мені, як створити перегляд пальцем типу facebook і панель меню в android
Неєрав Шах

1

Якщо ви хочете, я зробив це репо на Github GSSlideMenu Це дозволить вам створити меню у стилі Facebook, АЛЕ "назад" webView (як правило, всі репости, які я знайшов, мають tableView як "назад").



1

вид праворуч може знаходитися всередині підкласу UIScrollView. У цьому підкласі ви можете замінити, - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)eventщоб повернути ДА, лише якщо користувач торкнувся підперегляду. Таким чином ви можете розмістити прозорий UIScrollView над будь-яким іншим представленням даних і пройти через будь-яку сенсорну подію, що відбувається поза підпідглядом; і ви отримуєте матеріали прокрутки безкоштовно.

Наприклад:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
    CGPoint location=[self convertPoint:point toView:subview];
    return (location.x > 0 && 
            location.x < subview.frame.size.width && 
            location.y > 0 && 
            location.y < subview.frame.size.height);
}

або:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
    return [subview pointInside:
             [self convertPoint:point toView:subview] withEvent:event];

1

Спробуйте додати меню (до якого ви проведіть пальцем) під основним вікном. Почніть підписуватись на торкання подій у перегляді.

Реалізуйте touchesMoved:та перевірте, чи є перший gestureвертикальним (прокрутіть головний вигляд, якщо потрібно) чи горизонтальним (тут ви хочете показати меню). Якщо він горизонтальний, почніть викликати інший метод, - (void)scrollAwayMainView:(NSUInteger)pixelsщоразу, коли вас touchesMoved:викликають, обчислюючи кількість пікселів від початкової точки, якою повинен бути головний вигляд, і передаючи це число в метод. У реалізації цієї методи запустіть наступний код:

[mainView scrollRectToVisible:CGRectMake:(pixels, 
                                          mainView.origin.y, 
                                          mainView.size.width, 
                                          mainView.size.height];

0

Ознайомтесь з моїм рішенням цього питання:

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

Один єдиний клас, який вам потрібно лише підкласи і заповнити вмістом.

Ось клас. Більш детально див. Вищенаведене посилання.

#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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.