ConstraintLayout으로 아름다운 애니메이션하기

이 글은 Jinyan Cao가 작성한 Beautiful animations using Android ConstraintLayout 번역글입니다.

ConstraintLayout은 날이 갈 수록 인기를 더해가고 있습니다. 수평적인 뷰 계층 구조와 성능을 향상시키고, 임의의 경계 규칙을 지원합니다. 이전 레이아웃의 단점을 모두해결 할 것입니다. ConstraintLayout의 이점 중 하나는 매우 적은 코드로 멋진 애니메이션을 수행 할 수 있습니다. 이는 대부분의 개발자들이 알지못하며, 공식 문서에도 아무것도 언급되어 있지 않습니다.

방법?

ConstraintLayout의 기본 사항을 알고 있다고 가정합니다 (예: app:layout_constraintLeft_toLeftOf 및 다른 속성). 대부분의 문서또는 사이트에서는 새로 개선 된 Android Studio 레이아웃 디자인 패널을 사용하여 다양한 Constraint를 드래그/드롭/시각화 하는 방법만 소개되어 있습니다. 애니메이션의 목적을 위해서는 Constraint를 정확하게 이해하고 있어야만 조작이 가능합니다.

가장 간단한 형식인 TransitionManager(API 19 이상 또는 서포트 라이브러리에서 사용가능)를 통해 두 가지 Constraint 집합간에 애니메이션을 적용 할 수 있습니다. 긴 설명 보다 간단한 예제를 살펴 보겠습니다.

예제

Activity 실행시 초기화되는 XML 레이아웃부터 살펴 보겠습니다.

이것은 화면의 너비와 일치하는 화면 상단에 ImageView를 정의하는 기본 XML 파일입니다. (ConstraintLayout은 match_parent를 지원하지 않습니다.) 이제 하나의 추가 Constraint를 가진 대체 XML 레이아웃을 정의합시다.

여기서 유일한 차이점은 새 XML 레이아웃이 부모의 높이와 일치하는 높이로 설정하는것 입니다. 결과적으로 ImageView는 수직으로 가운데 정렬됩니다.
이제 두 개의 서로 다른 제약 조건 세트 (하나는 ImageView를 수직으로 중심에 배치하지 않고, 하나는 수직으로 가운데 배치)간에 애니메이션을 적용하려면 다음 코드를 Activity에 추가해야합니다.
(참고: 여기서는 Kotlin에 쓰여 있습니다. Kotlin에 익숙하지 않은 분은 Java 코드와 완전히 역 호환되는 동시에 최신 프로그래밍 언어의 많은 이점을 제공하므로 시작하는 것이 좋습니다. 이제 Android에서 공식적으로 지원되는 언어입니다!)

constraintSet1과 constraintSet2는 비 수직 가운데 정렬과 수직 가운데 정렬에 대응하도록 설정합니다. 먼저 TransitionManager에 ConstraintLayout에서 지연된 전환을 시작하라고 지시합니다. 그런 다음 ConstraintLayout에 다른 Constraint 집합을 적용합니다. TransitionManager는 자동으로 애니메이션을 수행하여 Constraint의 변경 사항을 표시합니다.

XML 레이아웃을 복제합니까?

무엇을 생각하는지 알고 있습니다. 이 접근법은 Constraint 변경을 위해 레이아웃 파일을 복제해야합니다. 아무도 중복 된 코드를 좋아하지 않습니다.
이것은 실제로 생각만큼 나쁘지 않습니다. 전환을 위해 대체 XML파일 생성하는 경우 레이아웃의 모든 속성(예 : textSize)을 생략 할 수 있습니다. ConstraintSet은 각 뷰의 Constraint의 속성을 제외한 나머지 속성을 무시합니다. 이렇게하면 두 파일에서 일관된 스타일을 유지할 필요가 없습니다.(예: 원래 XML에서 textSize를 변경하면 대체 XML에서 이를 변경할 필요는 없습니다.)
XML 코드 복제를 하고 싶지 않는 경우, 코드에서 동적으로 속성을 변경하면 됩니다.
위의 예를 하나의 레이아웃 XML로 어떻게 변경하는지 살펴 보겠습니다.

위의 코드에서 constraintSet2에 속성을 코드에서 변경하여 애니메이션을 수행하고 있습니다. 이렇게하면 우리는 Constraint 속성을 그대로 유지하고 코드 복제를 피할 수 있습니다.

하지만 이미 Transition 프레임워크를 사용하여 동일하게 사용할 수 있다!
이것은 전혀 새로운 방식이 아닙니다. Transition 프레임워크 또는 animateLayoutChanges와 같은 속성을 사용하여 동일한 작업을 수행 할 수 있습니다. 그러나 Constraint를 지정할 수 있기때문에 훤씬 강력합니다.
또 다른 이 점은 많은 요소를 애니메이션으로 만들려고 할 때입니다. 이 애니메이션을 살펴 보겠습니다.

Robinhood가 ConstraintLayout을 사용하여 주문 애니메이션을 만듭니다.
Robinhood (Android)의 주문 흐름 애니메이션입니다. 페이지의 모든 단일 요소(카드, 사용자 정의 키패드, FAB 등)를 수동으로 애니메이팅 하도록 구현되어 있습니다. 이 코드는 특히 앞뒤 애니메이션을 따로 작업한다는 점을 감안할 때 읽기에 약간의 문제가 있습니다.
대신이 애니메이션에 ConstraintLayout을 사용하는 샘플 앱을 만들었습니다. 이 구현은 훨씬 간단합니다. 변경되어야 할 속성만 바꾼다음 대체 XML 레이아웃 파일을 지정하면 애니메이션 프레임워크가 모든 것을 애니메이션으로 변환합니다. UI에서 이 애니메이션을 처리하는 코드는 ~250줄에서 ~30줄 간단해졌습니다.

 

더 있다!

ConstraintLayout 애니메이션을 시작하는 데 사용하는 코드를 기억하십니까?

두번째 파라미터를 이용하여 애니메이션을 커스터마이징 할 수있습니다!(기본은 내부에 구현된 기본 Transition 사용) 예를들어 애니메이션 속도를 쉽게 변경할 수 있습니다.

사소한주의 사항

ConstraintLayout 애니메이션으로 사용해본 후, 나는 애니메이션을 구현할 때 고려해야 할 몇 가지주의 사항을 발견했습니다.

  1. ConstraintLayout은 핸들링하는 자식에 대한 속성변경을 알고 있기때문에 직접 자식에 대해서만 애니메이션을 수행합니다. 중첩 된 ViewGroups인 경우 잘 처리 되지 않음을 의미합니다. 위의 예제에서 CardView 내부의 텍스트는 외부 ConstraintLayout에 의해 처리되지 않으므로 코드에서 수동으로 애니메이션을 적용해야합니다. 이것은 아마도 중첩 된 ConstraintLayout을 사용하여 해결할 수 있지만 여기서는 사용하지 않았습니다.

  2. ConstraintLayout은 레이아웃 관련 변경 사항 만 애니메이션으로 나타냅니다. 대체 XML 파일에서 다른 속성 (예: elevation, text)을 읽을 수 없으며 프레임워크가 모든 것을 처리 합니다. ConstraintSet.clone()은 레이아웃/Constraint 변경 사항을 복사하고 다른 모든 항목은 삭제합니다.

  3. constraint-layout:1.0.2에서 ConstraintLayout 속성을 동적으로 변경하면 업데이트 된 속성을 고려하지 않고 애니메이션됩니다.(예: translationY). 즉, 애니메이션을 실행하면 변경전의 속성의 값으로 되돌아 간뒤 새로운 값으로 애니메이션이 적용됩니다.

마치며..

ConstraintLayout을 사용하는 페이지에서 애니메이션을 구현할 함으로 Transition 프레임 워크 보다 많은 기본 레이아웃 변경 애니메이션을 수행 할 수 있습니다. 이를 통해 Activity/Fragment에서 UI/애니메이션 로직을 압축하고 XML로 통합 할 수 있습니다. 또한 더 읽기 쉬운 애니메이션 논리를 만듭니다. (아무도 프로그래밍 방식으로 생성 된 애니메이션을 읽는 것을 좋아하지 않습니다).

안드로이드 올바른 스플래시 화면을 구현하기 위한 방법

많은 실험 과정 속에서 안드로이드 스플래시 화면 구현에 대해 좋은 방법을 발견하였습니다. 보통 스플래시 화면 구현은 Activity에서 Runnable을 통해 시간을 지연하는 방식으로 구현합니다. 이는 약간의 문제점을 발생시킵니다.

실제로 스플래시 동안 아무런 작업을 하지 않지만 사용자는 무작정 기다려야 하는 문제가 있습니다. 또한 Application이나 Launch Activity에 많은 작업이 이루어진다면 Activity에서 레이아웃 인플레이트가 지연되어 스플래시 화면이 늦게 뜨는 문제점이 발생됩니다.

이해를 돕기 위해 문제가 되는 앱을 하나 보겠습니다. 메가박스 앱의 경우 실행할 때 검은 화면으로 덮인 후에 스플래시 화면이 뜨는 것을 볼 수 있습니다.

이런 문제점을 보완하여 앱을 로드하는 동안 스플래시 화면을 보여주기 위한 멋진방법을 소개해드리겠습니다.

코드

먼저 스플래시 화면을 사용한 레이아웃을 Drawable로 다시 디자인합니다. layer-list를 이용하여 배경 색상과 로고 이미지를 배치합니다.

이제 Activity에 사용할 테마의 windowBackground값에 이전에 만든 Drawable로 바꿔줍니다.

안드로이드 매니페스트에서 런치 될 Activity의 테마를 위에서 만든 스플래시 테마로 설정합니다.

Activity에서 onCreate전 setTheme를 이용하여 원래의 테마로 돌립니다.

Activity가 실행되기 전에 테마의 Background를 Drawable로 구성된 스플래시 화면을 보여주며 Activity가 생성되고 레이아웃 인 플레이트 되기 전 원래의 테마로 돌려줌으로써 스플래시 화면을 위한 Activity를 새롭게 생성할 필요가 없습니다.

이렇게 간단한 리소스를 이용한다면 앱의 초반 로딩 속도가 늦는 경우 로딩 프로그래스 대신 스플래시 화면을 사용하는 것도 나쁘지 않은 선택이 될 것입니다.

모든 코드는 Github에 공개되어있습니다.

디자이너 없이 안드로이드 앱 디자인 할 수 있는 몇 가지 방법

구글의 머트리얼 디자인 발표 후 안드로이드 앱의 디자인이 한결 깔끔하고 심플하게 변했습니다. 다양한 컬러와 복잡한 패턴을 사용하던 앱의 UI가 하나의 컬러와 도형으로 훨씬 심플해졌습니다. 이렇게 심플해진 UI로 인해 디자이너의 역할은 어느 때 보다 줄어들었습니다. 또한 구글의 머트리얼 디자인 가이드, 디자인 라이브러리, UI 툴이 한몫을 했다고 생각합니다.

개발자가 디자이너 없이도 안드로이드 앱 UI 디자인을 하기 위한 몇 가지 방법을 소개합니다.

 

1. 레이아웃

앱의 정보를 어떻게 배치하며 색상과 크기는 어떻게 지정할지에 대해서 많은 고민이 필요합니다. 머트리얼 디자인 가이드를 통해 UI 요소별 배치방법 및 스타일 가이드를 이용하면 훌륭하게 앱 디자인을 할 수 있습니다. 사용자가 편하게 볼 수 있도록 리스트뷰 행의 높이나 여백 등의 기정된 가이드라인에 따라 레이아웃에 적용만 하면 됩니다. 마진, 패딩은 8dp단위로 사용하면 훨씬더 깔끔하고 정돈된 디자인이 됩니다.

b879ecdd355781d2bfd5d26ea11aa1f6

안드로이드 디자인 서포트 라이브러리를 사용하면 가이드된 UI를 사용할 수 있습니다. 개발자가 직접 포토샵으로 리소스를 만들어 추출할 필요가 전혀 없습니다. 디자인 서포트 라이브러리를 통해 UI를 사용하고 가이드를 통해 여백이나 사이즈 등 수치만 잡아주시면 됩니다. 디자인 라이브러리 외 다양한 오픈소스를 활용하시면 됩니다.

2. 컬러 값

디자이너 없이 개발자가 좋은 컬러 값을 추출하기란 힘듭니다. 하지만 머트리얼 디자인 가이드에 플랫 하며 아름다운 색상이 이미 추출되어 있습니다. 개발자는 앱의 BI에 맞는 색상을 한 가지 선택해 추천하는 비슷한 톤의 컬러를 앱에서 사용하면 이질감 없이 통일된 UI를 구현할 수 있습니다.  컬러값을 미리보고 추출해주는  MaterialPalette사이트를 추천합니다.

5508a9714614b5de3ad9ff5163acb97d

3. 아이콘

구글이 공개한 저작권 없는 수백가지의 머트리얼 아이콘을 사용하면 됩니다. 웬만한 액션의 아이콘을 지원하고 계속 추가되고 있기 때문에 지속적으로 사용 가능합니다. 또한 dpi별로 추출 가능하며, 백터 Drawable을 사용하기 위한 SVG로도 추출 가능합니다.

머트리얼 아이콘은 안드로이드 스튜디오에서 New – Image(Vector) Asset메뉴를 통해서 쉽게 추가 가능합니다.

a1dd532e9beab8d56ed4a77f9fe41187

4. 런처 아이콘 만들기

앱의 아이콘은 앱의 가장 중요한 요소입니다. 사용자들이 앱 설치 전 UI의 느낌을 암시해주는 중요한 역할을 합니다. 앱의 아이콘에 따라 사용자가 설치할지 말지를 고민하게 할 수도 있는 큰역할을 합니다. romannurik가 만든 AndroidAssetStudioLauncher Icon Generator를 이용하면 손쉽고, 저작권에도 걸리지 않는 앱을 아주 간단하게 만들 수 있습니다. 최신 안드로이드(Nougat) 런처 스타일의 아이콘으로도 만들 수 있습니다.

c27b15d95c39e1915632cd12a6442177

다양한 설정을 통해 앱의 아이콘을 만들 수 있으며, dpi별로 추출해주기 때문에 편합니다.

5. 애니메이션

AndroidIconAnimator와 아이콘 리소스를 통해 간단한 애니메이션도 직접 만들 수 있습니다. SVG아이콘 리소스를 이용하여 아이콘이 애니메이션 하는 백터드로워블을 추출 할 수 있습니다. AndroidIconAnimator를 통해 기존 GIF의 프레임 하나씩 보여주는 방식보다 훌륭한 애니메이션을 만들 수 있습니다.

e7f3d92cf74b599838f70c2feda3ffa5

이렇게 머트리얼 디자인 가이드와 리스소만 잘 활용한다면 디자이너가 없어도 요즘 유행하는 앱 디자인을 갖출 수 있을 것입니다.

머트리얼 디자인 가이드를 잘 활용한 앱

a444e587ded8c2b5ef87a2253bc869de

빠르고 유연한 ContraintLayout

ContraintLayout?

ContraintLayout은 2016 구글 I/O를 통해 발표된 안드로이드의 새로운 레이아웃이다. 안드로이드 스튜디오(2.2 Preview2 부터)에 내장된 새로운 레이아웃 에디터(Blue Print)와 연동을 통해 이전의 레이아웃보다 쉽게 구성할 수 있다. 뷰 계층의 깊이와 복잡성을 해결하기 위해 ContraintLayout이 만들어졌으며, 앱의 UI렌더링 속도를 높일 수 있을 뿐만아니라 다양한 기기의 해상도에 최적화된 UI를 쉽게 개발 할 수도 있다. 안드로이드 서포트 라이브러리를 통해 사용가능하며 API 레벨 9부터 사용가능하다.

build.gradle에서 해당 라이브러리를 추가한다.

compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha2'

ContraintLayout 속성

  • layout_constraintTop_toTopOf
  • layout_constraintTop_toBottomOf
  • layout_constraintBottom_toTopOf
  • layout_constraintBottom_toBottomOf
  • layout_constraintLeft_toTopOf
  • layout_constraintLeft_toBottomOf
  • layout_constraintLeft_toLeftOf
  • layout_constraintLeft_toRightOf
  • layout_constraintRight_toTopOf
  • layout_constraintRight_toBottomOf
  • layout_constraintRight_toLeftOf
  • layout_constraintRight_toRightOf
  • layout_constraintCenterX_toCenterX
  • layout_constraintCenterY_toCenterY
  • layout_constraintBaseline_toBaselineOf

속성을 보면 알겠지만 많은 속성들로 인해 복잡하고 뷰들 간의 관계에 대한 속성들이 대부분이다. 자식뷰들관의 관계를 연결해주는 것을 보면 RelactiveLayout와 비슷해보이지만 ContraintLayout은 자식들과 부모관의 관계에 대한 정렬및 배치 방식과 좌표가 아닌 비율을 통해 위치가 지정되는등 다양한 기능을 가졌다.

 

레이아웃 에디터

개발자라면 그동안 레이아웃을 XML편집기를 이용하여 텍스트로 작성했을 것이다. 하지만 ContraintLayout은 무수히 많은 속성과 타겟 뷰의 ID를 값으로 주는 만큼 레이아웃구조를 텍스트로 작성하거나 또는 읽을때 예전보다는 확연히 힘들것이다. 이렇게 복잡한 레이아웃을 텍스트가 아닌 새롭게 선보인 디자인 툴(Blue Print)을 이용하면 훨씬 쉽고 간단하게 작성할 수 있다.

레이아웃 에디터는 UI설계를 하는 Design과 뷰들관의 관계를 보여주는 BluePrint 화면 2개가 나타난다. 이 2개 화면을 동시에 보거나 따로보는 방법은 레이아웃 에디터의 상단 아이콘을 이용하면 전환할 수 있다.

be44fb8e685150a5565f19c94e36e954
Design 표시 아이콘: 한번 누르면 디자인 화면으로 전환 되며 또한번 누르면 BluePrint 화면을 동시에 2개가 나타난다.

a72c79e2a3bf45f38413fec30f3dac36
BluePrint 표시 아이콘: 한번 누르면 BluePrint화면으로 전환되며 또한번 누르면 디자인 화면과 동시에 2개가 나타난다.

 

레이아웃 편집시 쓰이는 아이콘

b25f376c52508c900dbab5a8bf5d68bf
BluePrint화면의 뷰들간의 관계에 대한 정보를 숨기고 보일 수 있다.

f6ea28b2afd03030cfeed10d9b3f165a
새로운 뷰를 드래그 하는 경우 다른뷰들간의 관계를 자동으로 연결할 수 있다.

3fd3b60139267dc5bd0e2abce72f6f30
관계를 정보를 모두 삭제 한다.

4d928284744c25094798de88e6cce11d
자동으로 관계에 대한 정보를 연결한다.

7c2b5cfb7453a9614c2e5507998eff27
마진값의 단위를 선택한다. 0, 8, 16dp로 전환이 가능하다.

 

레이아웃 내에서 쓰이는 툴


하나의 뷰를 나타내며 가로/세로 크기와 다른뷰와의 관계에 대해 화살표로 설정할 수 있는데 자세히 알아보자.

99a8ebe4d5ada56e4abacb2dfedc9d50
뷰 크기 변경 컨트롤: 각모서리 가장자리에 있는 네모 모양을 통해 뷰의 크기를 늘리고 줄일 수 있다.

924dedda9eb89c0ab8f6a268c4558e13
관계 설정 컨트롤: 둥글게 생긴 부분으로 다른 뷰들관의 관계를 지정할 수 있다. 가로축의 컨트롤은 다른뷰의 가로축에만 연결되며, 세로축은 다른뷰의 세로축에만 연결된다. 이미 관계가 지정되어 있을때 클릭하면 해제된다.

a6b25ad94ce53ddfedbf2d689a506b78
베이스 라인 컨트롤: 뷰의 기본 라인을 맞춘다. 베이스 라인은 뷰내의 실제 컨텐트가 배치해있는 위치이다. 해당 컨트롤을 선택하기위해서는 커서를 몇초간 위치해있어야 한다.

 

ContraintLayout에서 뷰크기 지정

뷰의 크기는 우리가 알고 있듯이 고정된크기, 뷰의 컨텐츠에 맞게 지정되는 방식, 부모크기를 따라가는 방식이 있다. 이를 UI적으로 표현하여 좀거 쉽게 설정가능하다.

e8124ddde04b2aa76e42f79582123218

7300702340c7018202fbdcf57af5b525
고정된크기: 뷰의 사이즈가 고정되어 있다.

709b28b53490f5fb5f6dcdc5380a6fb3
부모 컨텐츠 크기: MATCH_PARENT방식으로 작동한다.

af2e72fd3b0d4188c61e06da211f9835
뷰 컨텐츠 크기: 뷰의 크기에 따라 크기가 설정된다.

edcfce9f89f19fb900de367212f55c3a
수평및 수직 정렬: 부모 뷰와 자식뷰가 연결되어 있는 경우 정렬을 퍼센테이지로 설정할 수 있다. LinearLayout의 weight와 비슷하다고 생각하면 쉽다.

팁!

처음 ContraintLayout을 접해보면 생각보다 힘든 작업이 될가능성이 높다. 이것저것 버튼을 눌러서 레이아웃을 맞추기에 생각보다 번거롭기 때문이다. 그래서 한가지 팁을 소개해보겠다. 먼저 뷰들간의 관계를 연결하지 말고 배치만으로 작업을 한다. 연결 되어 있다면 모두 끊은 상태에서 배치작업을 한뒤 자동 관계아이콘을 클릭하여 연결을 자동으로 구성 후 보정작업을 하거나 간단한 경우 직접 연결해준다.

 

ContraintLayout은 알파단계로 약간의 버그가존재하며 디자인툴이 생각보다 빨리 움직이지 않고 한번씩 다운되는등의 문제점이 발생된다. 하지만 기존의 너무 깊은 레이아웃을 구조로 앱의 성능에 문제가 생긴점을 해결해줄 속 시원한 레이아웃이 될것 같다. 그리고 BluePrint로 인해 디자이너도 툴을 쉽게 익히고 사용하는데 무리가 없을것 같다. 기존의 계층구조가 복잡한 레이아웃이 있다면 조금씩 바꿔나가는 것에 추천한다.

 

Android VectorDrawables

안드로이드 롤리팝에서 Vector방식의 Drawable을 사용 할 수 있는 VectorDrawable이 추가되었다. 구글의 안드로이드 Support Library 23.2부터 안드로이드 5.0 이하 버전에도 VectorDrawable을 지원한다.

픽셀 마다 색상 정보를 가지는 Bitmap과는 다르게 Vector방식은 Path정보를 통해 그래픽을 나타나게 된다. 이렇게 선과 선의 연결 정보를 가지고 있기때문에 정확한 크기정보를 가지고 있지않아 사이즈를 임의로 늘리거나 원하는 색상으로 변경해도 Bitmap처럼 뭉게지거나 깨지지 않는 장점이 존재하게 된다. 하지만 Bitmap처럼 복잡한 그래픽을 표현 하지는 못한다.

안드로이드 5.0 발표 당시 구글이 머트리얼 디자인을 함께 발표 하였다. 이 머트리얼 디자인 가이드의 주된 요점은 요소를 “단순화” 한다는 점에서 Vector와 정확하게 일치 한다. 머트리얼 디자인 아이콘을 보더라도 Vector방식으로 모두 표현이 가능하다.

기존의 BitmapDrawble을 사용함으로 DPI별로 각각 다른 이미지 리소스를 준비 했다면 VectorDrawable을 활용 한다면 DPI별로 각각 다른 이미지를 준비 할 필요가 전혀 없어진다. 이미지 관리 갯수도 작아질 뿐만아니라 용량도 많이 줄것이다.

android

 

 

 

 

 

 

<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="500px" height="500px" viewBox="0 0 500 500" enable-background="new 0 0 500 500" xml:space="preserve">
<g id="max_width__x2F__height" display="none">
<path display="inline" d="M499.001,1v498H1V1H499.001 M500.001,0H0v500h500.001V0L500.001,0z"/>
</g>
<g id="androd">
<path fill="#9FBF3B" d="M301.314,83.298l20.159-29.272c1.197-1.74,0.899-4.024-0.666-5.104c-1.563-1.074-3.805-0.543-4.993,1.199
L294.863,80.53c-13.807-5.439-29.139-8.47-45.299-8.47c-16.16,0-31.496,3.028-45.302,8.47l-20.948-30.41
c-1.201-1.74-3.439-2.273-5.003-1.199c-1.564,1.077-1.861,3.362-0.664,5.104l20.166,29.272
c-32.063,14.916-54.548,43.26-57.413,76.34h218.316C355.861,126.557,333.375,98.214,301.314,83.298"/>
<path fill="#FFFFFF" d="M203.956,129.438c-6.673,0-12.08-5.407-12.08-12.079c0-6.671,5.404-12.08,12.08-12.08
c6.668,0,12.073,5.407,12.073,12.08C216.03,124.03,210.624,129.438,203.956,129.438"/>
<path fill="#FFFFFF" d="M295.161,129.438c-6.668,0-12.074-5.407-12.074-12.079c0-6.673,5.406-12.08,12.074-12.08
c6.675,0,12.079,5.409,12.079,12.08C307.24,124.03,301.834,129.438,295.161,129.438"/>
<path fill="#9FBF3B" d="M126.383,297.598c0,13.45-10.904,24.354-24.355,24.354l0,0c-13.45,0-24.354-10.904-24.354-24.354V199.09
c0-13.45,10.904-24.354,24.354-24.354l0,0c13.451,0,24.355,10.904,24.355,24.354V297.598z"/>
<path fill="#9FBF3B" d="M140.396,175.489v177.915c0,10.566,8.566,19.133,19.135,19.133h22.633v54.744
c0,13.451,10.903,24.354,24.354,24.354c13.451,0,24.355-10.903,24.355-24.354v-54.744h37.371v54.744
c0,13.451,10.902,24.354,24.354,24.354s24.354-10.903,24.354-24.354v-54.744h22.633c10.569,0,19.137-8.562,19.137-19.133V175.489
H140.396z"/>
<path fill="#9FBF3B" d="M372.734,297.598c0,13.45,10.903,24.354,24.354,24.354l0,0c13.45,0,24.354-10.904,24.354-24.354V199.09
c0-13.45-10.904-24.354-24.354-24.354l0,0c-13.451,0-24.354,10.904-24.354,24.354V297.598z"/>
</g>
</svg>

Vector방식에서 가장 흔히 쓰이는 SVG 형식으로 아이콘을 제작하면 된다. 하지만 안드로이드에서는 SVG형식의 확장자를 바로 사용 할 수 없으며 VectorDrawable로 변환 해야한다. 최근 안드로이드 스튜디오에서는 SVG를 Import하면 자동으로 VectorDrawable 변경해주는 기능이 추가되어 쉽게 사용 할 수 있다. 위의 안드로이드 아이콘은 Path를 통해 SVG로 제작된 아이콘이다. 안드로이드에서 사용하기위해 아래와 같이 만들 수 있다.

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportWidth="500"
android:viewportHeight="500"
android:width="500px"
android:height="500px">
<group android:name="android">
<path
android:name="head"
android:fillColor="#9FBF3B"
android:pathData="M301.314,83.298l20.159-29.272c1.197-1.74,0.899-4.024-0.666-5.104c-1.563-1.074-3.805-0.543-4.993,1.199L294.863,80.53c-13.807-5.439-29.139-8.47-45.299-8.47c-16.16,0-31.496,3.028-45.302,8.47l-20.948-30.41c-1.201-1.74-3.439-2.273-5.003-1.199c-1.564,1.077-1.861,3.362-0.664,5.104l20.166,29.272c-32.063,14.916-54.548,43.26-57.413,76.34h218.316C355.861,126.557,333.375,98.214,301.314,83.298" />
<path
android:name="left_eye"
android:fillColor="#FFFFFF"
android:pathData="M203.956,129.438c-6.673,0-12.08-5.407-12.08-12.079c0-6.671,5.404-12.08,12.08-12.08c6.668,0,12.073,5.407,12.073,12.08C216.03,124.03,210.624,129.438,203.956,129.438" />
<path
android:name="right_eye"
android:fillColor="#FFFFFF"
android:pathData="M295.161,129.438c-6.668,0-12.074-5.407-12.074-12.079c0-6.673,5.406-12.08,12.074-12.08c6.675,0,12.079,5.409,12.079,12.08C307.24,124.03,301.834,129.438,295.161,129.438" />
<path
android:name="left_arm"
android:fillColor="#9FBF3B"
android:pathData="M126.383,297.598c0,13.45-10.904,24.354-24.355,24.354l0,0c-13.45,0-24.354-10.904-24.354-24.354V199.09c0-13.45,10.904-24.354,24.354-24.354l0,0c13.451,0,24.355,10.904,24.355,24.354V297.598z" />
<path
android:name="body"
android:fillColor="#9FBF3B"
android:pathData="M140.396,175.489v177.915c0,10.566,8.566,19.133,19.135,19.133h22.633v54.744c0,13.451,10.903,24.354,24.354,24.354c13.451,0,24.355-10.903,24.355-24.354v-54.744h37.371v54.744c0,13.451,10.902,24.354,24.354,24.354s24.354-10.903,24.354-24.354v-54.744h22.633c10.569,0,19.137-8.562,19.137-19.133V175.489H140.396z" />
<path
android:name="right_arm"
android:fillColor="#9FBF3B"
android:pathData="M372.734,297.598c0,13.45,10.903,24.354,24.354,24.354l0,0c13.45,0,24.354-10.904,24.354-24.354V199.09c0-13.45-10.904-24.354-24.354-24.354l0,0c-13.451,0-24.354,10.904-24.354,24.354V297.598z" />
</group>
</vector>

변형되는 xml은 SVG와 비슷한 구조로 부모 vector내에 path들이 존재하며 group을 통해서 path들을 묶어서 관리 할 수 있다. 이 SVG파일은 약 4kByte로 500×500의 Bitmap형식일때 25kByte 보다 약 6배이상 작은 공간을 차지한다. 사용법은 기존의 Drawable사용법과 동일하며 전혀 이질감 없이 VectorDrawable을 사용 할 수 있다.

<ImageView
android:id="@+id/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/android"/>

이렇게 VectorDrawable은 구글의 최신 디자인인 머트리얼 디자인을 표현하기에 가장 적합한 그래픽요소이며, 기존의 BitmapDrawable방식을 사용함으로 DPI별로 리소스를 준비해야하는 문제점은 한번에 해결 해 줄 수 있다. 안드로이드 스튜디오를 통해 자동 Import도 지원하고 있어 한결 편하게 사용 할 수 있기때문에 이제 선택 아닌 필수로 사용해볼만 하다.

 

 

디자이너 없이 머티리얼 아이콘 쉽게 제작하기

안드로이드 머티리얼 디자인이 발표 된지 이제 2년이라는 시간이 지났다. 머티리얼 디자인은 단순함을 추구하고 아주 심플한 디자인이다. 아이콘또한 2가지 이상의 색상으로 표현하지 않는 정말 한순화된 디자인 스타일이다. 이렇게 머티리얼 디자인은 개발자에게는 기회이다.

구글에서 안드로이드의 아이콘 리소스를 엄청난 양으로 공개한 마당이 이를 활용한다면 디자이너 없이 머티리얼 디자인의 앱을 만들 수 있다. 이번에 소개 할 아이콘을 제작도구또한 마찬가지다. 단순한 머티리얼 디자인이기때문에 이렇게 툴을 통해서 아이콘을 제작할 수 있도록 만들 수 있었다.

해당 툴을 이용하면 머티리얼 아이콘을 단숨에 만들 수 있다. SVG파일이나 기존의 구글에서 아이콘 리소스를 공개한것으로 사용가능하다. 다양한 설정값을 조절해가면서 마음에 드는 아이콘을 쉽게 제작할 수 있다.

http://bitdroid.de/Android-Material-Icon-Generator/

이툴은 깃허브를 통해 소스도 오픈되어 있다.

Android Design Support Library(II) – CoordinatorLayout

지난번 Navagation View에 이어 Design Support Library의 핵심인 CoordinatorLayout과 이와 관련된 Layout에 대해 살펴 보겠습니다. 작년 머티리얼 디자인발표시 저걸 어떻게 구현 할까 하고 겁먹으셨다면 이제 구글에서 제공하는 Design Support Library를 사용하면 코딩한줄 없이 구현가능합니다!

라이브러리가 지원되기 전에 Github를 통해 많은 오슨 소스들이 나왔었는데 이번 라이브러리 발표로 좀 더 쉽고 빠르게 구현가능할 수 있습니다.

CoordinatorLayout

ViewGroup을 상속해 구현 하였으며 자식이 행위를 선언하여 터치이벤트와 관련된 여러가지를 제어할 수 있게 해주고, 뷰간의 의존 관계를 구축 할 수 있게 해주는 레이아웃. 플로팅버튼 + 스낵바를 같이 띄우는 경우 스낵바가 떠오르는 경우 플로팅 버튼이 자동으로 올라가게 한다.

처음 개발시 앱바가 주요 컨텐츠의 스크롤에 반응 하도록 하는것이 주요 목표였다. AppBarLayout으로 감싸면 제어하는 ScrollFlags속성을 통해 화면을 아래로 스크롤 할때 각 구성요소가 화면 밖으로 스크롤 되거나 또는 화면 상단에 고정되며 내려갔다가 바로 다시 나타나도록 제어가능하다.
개발자가 동기화를 위히 스크롤시 코드를 직접 작성할 필요가 없다. 이를 이용하여 스크롤시 텍스트 크기를 늘리거나 줄일수 있으며 툴바에 타나나는 바탕색등을 변경 할 수 있다.

속성

layout_behavior

해당뷰와 스크롤 이벤트를 연결하기위한 속성으로 동일 레벨 계층뷰에 스크롤을 처리할 클래스명을 기입한다. AppBarLayout에 스크롤 이벤트를 연결하기위해 ScrollingViewBehavior가 구현되어 있다.
“android.support.design.widget.AppBarLayout$ScrollingViewBehavior”

 

AppBarLayout

LinearLayout을 상속받아 구현하였으며 CoordinatorLayout의 자식뷰들간의 의존 관계를 구축 할 수 있게 하기위한 레이아웃으로 스크롤 되는뷰(RecyclerView)의 스크롤 이벤트를 처리한다.

 

속성

layout_scrollFlags

  • “scroll” 스크롤 이되는 뷰와 함께 스크롤이 되어야 할 뷰에 반드시 설정해야 한다. 이 플래그값을 사용하지 않는 경우 화면상단에 고정되어 있게 된다.
  • “enterAlways” 아래로 스크롤시 해당뷰가 나타나게 되며 “빠른복귀” 패턴가 가능하다.
  • “exitUntilCollapsed” 해당뷰에 minHeight를 정의하고 이 플래그를 사용하면 최소높이를 지정한값에서 더이상 스크롤 되지 않고 떠있게 된다.
  • “enterAlwaysCollapsed” 해당뷰에 minHeight 속성의 크기로 시작해 맨위로 스크롤이 될때만 전체높이로 확장하게 된다.

CollapsingToolBarLayout

FrameLayout을 상속받아 구현하였으며 Toolbar를 확장하는 용도로 사용하는 레이아웃이다.

 

속성

layout_collapseMode

  • “pin” CollapsingToolbarLayout이 완전히 축소되면 툴바는 화면위에 고정되고 보여진다.
  • “parallax” 스크롤되는 동안 스크롤과 약간 어긋나도록 화면이 보여진다.

layout_collapseParallaxMultiplier

0.0(확장) ~ 1.0(축소) 사이의 값을 통해 스크롤시 값에 도달하게 되면 지정한색이 오버레이되어 자연스럽게 ToolBar로 변화 애니메이션을 나타낼 수 있다. (이때 지정된색은 CollapsingToolbarLayout의 coutentScrim속성을 통해 지정한다.)

expandedTitleMarginEnd
expandedTitleMarginStart
expandedTitleMarginBottom
expandedTitleTextApperance

Toolbar를 확장하는 용도로 사용하는 레이아웃임으로 해당 Title부분의 마진과 텍스트스타일을 변경 할 수 있는 속성도 있다.

 

 

예제 코드)

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
  android:id="@+id/main_content"
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:fitsSystemWindows="true">

<android.support.v7.widget.RecyclerView
  android:id="@+id/recyclerView"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

<android.support.design.widget.AppBarLayout
  android:id="@+id/appBarLayout"
  android:layout_width="match_parent"
  android:layout_height="300dp"
  android:fitsSystemWindows="true"
  android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

<android.support.design.widget.CollapsingToolbarLayout
  android:id="@+id/collapsingToolbarLayout"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:fitsSystemWindows="true"
  app:contentScrim="?attr/colorPrimary"
  app:expandedTitleMarginEnd="64dp"
  app:expandedTitleMarginStart="48dp"
  app:expandedTitleTextAppearance=""
  app:layout_scrollFlags="scroll|exitUntilCollapsed">

<ImageView
  android:id="@+id/backgroundImageView"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:fitsSystemWindows="true"
  android:scaleType="centerCrop"
  android:src="@drawable/appbar_image"
  app:layout_collapseMode="parallax"
  app:layout_collapseParallaxMultiplier="0.7"/>

<android.support.v7.widget.Toolbar
  android:id="@+id/toolbar"
  android:layout_width="match_parent"
  android:layout_height="?attr/actionBarSize"
  app:layout_collapseMode="pin"
  app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

</android.support.design.widget.CollapsingToolbarLayout>

</android.support.design.widget.AppBarLayout>

<android.support.design.widget.FloatingActionButton
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_margin="10dp"
  android:clickable="true"
  android:src="@drawable/ic_android_white_24dp"
  app:layout_anchor="@+id/appBarLayout"
  app:layout_anchorGravity="bottom|right|end"/>

</android.support.design.widget.CoordinatorLayout>

이처럼 한줄의 코딩 없이 레이아웃만을 통해서 첫화면의 이미지와 같은 화면을 구성 할 수 있다. 이는 구글의 머티리얼디자인 가이드를 바탕으로 만들어진 레이아웃이기에 조금의 변형(커스텀)을 하기위해서는 확장해서 새롭게 구현하거나 코드를 내려받아 수정을 해야한다. 이러한 부분들은 구글에서 지속적인 라이브러리 업데이트를 통해 보완해나갈 것이다.