상세 컨텐츠

본문 제목

[android] 안드로이드 N, 안드로이드 7 이상 화면 사이즈 변경에 따른 대응 방법 관련

스마트기기개발관련/안드로이드 개발

by AlrepondTech 2018. 4. 3. 17:19

본문

반응형
728x170

 

 

=================================

=================================

=================================

 

 

 

출처:  https://developers-kr.googleblog.com/2016/05/designing-for-multi-window.html

 

다양한 기능들이 Android N에 추가됩니다. 그 중, 개발자들이 활용할 수 있는 가장 도드라지는 기능 중 하나가 바로 멀티윈도우 지원입니다.

Android N은 다양한 멀티윈도우 모드를 지원하지만, 그 중, 스마트폰과 태블릿에서 활용할 수 있는 분할 화면 모드를 잘 지원하는 것이 가장 핵심이 될 것입니다. 이 모드에서는 두 개의 앱이 동시에 실행될 수 있으며, 사용자가 나누어져 있는 두 화면 사이의 칸막이를 끌어 앱의 크기를 조절할 수 있습니다. 네. 예상하신 것처럼, 이 모드를 올바르게 지원하기 위해서는 지금까지와는 다른 디자인상의 도전적 과제를 해결해야 합니다.

 

훨씬 더 빠르게 반응하는 UI

이전 버전의 Android, 모바일 웹, 그리고 데스크톱 환경에서 배운 교훈들이 Android N에도 여전히 적용되고 있습니다. 반응형 UI를 디자인하는 것이 멀티윈도우 환경 지원을 향한 중요한 첫 걸음입니다.

 


반응형 UI란 어떤 기기나 화면 크기에서도 훌륭한 사용자 환경을 창출하기 위해 가장 적절한 탐색 패턴과 콘텐츠 표현 양식이 선택될 수 있게 주어진 사이즈에 적응하는 UI입니다. 다음 블로그 게시물에 반응형 UI 빌드하기에서 효과적인 반응형 UI 디자인과 빌드 방법에 대해 자세히 알아보세요.
 

레이아웃 조정

어떤 사이즈의 화면을 디자인하든, 화면 크기가 변화될 때 발생하는 이벤트 처리를 분할 화면 레이아웃 가이드라인에 설명된 것처럼 매끄럽고 끊김 없이 넘어가도록 만드는 것이 중요합니다. 이미 모바일과 태블릿 간에 비슷한 레이아웃을 가지고 있다면, 상당히 많은 작업들이 자동으로 처리되어 있는 것을 알게 될 것입니다.

하지만 모바일과 태블릿의 레이아웃이 서로 크게 다르다면, 사용자가 화면 크기를 조정할 때 마다 앱의 UI가 크게 변경되거나 서로 뒤섞이지 않도록 주의해야합니다. 사용자들이 앱의 크기를 조절할 때 마다 UI에 대해 다시 배울 필요가 없도록 해야 합니다.

minimalHeight와 minimalWidth 레이아웃 특성을 통해 액티비티가 지원할 수 있는 최소 크기를 설정할 수 있지만, 이것이 사용자가 액티비티를 해당 값 보다 더 작게 만들 수 없다는 의미는 아닙니다. 사용자가 화면 크기를 더 작게 만들면, 지정된 최소 크기외의 앱의 다른 부분은 잘려나간다는 것을 의미합니다. 따라서, 필수적인 UI의 요소들이 화면에 표시되지 못할 수도 있습니다. 그러므로, 언제나 사용자가 여러분의 앱의 핵심 기능을 불편함없이 사용할 수 있도록, 최소 크기 220x220dp까지는 지원하도록 해야 할 것입니다.

고려할 디자인 구성

멀티윈도우에서 가능한 크기 및 가로 세로의 비율 중 많은 것들이 기존의 기기와 비슷하지만(가로 방향 태블릿의 1/3이 기존 모바일 기기와 화면 크기가 비슷함), 멀티윈도우를 고려할 때 훨씬 더 보편적인 구성이 몇 가지 있습니다.

 


첫째는 세로 방향 모바일 기기에서의 16x9 레이아웃입니다. 이 경우 세로 공간이 극히 제한됩니다. 차곡차곡 쌓여있는 고정 요소들이 많이 있을 경우(툴바, 콘텐츠 스크롤, 하단의 탐색 모음), 사실상 스크롤하는 콘텐츠를 위한 공간이 없다는 것을 발견할 것입니다. 이게 가장 중요한 부분인데 말이죠!

두 번째로 고려해야 할 경우는 태블릿의 34.15% 레이아웃입니다. 세로 방향 기기에서는 매우 넓고, 가로 방향 기기에서는 매우 높은 이 가로 세로 비율은 기존의 기기에서 볼 수 있는 것보다 더 심각합니다. 이 구성을 위한 출발점으로 모바일 레이아웃을 사용하는 것을 고려해 보세요.
 

피해야 할 패턴

멀티윈도우 디자인에서 전적으로 피해야 할 몇 가지 패턴이 있습니다.

첫째, 화면 가장자리로부터의 스외이프에 의존하는 UI입니다. 이는 (Nexus 기기 등의) 많은 기기에서 두드러진 화상 탐색 모음의 경우 이미 어느 정도 이슈가 되었었는데, 분할 화면 모드에서는 더 큰 문제가 됩니다. 액티비티가 맨 위에 있는지 맨 아래에 있는지, 왼쪽에 있는지 오른쪽에 있는지 (단호하게) 판단할 길이 없으므로 앱에서 가장자리 스와이프를 기능에 액세스하는 유일한 방법으로 삼지 마세요.그렇다고 가장자리 스와이프를 완전히 사용하지 말라는 뜻은 아닙니다. 반드시 대안을 마련하라는 겁니다. 이것의 좋은 예는 탐색 서랍 버튼입니다. 가장자리 스와이프로 서랍을 열지만, 툴바에서 햄버거 아이콘을 눌러서 열 수도 있습니다.

두 번째는 멀티윈도우를 완전히 비활성화하는 것입니다. 이 방법을 피할 수 없는 경우가 분명히 있지만(게임 등에서처럼 근본적으로 몰입적인 경험이 되므로), 여러분의 액티비티와 그 액티비티로부터 시작된 액티비티가 멀티윈도우를 지원하도록 강요되는 경우도 있습니다. 멀티윈도우 준비하기란 제목의 블로그 게시물에서 언급했듯이, 외부 앱에서 액티비티가 시작되도록 지원할 경우, 그 액티비티는 호출하는 액티비티의 멀티윈도우 속성을 상속합니다.



멀티윈도우 디자인은 모든 기기를 위한 디자인

반응형 UI는 개발은 훌륭한 멀티윈도우 환경을 위해서도 매우 중요하지만, 근본적으로 다양한 Android 기기에 걸쳐 모든 사용자들에게 혜택을 줄 수 있는 지침입니다.

그러므로 이것을 #BuildBetterApps의 기회로 삼으십시오.

Android 개발 패턴 모음을 팔로우하여 더 자세히 알아보세요!
 
 

 

=================================

=================================

=================================

 

 

출처: https://thdev.tech/androiddev/2016/03/29/Android-N-Preview-Multi-Window.html

 

 

Edit. 2016. 04. 14 Preview 2 버전이 나오면서 변경된 사항을 업데이트 합니다.

  • 일부 API 이름 변경

 

안드로이드 N에서 정식으로 Multi Window를 제공합니다. N에 숨겨진 멀티 윈도 기능도 있는데 그 기능을 사용하는 방법도 함께 적어보겠습니다.

Google - lan Lake가 Medium 작성 글 “5 tips for preparing for Multi-Window in Android N” 을 참고하시면 좋을 것 같습니다. 저는 주요 코드와 설명을 작성하도록 하겠습니다.(5가지 팁 중에 중요한 내용 포함…)

 

Android N Multi Window

Android N에 포함된 Multi Window는 Andoid M에도 있었습니다. 초기 버전에만 존재하는데 Nexus 6p에서만 확인이 되었던 적이 있습니다. 개발자 옵션에 잠시 포함되었다가 11월 패치쯤에 해당 기능이 사라졌었습니다.

동작 방식은 태스크에 표시된 미리 보기 창에 멀티윈도우 옵션을 제공하고, 이를 동작하는 정도였습니다.

이러한 기능이 좀 더 안정적으로 Android N에 정식으로 포함되었습니다. Android N에서는 폰과 Tablet에 제공하게 되는데 Tablet에서는 좀 더 PC처럼 사용할 수 있는 기능이 OFF로 숨겨져 있습니다. (이 기능은 아래쪽에 설명하도록 하겠습니다.)

 

Multi Window Support

Preview 문서 : Multi Window Support

스마트폰 : 스마트폰에서는 상/하 모드로 Split-Screen mode를 지원합니다. 구글 문서에 나와 있는 사진입니다. 아래와 같이 화면 분할이 되고, 기존 Overview screen(태스크?) 모양이 2개의 네모로 분리됩니다.

 

Tablet은 별도의 설명이 없습니다. 기본 기능은 모두 스마트폰과 동일하게 동작합니다. 다만 태블릿에서는 화면 회전을 지원하지 않을 경우 분할 모드를 지원하지 않습니다.

SDK를 통해 멀티윈도우를 제어할 수 있습니다. 창의 최소 사이즈를 정할 수 있고, 멀티 윈도우를 사용하지 않도록 지정할 수 있습니다.

 

TV Device : Picture-in-picture(PIP) 모드를 지원합니다.

TV Device에서 사용할 수 있는 Picture-in-picture(PIP)는 영상을 시청 중에 다른 행동을 할 수 있습니다. 영상을 틀어놓고 사진을 볼 수 있는데 일반적인 TV/모니터의 PIP 기능이라고 볼 수 있겠습니다.(팝업 플레이어? 정도라고 생각할 수도 있겠네요) Picture-in-picture 구글 문서에 나와있는 사진입니다.

 

 

Activity Lifecycle

Multi-window mode를 지원한다고 해서 별도로 달라지는 Lifecycle은 없다고 합니다. 기본 Android Activity의 Lifecycle을 따른다고 합니다.

그래서 현재 동영상을 시청하는데 있어서 멀티윈도우가 정상 동작하지 않습니다. 멀티윈도우 상태에서 동영상을 시청하려고 틀어놓고 다른 행동을 하려고 시도하였는데 이렇게 동작하였습니다.(문서상 내용도 비슷합니다.)

  • 동영상 APP을 실행하여 동영상을 플레이합니다.
  • 멀티 윈도우의 다른 화면을 눌러줍니다.
  • 동영상은 재생이 멈춥니다.

하나씩 Android Lifecycle대로 설명하면 다음과 같습니다.

  • 동영상을 정상으로 Player 하였습니다.(onResume 상태입니다.)
  • 멀티윈도우의 다른 화면을 눌러줍니다. 이때 동영상의 화면은 onPause()를 타게 됩니다.
  • 선택한 다른 화면이 onResume()를 타고 정상적으로 사용 가능해집니다.

Google Note.

화면이 보이기 때문에 onStop()이 불리지는 않습니다. 문서의 Note에는 다음과 같은 Tip을 제공하고 있습니다.

  • Player 하기 위해서 onPause()에서는 일시정지/정지 하지 않도록 한다.
  • onStop()으로 일시정지/정지하도록 한다

위와 같이 처리해주면 onPause()가 되더라도 동영상 플레이는 유지되고, 화면이 보이는 상태이기 때문에 onStop()이 호출되지는 않습니다. 다시 돌아왔을 때도 onResume()에서 동영상 재생을 하지 않고, onStart()에서만 start를 하도록 해주면 onPause와 onResume이 왔다 갔다 하는 상항에서도 문제없이 플레이가 가능해집니다.

아직은.. Google App도 이렇게 동작하지 않아서 확인은 불가능합니다.. 저도 아직 직접 확인해보지 않은 내용이라서… 일단 문서상…

Handling Runtime Changes에 관한 내용도 담고 있습니다. 자세한 내용은 문서를 참조해주세요.

 

Configuring Your App for Multi-Window Mode

Multi-Window 모드는 개발자가 직접 컨트롤 할 수 있습니다. 멀티윈도우를 지원하지 않을 수도 있고(현재 Preview에서는 모두 다 지원하도록 되어 있어서 정식 버전에 어떻게 적용될지 아직은 모르겠습니다.) 지원하면서 최소 사이즈를 지정할 수 있습니다.

AndroidManifest.xml에서 다음을 정의하면 Multi-Window를 지원/해제 할 수 있습니다.

android:resizeableActivity=["true" | "false"] 

이 코드를 <actiity> 또는 <application>에 각각 넣을 수 있습니다. application이 false 이면 해당 앱은 false가 기본으로 처리되어 멀티 윈도우가 동작하지 않습니다. activity 기반으로도 각각 페이지별 true/false를 적용하게 되면 동작이 다르게 되는 것이죠.

그래서 저는 이런 방법을 시도해보았습니다.

  • A Activity에서는 true
  • B Activity에서는 false

아직 Preview라서 그런지 첫 번째 Activity에 맞게 B Activity가 동작을 하였습니다. 다시 말하면 B는 true/false이 든 상관없이 동작하였습니다.

저런 식의 화면 구성을 하고 싶어 하시는 분이 있을 것 같습니다. 특정 화면은 집중을 요해서 전체 화면으로 구성을 하고 싶은 경우입니다. 그런데 이 경우는 별로 추천하지는 않을 것 같지만.. 현재 <activity>에 true/false를 지원하는 것을 보아 가능할 것 같습니다.

Picture-in-picture 역시 아래와 같습니다.

android:supportsPictureInPicture=["true" | "false"] 

화면 사이즈 정의

화면 사이즈 구성이 가능합니다. 아래와 같은 설정이 가능합니다. Google 문서상 freeform mode라는 이름으로 다음을 정의하고 있습니다.

android:defaultWidth android:defaultHeight android:gravity android:minimalHeight android:minimalWidth  <!-- Preview 2 change --> <!-- Remove API Name : android:minimalSize --> <!-- Add API Name : android:minimalWidth --> <!-- Add API Name : android:minimalHeight --> 

AndroidManifest.xml에 다음과 같이 정의합니다.

<activity android:name=".MyActivity">    <layout        android:defaultHeight="500dp"        android:defaultWidth="600dp"        android:gravity="top|end"        android:minimalHeight="450dp"        android:minimalWidth="300dp" />     <!-- Preview 2 change -->    <!-- Remove API Name : android:minimalSize -->    <!-- Add API Name : android:minimalWidth -->    <!-- Add API Name : android:minimalHeight --> </activity> 

freeform mode는 화면 자체를 자유롭게 이동할 수 있는 모드입니다. 사실 이 옵션(freeform mode)은 OFF되어 있습니다. xml 정의는 제공하고 있는 것 같습니다. 이 모드는 아래에서 설명을 하겠습니다.

 

Disable features in multi-window mode

다음의 경우는 Multi-window를 지원하지 않습니다. 저도 위에서 언급하였는데 screenOrientation을 설정하였을 경우에는 multi-window를 제공하지 않는다고 합니다.

 

Multi-window change notification and querying

Multi-window 모드 API가 있습니다. 저도 아직 자세하게 알아보지는 않았는데 API 문서 링크는 아래와 같습니다.

Android N Preview API

현재 모드가 멀티 윈도우인지 확인할 수 있습니다.

// Preview 2 API 이름 변경 // Activity.inMultiWindow() Activity.isInMultiWindowMode() 

 

PictureInPicutre 모드인지 확인합니다. Note: isInPictureInPictureMode() 모드가 true라면 isInMultiWindowMode() 역시 true가 return 된다고 합니다.

// Preview 2 API 이름 변경 // Activity.inPictureInPicture() Activity.isInPictureInPictureMode() 

 

true 일 경우 현재 MultiWindow 모드가 활성화 되고, false라면 MultiWindow에서 일반 모드로 변경됩니다.

// Preview 2 API 이름 변경 // Activity.onMultiWindowChanged() Activity.onMultiWindowModeChanged() 

 

onMultiWindowChanged와 기본 동작은 동일합니다.

// Preview 2 API 이름 변경 // Activity.onPictureInPictureChanged() Activity.onPictureInPictureModeChanged() 

추가로 Fragment에서도 동일하며 Fragment.isInMultiWindowMode()입니다.

 

Etc

// Flag 이름 변경 FLAG_ACTIVITY_LAUNCH_ADJACENT -> FLAG_ACTIVITY_LAUNCH_TO_ADJACENT 앱을 실행과 동시에 Multi-Window 모드를 사용할 수 있습니다. Intent.FLAG_ACTIVITY_LAUNCH_TO_ADJACENT 을 통해서 Multi-window를 실행할 수 있습니다. 자세한 내용은 API를 참고해주세요.

 

drag and drop 모드 지원

삼성 멀티윈도우와 같은 파일 복사? 기능을 제공합니다. Multi-window 간 퍼미션을 요청하여 URI을 전달하는 drag and drop 모드입니다.

 

Tip 5

5 tips for preparing for Multi-Window in Android N 에 소개되어 있는 5개 Tip 중에 가장 중요하다고 생각되는 부분을 소개하려고 합니다. 나머지 내용은 원문을 참고해주세요^^;;
Pro-tip 1 번에 해당하는 내용입니다. Google에서도 다음과 같이 하라고 하더군요.

Loading the proper resources requires the proper Context. If you’re using the Activity context for inflating your layouts, retrieving resources, etc, then you’re good to go. However, if you’re using your Application context for anything UI related, you’ll find that the resources that are loaded are blissfully unaware of multi-window. Besides issues with not using your Activity’s theme, you may be loading the wrong resources entirely! Best to keep your UI stuff with the Activity Context.

원문은 위와 같습니다. Multi-window의 지원으로 주의해야 할 부분이 context 사용 방법입니다. UI를 다룰 경우에는 Application context가 아닌 Activity의 context를 사용하라고 합니다. Application context를 사용하였을 경우 Activity 기반의 theme가 아니라 원하지 않는 theme가 나올 수 있으니 Application context가 아니라 Activity context을 사용하라고 합니다.

onResume()에서 너무 많은 처리를 하지 말 것을 강조합니다. 화면의 이동 간 onResume() onPause()는 매번 호출되게 됩니다. 멀티윈도우 사이즈가 변경되었을 때도 onResume()이 호출될 수 있으니 아래의 코드를 사용하여 데이터 처리를 하도록 하는 게 좋다고 합니다.

<activity  android:name=".MyActivity"  android:configChanges="screenSize|smallestScreenSize      |screenLayout|orientation" /> 

 

Multi-window의 숨겨진 기능

ganachoco(Young-Ho Cha)님이 Facebook GDG Korea Android(가입 필요)에 공유해주신 FreeForm Window 기능을 활성화하는 방법입니다. 위에 API 상으로는 FreeForm이라는 이름이 계속적으로 나오지만 실제 동작은 어떻게 되는지는 알 수 없었습니다. 다음의 방법을 통하면 아래 Remix OS와 같은 화면을 Android N Preview에서도 볼 수 있게 됩니다.

Freeform mode는 Remix OS와 유사하게 보입니다. Remix OS의 멀티 윈도우

 

다음 글에 Android N Feature FreeForm을 활성화 하는 방법을 담고 있습니다. 자세한 설명은 다음글을 참고하시면 되고, 적용 방법은 크게 2가지가 있습니다. 실물 기기에서는 TWRP 등의 커스텀롬 리커버리 모드를 이용하시거나 에뮬레이터를 통한 적용 방법입니다. Android N Feature FreeForm Window

Android N의 FreeForm Window 모드 적용 모습(androidpolice에서 따온 이미지입니다.)

 

 

마무리

Android N Preview의 멀티 윈도우를 살펴보았습니다. 멀티 윈도우에 동일한 UI를 적용하기 위해서는 Application Context가 아닌 Activity Context를 이용할 것과, 멀티 윈도우 지원 조건을 살펴보았습니다.

 

 

=================================

=================================

=================================

 

 

 

 

반응형

 

 

728x90

 

 

 

 

출처: https://thdev.tech/androiddev/2016/08/27/Android-N-ScreenSizeChangeEvent.html


Android Nougat(7.0)부터 루팅이나 adb 명령을 통하지 않고도, 스크린 사이즈를 변경이 가능해졌습니다.

누가 정식 버전에서는 아래와 같은 메뉴를 통해 화면 사이즈 변경이 가능한데, 재부팅 하지 않고도 동작합니다.

시스템 설정 > 화면 > 화면 크기

 

 

이런 좋은 기능은 Android N에서만 제공되지는 않을 것입니다. 일부 제조사에서 이전 버전에 미리 가져갈 수 있습니다.(원래 adb를 통해서 제공되던 기능이라서 어렵지 않게 포팅도 가능할 겁니다.)

가장 최근에 나온 갤럭시 노트 7(Note 7)이 이에 해당되는 기기입니다.

노트 7은 배터리 최적화 모드와 일부 최신 OS에서는 화면 사이즈를 직접 변경할 수 있는 옵션을 제공합니다.

이에 따라 생길 수 있는 오류는 다음과 같습니다.

  • 일부 개발 시 화면 사이즈를 저장하여 사용할 수 있습니다.
    • 그간 화면 사이즈 변경은 쉽게 이루어질 수 없고, 바로 적용되지 않았습니다.
    • 일부 커스텀 롬 또는 adb를 통해서 할 수 있었습니다.
  • 화면 사이즈를 저장해두고 사용하면 UI의 깨짐이 발생할 수 있으며, 일부 원치 않는 방식으로 동작할 수 있었습니다.
  • Android N이 아닌 이상 configChanges 이벤트가 발생하지 않습니다.

대략 위와 같습니다. 이에 대해서 간단하게 누가에서 제공하는 화면 사이즈 종류와 갤럭시 노트 7에서 제공하는 화면 사이즈 정보를 정리해보고, 사이즈 변화를 어떤식으로 대응할 수 있을지에 대해서 정리해보았습니다.

 

화면 사이즈 종류

누가(API 24) 정식 버전

누가 정식 버전에서는 아래와 같은 화면 사이즈 변경이 가능합니다.

  • 가장 작게
  • 기본 사이즈
  • 크게
  • 조금 크게
  • 가장 크게

위와 같이 5단계의 화면 사이즈가 변경이 가능합니다. 이 부분은 아래에서 실제 코드와 함께 얼마나 변하는지를 살펴보겠습니다.

노트 7의 배터리 최적화 및 화면 크기 변경 시 사이즈

  • 1280x720
  • 1920x1080
  • 2560x1440

위와 같이 3가지의 값으로 변경이 일어나게 됩니다. 실제로 값을 체크하면 해상도 자체의 변화가 심하게 발생하게 됩니다.

 

화면 사이즈 변경으로 인한 문제점은??

안드로이드 nougat에서는 해상도는 아래와 같이 5단계로 변경이 일어납니다.

하지만 실제 값의 변화는 dpi 값이 크게 변할 뿐 실제 해상도는 크게 변하지 않습니다.

 

다만 갤럭시 노트 7에서는 dpi 값보다는 해상도 자체가 큰 변화를 일으킵니다.

위에서 설정할 수 있는 3개 중에 하나의 값이 오게 되므로 전혀 다른 값이 오게 되는 것이죠.

 

우선 일반적인 해상도 정보를 가져오는 방법입니다.

DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); 

위의 값으로 불러오는데 다음의 경우 문제가 발생할 수 있겠습니다.

  • 실시간으로 화면 사이즈를 가져와서 처리하지 않는 경우(Splash, Intro 등의 처음 실행시 최초 한번만 체크)
    • 값을 저장해두고 사용하는 경우에 해당됩니다.
  • onResume이 아닌 onCreate등에서 한 번만 호출해서 사용할 경우

 

그렇다고 해도 누가에서 제공하는 화면 사이즈 변화에서는 큰 문제는 없습니다.

아래에서 확인하겠지만 실제 값의 변화가 크지 않음을 알 수 있습니다.

대부분 pixel 값을 가지고 계산을 하여 레이아웃을 그리거나, 애니메이션 처리를 하는 경우가 될 것입니다.

 

하지만 삼성에서는 이 pixel 값이 전혀 다르게 들어오게 됩니다.

  • 1920x1080 -> 최대 화면 사이즈로 변경 시 2560x1440
  • 2560x1440 -> 보통의 화면 사이즈로 변경 시 1920x1080
  • 2560x1440 -> 가장 큰 화면으로 변경 시 1280x720

위와 같이 전혀 다른 새로운 값으로 오게 됩니다.

 

저는 노트 7이 없어서 Nexus 6의 누가로 테스트하였습니다.

 

화면 사이즈 변화를 확인해보자

그렇다면 안드로이드 누가에서 실제로 어떤 변화가 있는지, 어떤 식으로 값을 체크하면 좋은지에 대해서 가이드를 해보겠습니다.

해당 방법은 Android N과 무관하게 동작하지만, Target API가 24일 경우의 대응은 아래 Android 누가 대응 부분에서 확인해주세요.

테스트는 다음과 같이 진행하였습니다.

  • onResume에서 getMetrics를 통해 사이즈 변화 체크
  • onConfigurationChanged를 통한 changed event 확인 방법

 

onResume을 통해서 확인

가장 대응하기 쉬운 onResume을 통해서 화면 사이즈의 변화를 체크해보았습니다.

일반적으로 가장 대응하기 쉬운 방법이 되겠는데 다음과 같은 코드로 확인할 수 있었습니다.

@Override     protected void onResume() {         super.onResume();          DisplayMetrics metrics = new DisplayMetrics();         getWindowManager().getDefaultDisplay().getMetrics(metrics);          Log.i("TAG", "display width : " + metrics.widthPixels + ", height : " + metrics.heightPixels + ", densityDpi : " + metrics.densityDpi);     } 

Nexus 6 기준 기본 해상도는 다음과 같습니다.

위와 같은 코드로 5가지 설정을 각각 확인하면 아래와 같습니다.

  • 가장 작은 화면 : display width : 1440, height : 2417, densityDpi : 476
  • 기본 화면 : display width : 1440, height : 2392, densityDpi : 560
  • 큰 화면 : display width : 1440, height : 2376, densityDpi : 612
  • 조금 큰 화면 : display width : 1440, height : 2360, densityDpi : 666
  • 가장 큰 화면 : display width : 1440, height : 2344, densityDpi : 720

해상도 별로 dpi 사이즈와 heightPixels의 값이 조금씩 변함을 알 수 있습니다.

해당 코드는 태블릿에서도 확인하였지만 동일하게 height만 변함을 확인하였습니다.

대략 넥서스 6 기준으로는 높이는 2417 ~ 2344까지 변함을 알 수 있고, 편차는 73 pixel 정도 차이를 보임을 알 수 있습니다. 이에 따라 실제 큰 변화가 없어서 사실 기존 값을 유지하였을 때 사용성에 문제는 없을 수 있습니다.

하지만 갤럭시 노트는 display width, height의 pixel 사이즈가 완전히 다르게 오게 되어 값을 변경하지 않으면 100% UI/애니메이션에 문제가 발생할 수 있습니다.

 

해당 방법은 단순히 onResume을 통해서 체크하였습니다. Android N에서는 이런 대응 방식이 좋지 않습니다. 바로 멀티 윈도우 때문이죠. 그래서 바로 아래와 같은 방법으로 좀 더 안전하게 확인이 가능합니다.

 

Android N에서 화면 사이즈 변화를 확인하기

안드로이드 7.0부터는 Multi Window를 지원합니다. 이에 따라 configChanges를 정의하지 않는다면 onResume이 계속적으로 불릴 수 있게 됩니다.

안드로이드 N에서는 Multi Window(Muti Window 대응 방법)와 화면 사이즈의 변화도 함께 체크해주어야 합니다.

우선 Android 7.0 Behavior Changes의 문서를 살펴보면 화면 사이즈 변화를 Screen Zoom이라고 표현하고 있으며, 그에 대한 내용을 제공해주고 있습니다.

저는 Android N의 Screen 대응 방식에 density를 추가하여 아래와 같은 android:configChanges를 추가하였습니다. density의 변화를 알 수 있으며, 그에 따른 변화를 대응할 수 있게 됩니다.

screenLayout screenSize smallestScreenSize density

위와 같은 코드는 아쉽지만 Android Target API 24에서만 동작하게 됩니다.

API 24 이전이라면 onResume을 통해서만 확인이 가능합니다.

<activity         android:name=".view.main.MainActivity"         android:configChanges="screenLayout|screenSize|smallestScreenSize|density"         android:label="@string/app_name"         android:theme="@style/AppTheme.NoActionBar">         <!-- 생략 --> </activity> 

다음과 같이 확인할 수 있지만 onResume을 호출하지 않아서 안전한 처리가 가능합니다.

@Override public void onConfigurationChanged(Configuration newConfig) {     super.onConfigurationChanged(newConfig);      Log.d("TAG", "config : " + (newConfig.orientation) + ", newConfig.screenLayout : " + newConfig.screenLayout);     Log.e("TAG", "newConfig.densityDpi : " + newConfig.densityDpi);     Log.i("TAg", "uiMode : " + newConfig.uiMode);     Log.i("TAg", "smallestScreenWidthDp : " + newConfig.smallestScreenWidthDp);     Log.i("TAg", "screenWidthDp : " + newConfig.screenWidthDp + ", screenHeightDp : " + newConfig.screenHeightDp); } 

Android N부터는 사실 기존에 지키지 않던 onResume의 활용을 적극적으로 지켜주어야 합니다.(그런 것을 생각해보면 삼성이 멀티윈도우 API를 참 대응 잘하는 느낌입니다.)

 

마무리

Android 누가의 화면 사이즈 변화에 대해서 정리하려고 했었는데 이제야 정리하게 되었습니다. 바로 갤럭시 노트 7 덕분이네요. 화면 사이즈를 저런 식으로 변화를 해줄지는 몰랐습니다.

좀 아쉬운 건 Android N부터 제공되는 API라서 하위 버전에서는 onResume을 통해서 체크할 수 있다는 점입니다.

=================================

=================================

=================================

 

 

 

출처: https://thdev.tech/androiddev/2016/04/05/Android-Multi-Window-Example-One.html


Edit. Preivew 2가 나오면서 일부 API 이름이 변경되었습니다.

 

안드로이드 N부터 Multi window를 지원하게 됩니다.
단순히 Multi window이고 구글 설명상 Activity lifecycle을 그대로 따를 것이라고 합니다.
이번에는 예제를 통해서 이러한 변화가 어떻게 적용되는지 살펴보겠습니다.

지난 정리 글 :

API 문서 :

 

테스트 코드 주소

Android Studio 2.2+에 맞게 수정한 내용을 적용하였습니다.

Multi window example code - GitHub

안드로이드 멀티 윈도우

멀티 윈도우 적용 시 달라지는 점을 확인하기 위해서 다음과 같은 테스트를 해보았습니다.

  • onResume/onPause 호출 시점
  • 창 크기 변경에 따른 lifecycle
  • 창 크기 변경 - configChange를 적용하였을 경우
  • 전체적인 정리


onResume/onPause 호출 시점
일반적으로는 Activity가 활성화되고, 비활성화 시에 호출되게 됩니다.
화면이 완전히 사라진다면 onStop이 호출되겠죠.
멀티 윈도우가 적용되는 N에서는 onResume/onPause가 생각보다 많이 호출된다고 합니다.
onResume/onPause가 호출되는 시점을 확인하기 위해서 다음을 테스트해보았습니다.

다음 테스트 결과는 위쪽에 최신 데이터를 가지게 됩니다. 

 

정상적으로 앱이 실행되었습니다.
onCreate -> onStart -> onResume 가 순서대로 동작합니다.

Multi Window 간 화면 전환을 시도하였을 때 다음과 같은 동작이 추가되었습니다.
onPause -> onResume -> onPause -> …
onResume(활성화) 상태에서 onPause(비활성화) 상태로의 변환이 계속적으로 일어남을 확인할 수 있습니다.

이를 그림으로 그리면 다음과 같습니다.
창간의 전환이 일어나게 되면 빨간 부분의 onResume / onPause 가 계속적으로 호출되게 됩니다.
특히나 동영상의 onPause에서 동영상 일시 정지를 하게 되는 경우가 많을 것 같습니다.
이 경우에는 꼭 onPause가 아니라 onStop으로 이동이 필요하다고 생각됩니다.(구글 팁의 lifecycle에서 자세하게 나옵니다.)

 


이로 인해 onResume, onPause 간에서는 동작을 최소한으로 줄이는 노력이 필요해 보입니다.


창 크기 변경에 따른 lifecycle
창의 크기를 변경할 수 있습니다.
분활 된 창의 가운데 부분을 왼쪽/오른쪽, 상/하로 이동하게 되면 창이 커지고 줄어들게 됩니다.
이때의 창의 크기가 변하는데 실제 lifecycle은 어떻게 동작하는지 살펴보겠습니다.

 

별다른 것 없어 보입니다. 실제로는 다음을 무한 루프 돌게 됩니다.
onCreate -> onStart -> onResume

onResume 상태를 기준으로 전체적으로 다시 보게 되면
onResume -> onPause(창 크기 변경 시작) -> onStop -> onDestroy -> onCreate(창 크기 변경 종료) -> onStart -> onResume

앱이 onCreate부터 처음부터 다시 시작하고 있습니다.
이동 중에는 아래의 flowchart처럼 동작하게 됩니다.

 

다시 정리하면 Android N 대응을 하지 않을 경우에는 onDestroy -> onCreate가 계속적으로 동작하게 됩니다.

 

창 크기 변경 - configChange를 적용하였을 경우

5 tips for preparing for Multi-Window in Android N에서 보았던 configChanges 코드를 적용해보겠습니다.

configChanges를 적용하였을 경우 lifeCycle이 어떻게 변화되는지 살펴보겠습니다.

우선 xml에 다음의 코드를 추가하였습니다.

android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation" 

java 코드도 추가했습니다.

@Override public void onConfigurationChanged(Configuration newConfig) {     super.onConfigurationChanged(newConfig);      // ...  } 

 

바로 위에서 보았던 이미지와는 많이 다름을 확인할 수 있습니다.
크게 onPause -> onDestroy 가 호출되지 않았습니다.
코드 상으로 onConfigurationChanged가 호출이 되고 있습니다.
그림 상으로는 아래와 같이 표현 할 수 있겠습니다.

 

그리고 숫자 1이 표시되고 있는데 이 값은 API의 Configuration API 문서

Configuration.SCREENLAYOUT_SIZE_SMALL 

화면이 축소된 상태이므로 size small이 호출됩니다.

전체적인 정리
내용을 정리해보겠습니다.
멀티윈도우 간 화면 전환 시 호출되는 순서
onPause -> onResume -> onPause -> …

Android N 대응 존 앱에서 창 사이즈를 변경 시
onPause -> onStop -> onDestroy -> onCreate -> onStart -> onResume
이 경우에는 전체적인 lifeCycle이 다시 동작하게 됩니다.

configure 설정을 하였을 경우
onResume인 상태에서 -> onConfigurationChanged
onConfigurationChanged만 호출되게 됩니다.

창 사이즈가 줄어들기 전과 복구된 상태에서는 onConfigurationChanged에서 다음의 코드가 호출됩니다.

Configuration.SCREENLAYOUT_SIZE_NORMAL Configuration.SCREENLAYOUT_SIZE_SMALL 

Size가 변경이 일어나게 되면 Normal -> small 이 호출됩니다.
inMultiWindow 상태도 false -> true로 변경되게 됩니다.

 

 

주요 코드

xml에서는 다음의 코드를 적용하였습니다.

참고 : 반대로 동작하지 않을 경우 screenOrientation을 강제로 지정하는 경우(가로 고정/세로 고정)에는 Multi window가 동작하지 않습니다.

<!-- Multi window support example --> <activity     android:name=".multiwindow.MultiWindowActivity"     android:resizeableActivity="true"     android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"     android:theme="@style/AppTheme.NoActionBar" />  <!-- Multi window freeform mode example --> <!-- 테스트 하려고 넣었지만 실제 동작하지 않네요 --> <activity     android:name=".multiwindow.FreeformModeActivity"     android:resizeableActivity="true"     android:theme="@style/AppTheme.NoActionBar">     <layout         android:defaultHeight="500dp"         android:defaultWidth="600dp"         android:gravity="top|end"         android:minimalHeight="450dp"         android:minimalWidth="300dp" />      <!-- Preview 2 change -->     <!-- Remove API Name : android:minimalSize -->     <!-- Add API Name : android:minimalWidth -->     <!-- Add API Name : android:minimalHeight --> </activity> 

 

Java 코드에서는

Activity 기반에서는 다음의 코드를 통해 Multi window 상태를 알 수 있습니다.
아래 2개 코드가 존재하고 있는데 boolean 값을 return 해주고 있습니다.

/*  * 멀티 윈도우 상태를 가져옵니다.  */ // Preview 2 API 이름 변경 // boolean inMultiWindow() boolean isInMultiWindowMode() /*  * 멀티 윈도우 상태를 변경합니다.  * true -> 멀티윈도우로 전환합니다.  * false -> 멀티윈도우에서 빠져나옵니다.  */ // Preview 2 API 이름 변경 // void onMultiWindowChanged(boolean isMultiWindow) void onMultiWindowModeChanged(boolean isMultiWindow) 

제가 테스트 한 코드는 아래와 같습니다.

multiWindowAdapter.addItem("onResume() isInMultiWindowMode " + isInMultiWindowMode(), true); 

 

마무리

멀티 윈도우에 대해서 전반적인 내용을 살펴보았습니다.
API 문서를 정리하였고, Freeform 모드를 적용해보기도 하였습니다.



onResume/onPause와 configChanges에 대한 대응은 꼭 필요하다고 생각됩니다.
configChanges를 적용하지 않으면 앱의 LifeCycle가 처음부터 다시 동작하게 됩니다.
그것도.. 실시간으로 일어나게 되겠습니다. 손을 놓을 때마다… 

다음의 문서는 정말 중요한 문서라고 생각됩니다.
이 문서의 내용을 꼭 습득하시기 바랍니다.
5 tips for preparing for Multi-Window in Android N

 

테스트 코드 주소

Android Studio 2.2+에 맞게 수정한 내용을 적용하였습니다.

Multi window example code - GitHub

 

 

=================================

=================================

=================================

 

 

반응형
그리드형


관련글 더보기

댓글 영역