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>

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




Android Design Support Library(l) – Navigation View


구글 I/O 2015에서 안드로이드 개발자를 위한 라이브러리를 발표했다. Design Support Library는 개발에 있어서 유용하게 사용할 수 있다. 특히 구글의 최신 디자인인 Material Design을 기반으로 하고 있기 때문에 디자이너에게는 훨씬 심플한 디자인을 개발자에게는 손쉽게 사용 할 수 있도록 도와준다.

안드로이드 서포트 라이브러리는 Cheesesquare Github를 통해 다양한 예제를 볼 수 있다. 단순히 예제를 보는것보다 각각의 새로운 기능에 대해 좀 더 깊이 있는 이야기를 써볼까 한다.

Navigation View

작년 Material 디자인을 발표 하면서 Navigation Drawer는 대다수의 랩에서 표준으로 사용되고 있다. Navigation View는 Drawer가 열였을때의 View를 손쉽게 구현하는 것을 도와준다.

navigation_drawer1-e1433071058464

이러한 Drawer View를 만들때 많을 시간을 소모 했다면 Navigation View를 이용한다면 훨씬 빠르게 구현 할 수있다.

 

작동은 어떻게?

Navigation View는 상단 헤더부분과 메뉴부분(또는 서브메뉴) 2가지로 구성된다. 상단 헤더부분은 개발자가 임의으로 레이아웃을 배치 할수 있으며 그아래 하단 메뉴부분은 메뉴통해 아이템이 생성되며 해당 아이템의 이벤트를 별도로 처리도 가능하다.

메뉴를 생성하여 Navigation View의 menu속성을 통해 menu resource를 지정해주면 된다.

메뉴 생성
<menu xmlns:android="http://schemas.android.com/apk/res/android">

 <group
 android:checkableBehavior="single">

 <item
  android:id="@+id/drawer_home"
  android:checked="true"
  android:icon="@drawable/ic_home_black_24dp"
  android:title="@string/home"/>

 <item
  android:id="@+id/drawer_favourite"
  android:icon="@drawable/ic_favorite_black_24dp"
  android:title="@string/favourite"/>
  ...

 <item
  android:id="@+id/drawer_settings"
  android:icon="@drawable/ic_settings_black_24dp"
  android:title="@string/settings"/>

 </group>
</menu>

하위 메뉴 생성

<item
  android:id="@+id/section"
  android:title="@string/section_title">
  <menu>
   <item
     android:id="@+id/drawer_favourite"
     android:icon="@drawable/ic_favorite_black_24dp"
     android:title="@string/favourite"/>

   <item
     android:id="@+id/drawer_downloaded"
     android:icon="@drawable/ic_file_download_black_24dp"
     android:title="@string/downloaded"/>
  </menu>
</item>
<android.support.v4.widget.DrawerLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:id="@+id/drawer_layout"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:fitsSystemWindows="true"
  tools:context=".MainActivity">

  <FrameLayout
    android:id="@+id/content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

  ...

  </FrameLayout>

  <android.support.design.widget.NavigationView
    android:id="@+id/navigation_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    app:headerLayout="@layout/drawer_header"
    app:menu="@menu/drawer"/>

</android.support.v4.widget.DrawerLayout>

헤더영역은 사용자가 별도의 레이아웃을 생성 할 수있다. Navigation View에 headerLayout속성을 통해 레이아웃 리소스를 지정하면 된다.

코드를 통해 Navigation View에서 메뉴를 선택 시 클릭 리스너를 처리 하기위해서 다름과 같이 리스너를 달아준다.

NavigationView view = (NavigationView) findViewById(R.id.navigation_view);
view.setNavigationItemSelectedListener(new   NavigationView.OnNavigationItemSelectedListener() {
    @Override public boolean onNavigationItemSelected(MenuItem menuItem) {

    //TODO

    drawerLayout.closeDrawers();
    return true;
  }
});

이 처럼 Navigation View는 Material 디자인의 훨씬 빠르고 쉽게 Drawer기능을 개발하도록 도와준다.