Apa cara terbaik untuk mengembangkan menu samping seperti yang ada di aplikasi iOS baru Facebook?


155

Tampaknya menu geser samping menjadi elemen antarmuka yang lebih umum karena lebih banyak informasi dijejalkan ke setiap aplikasi iPhone. Facebook telah memasukkannya dalam versi terbaru mereka dan aplikasi Gmail baru tampaknya memasukkannya juga . Saya bertanya-tanya apakah ada yang memikirkan cara paling efisien untuk mengembangkan sesuatu seperti ini karena itu menjadi elemen antarmuka yang lebih umum. Sementara saya memiliki pemikiran sendiri tentang cara membangun ini, saya ingin tahu apa yang dipikirkan orang lain.

Navigasi gesek Facebook


Saya perhatikan, bahwa ketika menu sideswipe diaktifkan, Anda tidak dapat melakukan apa pun dengan menggesekkan bagian tampilan. Ide saya adalah membuat tampilan saat ini dalam gambar dan menampilkan bagian dari itu, ketika sidewipe diaktifkan
Denis

5
Profil Facebook siapa yang kamu intip, Nick O'Neill? :-p
Constantino Tsarouhas

1
kemungkinan duplikat dari SplitView tetapi pada iPhone
JosephH

1
@Zoidberg Saya tertarik mendengar lebih banyak tentang ini. Secara pribadi, saya suka sidenav! Tapi saya seorang pengembang, bukan desainer. Apa yang membuat UX ini buruk?
Robert Karl

3
Silakan ada yang menonton Merancang Pengalaman Pengguna Intuitif untuk mempelajari tentang masalah apa yang telah diidentifikasi apel dengan apa yang disebut "menu hamburger"
vikingosegundo

Jawaban:


34

Saya baru-baru ini menemukan ini, tidak benar-benar melihat kode atau menguji kontrol, tetapi sepertinya itu mungkin titik awal yang sangat baik.

jtrevealsidebar

Sunting: Pembaca juga harus melihat jawaban lain :)


Tidak mengizinkan pengguna untuk meluncur
cannyboy

6
Jika Anda mencari fungsi swipe. Masukkan pengenal isyarat ke tampilan kemudian ganti tombol sakelar dengan pengenal isyarat.
CJ Teuben

Tetapi bagaimana jika Anda ingin menggesek dan dapat beralih?
jsetting32

Ini dihentikan jadi saya akan pindah ke tempat lain.
Mike Flynn

84

Ada perpustakaan yang bagus untuk ini oleh Tom Adriaenssen: Inferis / ViewDeck

Ini sangat mudah digunakan dan memiliki pengikut yang cukup besar.

EDIT:

Untuk sesuatu yang sedikit lebih ringan, periksa: mutualmobile / MMDrawerController

Itu tidak memiliki semua fitur ViewDeck tetapi lebih mudah untuk memodifikasi dan memperluas.


6
Saya sarankan semua orang menggunakan ini.
Almas Adilbek

3
solusi terbaik: fleksibel dan mudah digunakan
HotJard

2
Saya mencobanya dan menemukan banyak Bug di Contoh mereka. Setelah beberapa klik cepat, viewcontrollers tidak selaras
Torsten B

13
Kami telah menggunakannya untuk beberapa aplikasi, tetapi sangat sulit untuk mempertahankan dan menambahkan fitur baru. Itu juga telah menderita karena mencoba menerapkan terlalu banyak. Kami memutuskan untuk menulis MMDrawerController kami sendiri. Ringan, dan fokus: github.com/mutualmobile/MMDrawerController
kcharwood

1
MMDrawerController adalah perpustakaan yang sangat bagus. Juga mendukung aplikasi universal. aplikasi iphone dan ipad
Erhan Demirci

48

Saya membuat perpustakaan untuk ini. Ini disebut MFSideMenu .

Antara lain itu termasuk dukungan untuk iphone + ipad, portrait + landscape, menu di sisi kiri atau kanan, UITabBarController, dan gerakan pan.


Ini adalah proyek yang hebat .. tetapi ini tidak mendukung untuk mode lansekap .. Bisakah Anda memberi kami petunjuk untuk menggunakannya dalam mode lansekap juga .. Terima kasih
Sameera Chathuranga

Terima kasih @ameeraChathuranga. Saya berharap dapat menambahkan dukungan lanskap jika saya punya waktu. Satu-satunya bagian yang tidak memiliki dukungan lansekap adalah SideMenuViewController ... Saya yakin Anda harus melakukan sesuatu seperti jawaban ke-2 di sini: stackoverflow.com/questions/2508630/… . Silakan garpu dan berkontribusi untuk repo!
Michael Frederick

Dan saya sarankan ini adalah jawaban untuk pertanyaan ini .. bukan yang di atas .. terlalu rumit .. ini sangat sangat mudah untuk ditangani :) jika seseorang ingin saya dapat memposting kode, cara bekerja dengan oriantation ..: )
Sameera Chathuranga

6
Bagi siapa pun yang tertarik, saya baru saja menambahkan dukungan lansekap ke perpustakaan.
Michael Frederick

1
@AlmasAdilbek, dapatkah Anda menjelaskan bagian aplikasi yang mengalami penurunan kinerja? Saya akan senang melakukan optimasi yang diperlukan.
Michael Frederick

29

Lihat MMDrawerController:

MMDrawerController

Kami tidak dapat menemukan perpustakaan yang kami sukai, jadi kami hanya menggulirnya sendiri.


10
Hanya ingin mengatakan bahwa ini DENGAN JAUH implementasi terbaik yang tercantum di sini. Orang yang baru mengenal utas ini: gunakan MMDrawerController.
mxcl

Hargai kata-kata baik itu!
kcharwood

Saya menggunakan ViewDeck dari satu tahun terakhir tetapi saya baru-baru ini beralih ke MMDrawerController dan saya merekomendasikan semua orang untuk menggunakan ini. Salah satu implementasi terbaik di perpustakaan secara keseluruhan. Terima kasih Kevin :)
Tariq

Memeriksa MMDrawerController ini dan ingin mengatakan bahwa itu benar-benar pilihan terbaik untuk menu samping. Dihargai! Terima kasih banyak kepada @Michael Frederick
Resty

Apakah ini mendukung iOS8? Terima kasih
Brad Thomas

12

The Ide kunci yang Anda harus bingkai set self.navigationController.view atau pusat . Ada dua acara yang harus Anda tangani. (1) barButtonItem tekan . (2) gerakan pan karena menggesek.

Anda dapat mengirim view controller ke latar belakang seperti ini:

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

Bekerja sempurna dan tanpa terlalu banyak kode. Anda hanya perlu menentukan batas di mana pengguna dapat menggeser sehingga tampilan Anda
Moisés Olmedo

@ Joan tuan tolong bantu saya kurang dalam hal ini selama beberapa hari
Ragul

Saya telah membuat menu sisi keluar dengan bantuan kode Anda di atas, ketika slide bagian belakang hanya menunjukkan warna gelap bukan pemandangannya tolong bantu saya
Ragul

Pak itu berfungsi dengan baik saya hanya menggunakan kode di atas ini. satu-satunya hal adalah tampilan latar belakang menunjukkan tidak saya telah terbalik itu tolong bantu saya untuk menunjukkan tampilan latar belakang
Ragul

@ János dan di mana harus menggunakan baris kode ini [self.view sendSubviewToBack: menuViewController.view];
Ragul


11

Implementasi Facebook menempatkan UIPanGestureRecognizer di UINavigationBar. Dengan demikian memungkinkan untuk menangkap gesekan di mana itu dibutuhkan.

Itu memungkinkan untuk melakukan hal-hal seperti, mengenali arah sentuhan dalam x / z secara langsung serta kecepatan yang terjadi.

Juga semacam mengutak-atik UIViews (lebih dari satu di layar pada satu waktu dengan tugas yang jelas berbeda -> dengan demikian pengendali yang berbeda) harus (saya tergoda untuk mengatakan) menggunakan fitur baru ViewController-Containment iOS. Setiap implementasi tanpa itu sangat buruk karena mengotak-atik hierarki tampilan dengan cara yang tidak dimaksudkan oleh Apple.

Pada sidenote: Jika Anda benar-benar ingin tahu tentang bagaimana hal itu dapat dilakukan sedekat mungkin dengan cara Facebook, periksa proyek yang saya buka bersumber di Github PKRevealController .


Tidak ada yang salah (atau HIG tidak patuh) dengan mengelola UI khusus berbasis UIView. Lihat pengontrol kontainmen datang terlambat, sehingga banyak pendekatan lain telah digunakan. Artikel terkait: blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers
Jacob Jennings

1
Perkembangan besar tidak akan menargetkan versi minimum iOS 5 untuk waktu yang lama, karena sejumlah besar pengguna tidak akan meningkatkan untuk waktu yang sangat lama. Walaupun banyak dari mereka adalah 'peretasan' seperti yang Anda katakan, itu pasti dapat dilakukan dengan benar. Tetap berada dalam kerangka kerja jelas merupakan taruhan yang aman, tetapi kadang-kadang UI yang unik dan kustom membutuhkan lebih banyak.
Jacob Jennings

8

Ada puluhan perpustakaan berbeda yang telah dibuat pengembang untuk mengimplementasikan navigasi gaya Facebook / Path untuk aplikasi iOS. Saya dapat mendaftar semuanya tetapi karena Anda telah meminta yang terbaik, berikut adalah dua pilihan saya yang saya gunakan untuk menerapkan menu navigasi geser samping:

1) ECSlidingViewController Sangat mudah untuk mengimplementasikan dan menggunakan Storyboard juga. Saya belum memiliki masalah dalam mengimplementasikannya atau menerima kesalahan atau hal seperti itu. Tautan yang saya berikan memiliki hampir semua penjelasan untuk menggunakannya.

2) SWRevealViewController Perpustakaan ini mudah digunakan dan Anda dapat menemukan tutorial DI SINI , yang menunjukkan cara menerapkannya dengan semua penjelasan beserta gambar. Anda bisa mengikuti tutorial dan terima kasih saya nanti.


1
SWRevealViewController adalah yang paling sederhana, menggunakannya tidak ada bug berfungsi dengan baik
vishal dharankar

7

Pilihan lain adalah menggunakan Scringo . Ini memberi Anda menu samping seperti di aplikasi youtube / facebook, dan juga semua jenis fitur bawaan di menu yang dapat Anda pilih untuk ditambahkan (mis. Ngobrol, undang teman, dll ...)

Menambahkan menu samping cukup dengan memanggil [ScringoAgent startSession ...] dan semua konfigurasi dapat dilakukan di situs.



4

Pertanyaan ini cukup populer tetapi semuanya berujung pada pengimporan dan penggunaan yang mudah bagi saya ... Inilah yang saya gunakan ... SWRevealController .

Saya terkejut orang-orang melewatkannya ... Ini SANGAT HEBAT !!! dan mudah digunakan. Pengembang bahkan menyertakan beberapa contoh proyek yang memungkinkan Anda melihat cara menggunakannya dalam berbagai skenario.



2

Baik Gmail dan Facebook banyak menggunakan tampilan web, jadi sulit untuk mengatakan apa kode asli dan apa yang dirender HTML. Namun, melihat antarmuka, sepertinya mereka telah menempatkan UITableView dengan lebar lebih sempit daripada lebar layar (320pt) di bawah UIView yang berisi konten yang ingin ditampilkan. Memilih baris tableview yang berbeda mungkin mengganti subview dari tampilan konten.

Setidaknya, itulah cara saya mendekati masalah. Sulit untuk menentukan apa yang seharusnya. Langsung saja masuk dan mulailah bereksperimen!


hei ada yang bisa memberi tahu saya cara membuat tampilan tipe swipe facebook dan panel menu di android
Neerav Shah

1

Jika Anda mau, saya melakukan repo ini di github GSSlideMenu. Ini memungkinkan Anda untuk membuat menu bergaya Facebook TETAPI dengan "kembali" webView (umumnya semua repo yang saya temukan memiliki tableView sebagai tampilan "kembali").



1

tampilan di sebelah kanan bisa di dalam subkelas dari UIScrollView. Dalam subkelas ini Anda dapat menimpanya- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event untuk mengembalikan YA hanya jika pengguna menyentuh subview tersebut. Dengan cara ini Anda dapat menempatkan UIScrollView transparan Anda di atas tampilan lain dan melewati setiap acara sentuh yang terjadi di luar subview; dan Anda mendapatkan barang-barang gulir gratis.

Sebagai contoh:

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

atau:

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

1

Coba tambahkan menu Anda (yang Anda geser ke sana) di bawah tampilan utama. Mulai berlangganan untuk menyentuh acara di tampilan.

Terapkan touchesMoved:, dan periksa untuk melihat apakah yang pertama gestureadalah vertikal (gulir tampilan utama, jika perlu), atau horizontal (di sini Anda ingin menampilkan menu). Jika itu horisontal, mulailah memanggil metode lain - (void)scrollAwayMainView:(NSUInteger)pixels,, kapan touchesMoved:pun dipanggil, menghitung jumlah piksel dari titik awal tampilan utama seharusnya, dan meneruskan angka itu ke dalam metode. Dalam implementasi metode tersebut, jalankan kode berikut:

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

0

Lihat solusi saya untuk pertanyaan ini:

Bagaimana cara membuat menu slide khusus tanpa perpustakaan pihak ketiga.?

Satu kelas tunggal yang Anda hanya perlu subkelas dan isi dengan konten.

Ini kelasnya. Untuk detail lebih lanjut, lihat tautan di atas.

#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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.