Ionic 데스크톱 네이게이션 뷰

이상훈
상훈 Devlog
Published in
7 min readAug 23, 2020

아이오닉을 통해 앱을 개발하다보면 탭 메뉴라던지 네이게이션 툴바가 모바일 중심으로 화면이 구성된다. 그러다보니 모바일이 아닌 데스크톱 웹사이트를 확인해보면 어색하게 느껴진다.

화면 크기에 따라 모바일 뷰로 나타나거나 데스크톱 뷰로 나타나도록 할 필요가 있게된다.

화면 사이즈가 변경될 때마다 컴포넌트/레이아웃이 달라진다.

화면 크기 체크하기

CheckDesktopService는 현재 화면이 데스크톱 크기인지 아닌지를 판단할 수 있는 isDesktop$ 옵저버블을 가지고 있다. 예시에서는 화면 width가 568 이상일때 데스크톱 뷰라고 판단한다.

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class CheckDesktopService {
private isDesktopSource = new BehaviorSubject<boolean>(true);
isDesktop$ = this.isDesktopSource.asObservable();
mobileWidth = 568;
constructor() { }setIsDesktop(width) {
if (width < this.mobileWidth) {
this.isDesktopSource.next(false);
} else {
this.isDesktopSource.next(true);
}
}
}

isDesktop 구독

CheckWithDesktop 서비스의 setIsDesktop을 호출하여 서비스 로드 시 뷰를 정한다. 그 다음 isDesktop$옵저버블을 구독하여 클래스 변수인isDesktop에 그 값을 할당한다.

서비스 로드 시 뷰를 초기화 했다면 화면의 사이즈가 변경 될 때마다도 setIsDesktop을 호출하여 뷰를 새롭게 구성할 수 있도록 한다.

화면 사이즈가 변경되는 이벤트를 처리하기 위해서 @HostListener를 통해 window:resize에 대한 이벤트 처리기를 정의하면된다.

import { Component, HostListener, OnInit } from '@angular/core';
import { CheckWidthService } from './../../app/check-width.service';
@Component({
selector: 'tabs',
templateUrl: 'tabs.page.html',
styleUrls: ['tabs.page.scss']
})
export class TabsPage implements OnInit {
isDesktop = true;
constructor(
private cws: CheckWidthService
) { }
ngOnInit() {
this.cws.setIsDesktop(window.innerWidth);
this.cws.isDesktop.subscribe(resp => this.isDesktop = resp);
}
@HostListener('window:resize', ['$event'])
private onResize(event) {
this.cws.setIsDesktop(event.target.innerWidth);
}
}

isDekstop 활용하기

이제 isDesktop 변수를 통해 데스크톱 뷰인지 모바일 뷰인지 판단할 수 있기 때문에 이를 사용하여 뷰를 적절히 구성하면된다.

다음 예시는 모바일 뷰에서는 하단 탭 메뉴를, 데스크톱 뷰에서는 상단 네비게이션 바를 적용한 것이다.

<!-- mobile view -->
<ng-container *ngIf="!isDesktop">
<ion-tabs>
<ion-tab-bar slot="bottom">
<ng-container *ngFor="let tab of tabs">
<ion-tab-button [tab]="tab.name">
<ion-icon [name]="tab.icon" style="font-size: 25px;"></ion-icon>
<ion-label>{{tab.label}}</ion-label>
</ion-tab-button>
</ng-container>
</ion-tab-bar>
</ion-tabs>
<ion-header class="ion-no-border">
<ion-grid fixed style="padding: 0px">
<ion-toolbar>
<ion-title mode=ios>
<a style="text-decoration: none; cursor: pointer;" [routerLink]="'/tabs/home'">
<img src="../../../assets/icon/favicon.png" height="32">
</a>
</ion-title>
<ion-buttons slot="end">
<ion-button>
<ion-icon slot="icon-only" name="search-outline" class="icon"></ion-icon>
</ion-button>
<ion-button [routerLink]="'/tabs/more'">
<ion-icon slot="icon-only" name="person-circle-outline" class="icon"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-grid>
</ion-header>
</ng-container>
<!-- desktop view -->
<ng-container *ngIf="isDesktop">
<ion-header class="ion-no-border">
<ion-grid fixed>
<ion-toolbar>
<ion-title>
<a style="text-decoration: none; cursor: pointer;" [routerLink]="'/tabs/home'">
<img src="../../../assets/icon/favicon.png" height="32"></a>
</ion-title>
<ion-buttons slot="secondary">
<ng-container *ngFor="let tab of desktopMenus">
<ion-button [routerLink]="'/tabs/'+tab.name">
{{tab.label}}
</ion-button>
</ng-container>
<ion-button>
<ion-icon slot="icon-only" name="search-outline"></ion-icon>
</ion-button>
<ion-button [routerLink]="'/tabs/more'">
<ion-icon slot="icon-only" name="person-circle-outline"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-grid>
</ion-header>
<ion-router-outlet></ion-router-outlet>
</ng-container>

아이오닉을 통해 별다른 처리없이 모바일 앱에 적당한 탭 메뉴, 레이아웃 등을 구성하였을 때 데스크톱 웹에서는 보면 이질감이 생기거나 UX적인 측면에 맞지 않는 부분들이 존재하게 된다.

모바일 앱과 데스크톱 웹사이트를 모두 동시에 서비스 중이라면 각각의 화면 크기에 따라 뷰와 레이아웃을 구성하면 이질감 없이 유저들이 사용할 수 있을 것이다.

--

--

이상훈
상훈 Devlog

Frontend Developer 😁😁 #angular #javascript #typescript #scala #node