^(코딩캣)^ = @"코딩"하는 고양이;

[iOS・iPadOS] iOS 앱에서도 안드로이드처럼 DrawerLayout(사이드 메뉴) 만들기

API/Cocoa
2021. 8. 15. 15:10

iOS・iPadOS

이전 게시글: 앱에 커스텀 폰트(custom font) 적용하기.

 

iOS 앱에서도 안드로이드처럼 DrawerLayout(사이드 메뉴) 만들기

안드로이드에서는 라이브러리 차원에서 DrawerLayout, 일명 사이드 메뉴 또는 햄버거(hamburger) 버튼에 해당하는 메뉴 인터페이스가 지원되지만, iOS 쪽에는 그와 똑같은 기능이 따로 없다. iOS에서 DrawerLayout에 해당하는 인터페이스를 만들려면 써드 파티 라이브러리를 끌어오거나 다른 곳에서 코드를 복사/붙여넣기하는 방법 등 여러가지 길이 있겠으나 여기에서는 별도 라이브러리 없이 이와 유사한 인터페이스를 만들어보도록 하겠다.

 

1 단계. 내비게이션 뷰 컨트롤러(Navigation View Controller) 구성하기

앱 화면의 상단에 햄버거 버튼을 만들어야 하므로 앱의 인터페이스에 내비게이션을 적용한다. Xcode에서 기본으로 만들어 준 뷰 컨트롤러를 그대로 둔 채 [Editor] - [Embed In] - [Navigation Controller]를 클릭한다.

앱 인터페이스에 내비게이션을 적용한다.

 

Entry Point와 빈 화면 사이에 Navigation Controller가 새로 끼어들면서 기존의 빈 화면은 두 번째로 밀려났다. 이 두 번째 화면에 DrawerLayout과 비슷한 레이아웃을 구성한다. 다음과 같이 최상위 뷰(View)의 아래에 두 개의 뷰(View)를 두는데 하나의 뷰에는 기본적인 화면을 구성하고 또 다른 뷰에는 사이드 메뉴를 구성한 다음 그 두 개의 뷰를 포갠다. 사이드 메뉴로 쓰일 뷰의 폭은 다소 좁게 지정할 수 있는데 여기서는 300으로 지정한다. 좀 더 확실한 구별을 위해 사이드 메뉴로 쓰일 뷰의 배경은 오렌지 색으로 칠했다.

DrawerLayout을 고려하여 레이아웃을 작성한다.

그 다음 네비게이션 바의 좌측에 햄버거 버튼을 추가한다. 햄버거 버튼에 사용할 이미지를 구해서 넣는 과정까지는 생략한다. 혼동하지 말아야 할 것은 내비게이션 바에 추가되는 버튼의 형식은 UIBarButtonItem이라는 것이다. 이것을 내비게이션 바의 좌측에 추가한다.

내비게이션 바에 Bar Button Item을 추가한다(1).
내비게이션 바에 Bar Button Item을 추가한다(2).
내비게이션 바에 Bar Button Item을 추가한다(3).

 

2 단계. 로직 구성하기

겉 모습은 대강 위와 같이 만들어졌으므로 이제 코딩을 할 차례이다. 햄버거 버튼을 클릭할 때마다 사이드 메뉴가 나타나거나 사라지거나 해야 하는데, 이 방법에는 여러 가지가 있겠으나 여기에서는 constraint를 사용해서 사이드 메뉴의 폭을 유지한 채로 좌우로 이동시키는 방식을 사용하겠다. 다시 적으면, 평소에는 사이드 메뉴가 화면 바깥으로 완전히 나가 있다가 햄버거 버튼을 누르면 화면에 나타나도록 constraint를 조정하고 다시 햄버거 버튼을 누르면 사이드 메뉴를 화면 바깥으로 완전히 이동시키는 방식이다.

사이드 메뉴가 화면 안으로 들어왔을 때의 leading constraint.
사이드 메뉴가 화면 밖으로 벗어났을 때의 leading constraint. 

 

이와 같은 작동을 구현하기 위해 다음과 같이 최소한 2개의 IBOutlet과 1개의 IBAction이 필요하다.

class ViewController: UIViewController {
    // sidebarView의 폭을 정의하는 상수입니다.
    let sidebarViewWidth = 300
    
    // ...

    // 사이드 메뉴를 포함하고 있는 뷰(오렌지색 배경의 뷰)입니다.
    @IBOutlet var sidebarView: UIView!
    // sidebarView와 super view 사이에 적용되고 있는 Leading Constraint입니다.
    @IBOutlet var sidebarViewLeadingConstraint: NSLayoutConstraint!

    // ...

    // 햄버거 버튼을 터치할 때마다 수행될 작동이 정의된 메소드입니다.
    @IBAction func hamburgerNavigationItemTouchDown(_ sender: Any) {
        
    }
}

 

Objective-C로는 다음과 같이 적을 수 있다.

// ViewController.m
// sidebarView의 폭을 정의하는 상수입니다.
#define SIDEBAR_VIEW_WIDTH 300
// ...
@interface ViewController ()
// 사이드 메뉴를 포함하고 있는 뷰(오렌지색 배경의 뷰)입니다.
@property(atomic) IBOutlet UIView * sidebarView;
// sidebarView와 super view 사이에 적용되고 있는 Leading Constraint입니다.
@property(atomic) IBOutlet NSLayoutConstraint * sidebarViewLeadingConstraint;
@end

@implementation ViewController
// 햄버거 버튼을 터치할 때마다 수행될 작동이 정의된 메소드입니다.
- (IBAction)hamburgerNavigationItemTouchDown:(id)sender {
    
}
@end

 

ViewController 클래스에서 선언한 총 3개의 메소드 및 변수들을 스토리보드와 reference 시킨다.

코드에서 작성한 멤버와 스토리보드 요소 사이를 reference 시킨다.

 

사이드 메뉴를 화면에 나타나도록 작동하는 코드는 다음과 같이 작성한다. 사이드 메뉴 뷰와 super view 사이에 적용되는 leading constraint 값을 0으로 하면 된다.

func showSidebarView() {
    sidebarViewLeadingConstraint.constant = 0
    
    // 애니메이션 효과
    UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseIn, animations: {
        self.view.layoutIfNeeded()
    })
}

 

Objective-C로는 다음과 같이 적을 수 있다.

- (void)showSidebarView {
    self.sidebarViewLeadingConstraint.constant = 0;
    
    [UIView animateWithDuration: 0.5
                          delay: 0.0
                        options: UIViewAnimationOptionCurveEaseIn
                     animations: ^{[self.view layoutIfNeeded];}
                     completion: nil];
}

 

사이드 메뉴를 화면 밖으로 치우는 코드는 다음과 같이 작성한다. 사이드 메뉴 뷰와 super view 사이에 적용되는 leading constraint의 값을 사이드 메뉴의 폭이나 더 넓은 값으로 지정하되, 음수로 지정한다.

func hideSidebarView() {
    sidebarViewLeadingConstraint.constant = -CGFloat(sidebarViewWidth)
    
    // 애니메이션 효과
    UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseIn, animations: {
        self.view.layoutIfNeeded()
    })
}

 

Objective-C로는 다음과 같이 적을 수 있다.

- (void)hideSidebarView {
    self.sidebarViewLeadingConstraint.constant = -(CGFloat)SIDEBAR_WIDTH;
    
    [UIView animateWithDuration: 0.5
                          delay: 0.0
                        options: UIViewAnimationOptionCurveEaseIn
                     animations: ^{[self.view layoutIfNeeded];}
                     completion: nil];
}

 

햄버거 메뉴를 클릭할 때마다 사이드 메뉴에 적용된 leading constraint의 값이 음수인지 여부를 탐지하여 보이거나 감출 수 있다.

@IBAction func hamburgerNavigationItemTouchDown(_ sender: Any) {
    if (sidebarViewLeadingConstraint.constant < 0) {
        showSidebarView()
    } else {
        hideSidebarView()
    }
}

 

Objective-C로는 다음과 같이 적을 수 있다.

- (IBAction)hamburgerNavigationItemTouchDown:(id)sender {
    if (self.sidebarViewLeadingConstraint.constant < 0) {
        [self showSidebarView];
    } else {
        [self hideSidebarView];
    }
}

 

DrawerLayout(Sidebar) 작동 영상.

 

카테고리 “API/Cocoa”
more...