Facebook'un yeni iOS uygulamasındaki gibi bir yan kaydırma menüsü geliştirmenin en iyi yolu nedir?


155

Her iPhone uygulamasına daha fazla bilgi sıkıştıkça, yan kaydırma menülerinin daha yaygın bir arayüz öğesi haline geldiği anlaşılıyor. Facebook bunu en son sürümüne dahil etti ve yeni Gmail uygulaması da onu içeriyor gibi görünüyor . Daha yaygın bir arabirim öğesi haline geldiği için böyle bir şeyi geliştirmenin en etkili yolu hakkında düşüncelerin olup olmadığını merak ediyordum. Bunu nasıl oluşturacağım konusunda kendi düşüncelerim olsa da, diğer insanların ne düşündüğünü duymak isterim.

Facebook hızlıca gezinme


Sidewipe menüsü etkinleştirildiğinde, görünümün kaydırılmış kısmı ile hiçbir şey yapamayacağınızı fark ettim. Benim fikrim, sidewipe etkinleştirildiğinde görüntüdeki geçerli görünümü oluşturmak ve bir kısmını görüntülemekti
Denis

5
Kimin Facebook profilini inceledin, Nick O'Neill? :-p
Constantino Tsarouhas


1
@Zoidberg Bununla ilgili daha fazla şey duymak istiyorum. Şahsen ben sidenavı seviyorum! Ama ben bir geliştiriciyim, tasarımcı değil. Bu UX'i kötü yapan nedir?
Robert Karl

3
Herkes bu elma "hamburger menüleri" ile tanımladığı sorunları öğrenmek için Sezgisel Kullanıcı Deneyimleri Tasarlama izleyin
vikingosegundo

Yanıtlar:


34

Son zamanlarda bununla karşılaştım, aslında koda bakmadım veya kontrolü test etmedim, ama çok iyi bir başlangıç ​​noktası olabilir gibi görünüyor.

jtrevealsidebar

Düzenleme: Okuyucu diğer cevaplara da bakmalıdır :)


Kullanıcının kaymasına izin vermez
cannyboy

6
Kaydırma işlevini arıyorsanız. Görünüme bir hareket tanıyıcı ekleyin, ardından seçim düğmesini hareket tanıyıcı ile değiştirin.
CJ Teuben

Peki ya hızlıca kaydırmak ve geçiş yapmak istiyorsanız?
jsetting32

Başka bir yere taşınmak için bu durduruldu.
Mike Flynn

84

Tom Adriaenssen'den bunun için harika bir kütüphane var: Inferis / ViewDeck

Kullanımı çok kolay ve oldukça büyük bir takipçisi var.

DÜZENLE:

Biraz daha hafif bir şey için göz atın : mutualmobile / MMDrawerController

ViewDeck'in tüm özelliklerine sahip değildir, ancak değiştirilmesi ve genişletilmesi daha kolaydır.


6
Herkesin bunu kullanmasını öneriyorum.
Almas Adilbek

3
en iyi çözüm: esnek ve kullanımı kolay
HotJard

2
Ben denedim ve onların Örnek bir sürü Hata bulundu. Bazı hızlı tıklamalardan sonra görünüm denetleyicileri yanlış hizalanmış
Torsten B

13
Birkaç uygulama için kullandık, ancak bakımını yapmak ve yeni özellikler eklemek çok zordu. Ayrıca çok fazla uygulamayı denemekten de acı çekti. MMDrawerController adlı yazımızı yazmaya karar verdik. Hafif ve odaklanmış: github.com/mutualmobile/MMDrawerController
kcharwood

1
MMDrawerController çok iyi bir kütüphane.Ayrıca evrensel uygulamayı destekliyor. iphone ve ipad uygulamaları
Erhan Demirci

48

Bunun için bir kütüphane oluşturdum. Buna MFSideMenu denir .

Diğer şeylerin yanı sıra iphone + ipad, portre + manzara, sol veya sağ taraftaki menü, UITabBarController ve pan hareketlerini destekler.


Onun harika bir proje .. ama onun manzara modu için desteklemiyor .. u bize de manzara modunda kullanmak için bir ipucu verebilir .. Teşekkürler
Sameera Chathuranga

Teşekkürler @SameeraChathuranga. Biraz zaman alırsam peyzaj desteği eklemeyi umuyorum. Peyzaj desteği olmayan tek parça SideMenuViewController ... Sanırım burada 2. cevap gibi bir şey yapmanız gerekecek: stackoverflow.com/questions/2508630/… . Çatalı çekinmeyin ve repoya katkıda bulunun!
Michael Frederick

Ve ben bu sorunun cevabını tavsiye ederim .. yukarıda değil .. onun çok karmaşık .. bu çok kolay :) bazı biri istersen ben kod gönderebilirsiniz, nasıl oryantasyon ile çalışmak ..: )
Sameera Chathuranga

6
İlgilenen herkes için kütüphaneye peyzaj desteği ekledim.
Michael Frederick

1
@AlmasAdilbek, uygulamanızın hangi bölümlerinde performans düşüşü yaşadığını açıklayabilir misiniz? Gerekli optimizasyonları yapmaktan memnuniyet duyarım.
Michael Frederick

29

MMDrawerController'a göz atın:

MMDrawerController

Beğendiğimiz bir kütüphane bulamadık, bu yüzden sadece kendi kütüphanemizi aldık.


10
Sadece bunun FAR TARAFINDAN burada listelenen en iyi uygulama olduğunu söylemek istedim. Bu konuya yeni katılanlar: MMDrawerController kullanın.
mxcl

Nazik kelimeleri takdir edin!
kcharwood

Son bir yıldan beri ViewDeck kullanıyordum ama son zamanlarda MMDrawerController'a geçtim ve herkese bunu kullanmasını öneriyorum. Genel kütüphanelerdeki en iyi uygulamalardan biri. Teşekkürler Kevin :)
Tarık

Bu MMDrawerController'ı kontrol ettim ve yan menü için gerçekten en iyi seçenek olduğunu söylemek istiyorum. Takdir! @Michael Frederick
Resty

Bu iOS8'i destekliyor mu? Teşekkürler
Brad Thomas

12

Anahtar fikir Eğer zorunda kümesi self.navigationController.view çerçevesinin veya merkezi . Orada iki olay işlemek zorunda. (1) barButtonItem tuşuna basın . (2) kaydırma nedeniyle kaydırma hareketi .

Görünüm denetleyicisini arka plana şu şekilde gönderebilirsiniz:

[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);
            }];
        }
    }
}

Mükemmel ve çok fazla kod olmadan çalışır. Yalnızca kullanıcının görünümünüzü kaydırmak için sınırlarını belirtmeniz gerekir
Moisés Olmedo

@Janos efendim nazikçe bana daha fazla gün için eksik olduğumu yardım
Ragul

Ben yukarıdaki kod yardımı ile yan dışarı menü yarattık, slideout arka taraf sadece koyu renk gösterir zaman görünüm nazikçe bana yardım
Ragul

Efendim iyi çalışıyor Ben sadece yukarıdaki kodu kullanın. tek şey arka plan görünümü dosjected ben gösterir upoted lütfen arka plan görünümünü göstermek için bana yardım
Ragul

@ János ve bu kod satırının nerede kullanılacağı [self.view sendSubviewToBack: menuViewController.view];
Ragul


11

Facebook'un uygulaması UINavigationBar'a bir UIPanGestureRecognizer yerleştirir. Böylece ihtiyaç duyulan yerlerde swipe yakalamanıza izin verir.

Bu, x / z'deki dokunma yönünü ve bunların meydana geldiği hızı tanımak gibi şeyler yapmanıza izin verir.

Ayrıca UIViews ile bu tür müdahaleler (açıkça farklı görevlerle aynı anda birden fazla ekranda -> böylece farklı denetleyiciler) iOS yeni ViewController-Containment özelliklerini kullanmalıdır (şart olduğunu söylemek cazipim). Onsuz her uygulama, görünüm hiyerarşisine Apple tarafından tasarlanmayan bir şekilde müdahale ettiği için kötüdür.

Bir sidenote üzerinde: Facebook'un mümkün olduğu kadar yakın bir şekilde nasıl yapılabileceğini gerçekten merak ediyorsanız, Github PKRevealController'da açtığım projeye göz atın .


UIView tabanlı özel kullanıcı arayüzünü yönetmede yanlış (veya HIG uyumlu olmayan) bir şey yok. Görünüm denetleyicisi kapsamı çok geç geldi, bu nedenle başka yaklaşımlar da kullanıldı. İlgili bir makale: blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers
Jacob Jennings

1
Çok sayıda kullanıcı çok uzun bir süre yeni sürüme geçmeyeceğinden, önemli gelişmeler iOS 5'in minimum sürümünü uzun süre hedeflemeyecektir. Birçoğu dediğin gibi 'hack' olsa da, kesinlikle doğru bir şekilde yapılabilir. Çerçevelerin içinde kalmak kesinlikle güvenli bir bahistir, ancak bazen benzersiz ve özel bir kullanıcı arayüzü daha fazlasını gerektirir.
Jacob Jennings

8

Geliştiricilerin iOS uygulamaları için Facebook / Yol stili navigasyonunu uygulamak için oluşturdukları onlarca farklı kütüphane vardır. Hepsini listeleyebilirim ama en iyisini istediğin gibi, burada yan kaydırma navigasyon menüsünü uygulamak için kullandığım iki seçimim:

1) ECSlidingViewController Storyboard'ları uygulamak ve kullanmak çok kolaydır. Uygularken herhangi bir sorun yaşamadım veya herhangi bir hata veya benzeri bir şey almadım. Sağladığım bağlantı kullanmak için hemen hemen tüm açıklamalara sahiptir.

2) SWRevealViewController Bu kütüphanenin kullanımı kolaydır ve BURADA bir öğretici bulabilirsiniz , bu görüntülerle birlikte tüm açıklamalarla nasıl uygulanacağını gösterir. Öğreticiyi takip edebilir ve daha sonra bana teşekkür edebilirsiniz.


1
SWRevealViewController en basit olanıdır, hiçbir hata iyi çalışmadı
vishal dharankar

7

Başka bir seçenek Scringo'yu kullanmaktır . Size youtube / facebook uygulamalarında olduğu gibi bir yan menü ve ayrıca menüde eklemeyi seçebileceğiniz her türlü yerleşik özellik sunar (örneğin sohbet, arkadaşlarınızı davet edin, vb.)

Yan menünün eklenmesi basitçe [ScringoAgent startSession ...] 'ı çağırmaktır ve sitede tüm yapılandırmalar yapılabilir.



4

Bu soru oldukça popüler ama hepsi benim için kolay içe aktarma ve kullanma için geldi ... İşte kullandığım şey ... SWRevealController .

İnsanlar özledim şaşırdım ... Gerçekten BÜYÜK !!! ve kullanımı kolaydır. Geliştirici, farklı senaryolarda nasıl kullanılacağını görmenizi sağlayan birkaç örnek proje bile içerir.



2

Hem Gmail hem de Facebook, web görüntülemelerini yoğun bir şekilde kullanıyor, bu nedenle yerel kodun ve HTML'nin neyin oluşturulduğunu söylemek zor. Ancak, arayüze bakıldığında, görüntülemek istedikleri içeriği içeren bir UIView altına ekran genişliğinden (320pt) daha dar bir genişliğe sahip bir UITableView yerleştirmiş gibi görünüyorlar. Farklı tablo görünümü satırlarının seçilmesi muhtemelen içerik görünümünün bir alt görünümünü değiştirir.

En azından soruna bu şekilde yaklaşırım. Ne olması gerektiğini dikte etmek zor. Sadece sağa atla ve denemeye başla!


hey biri bana facebook türü tokatlamak görünümü ve android menü paneli oluşturmak için nasıl söyleyebilir
Neerav Shah

1

İsterseniz ben bu repo github GSSlideMenu üzerinde yaptım Bu bir "geri" webView (genellikle bulduğum tüm depolar "arka" görünümü olarak bir tableView vardır) bir Facebook tarzı menü AMA oluşturmanıza olanak sağlar.



1

sağdaki görünüm bir UIScrollView alt sınıfının içinde olabilir. Bu alt - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)eventsınıfta, yalnızca kullanıcı alt görünüme dokunduğunda EVET'i döndürmek için geçersiz kılabilirsiniz . Bu şekilde, şeffaf UIScrollView öğenizi diğer görünümlerin üzerine yerleştirebilir ve alt görünümün dışında gerçekleşen herhangi bir dokunma etkinliğinden geçebilirsiniz; ve ücretsiz kaydırma şeyler alırsınız.

Örneğin:

- (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);
}

veya:

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

1

Ana görünümün altına menünüzü (almak için kaydırdığınız) eklemeyi deneyin. Görünümdeki dokunma etkinliklerine abone olmaya başlayın.

Uygulayın touchesMoved:ve birincinin gesturedikey (gerekirse ana görünümü kaydırın) veya yatay (burada menüyü göstermek istediğinizde) olup olmadığını kontrol edin. Yataysa, başka bir yöntem çağırmaya başlayın - (void)scrollAwayMainView:(NSUInteger)pixels, her touchesMoved:çağrıldığında, ana görünümün olması gereken başlangıç ​​noktasından uzak piksel sayısını hesaplayın ve bu sayıyı yönteme geçirin. Bu yöntemlerin uygulanmasında aşağıdaki kodu çalıştırın:

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

0

Bu soru için çözümüme göz atın:

Üçüncü taraf kitaplığı olmadan özel slayt menüsü nasıl oluşturulur?

Yalnızca alt sınıflara ayırmanız ve içerikle doldurmanız gereken tek bir sınıf.

İşte sınıf. Daha fazla ayrıntı için yukarıdaki bağlantıya bakın.

#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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.