[Android] Coordinatorlayout 배워보기 #1 - AppbarLayout
Coordinatorlayout 배워보기 #1
요약
- FrameLayout 같이 좌표를 자유롭게 지정 가능하다.
- android sdk 24.1.0(Nougat)에 포함되었다.
- 만약 compile sdk 가 24.1.0 이전 버전이라면
- 한개의 parent 아래 포함된 여러개의 child view 를 behavior 라는 것을 이용해서 다양한 애니메이션 효과를 표현해 낼 수 있다.
순서
- AppbarLayout 구성하기
- CoordinateLayout Behavior
- Custom Behavior
1. AppbarLayout
새 프로젝트를 생성한다. Empty Activity 로 생성하고 api level 은 19로 한다. (하지만 처음부터 api level을 24로 해도 된다)
프로젝트를 생성했으면 activity_main.xml 파일을 수정하도록 한다.
단, api level 24 이상에서는 support:design library 가 포함되어 있어서 바로 CoordinatorLayout 을 추가해도 되지만 그 이하에서는 gradle 파일에 아래 dependency 를 추가해 준다.
gradle sync 를 마친 후 activity_coordinator.xml 파일을 열어서 싹 지운 후 아래 코드를 붙여넣기 한다. (context 부분만 자신의 package 명에 맞게 변경해 주면 된다)
이 상태에서 빌드 후 앱을 실행 시켜 본다. Hello World! 가 보인다면 성공한 것이다. 여기에 하나씩 추가를 해보면서 익혀보도록 하자.
CoordinatorLayout 은 frameLayout 처럼 parent view 역할을 한다. 이제 이 안에 적절한 view 들을 넣어줄 차례인데, 가장 일반적으로 많이 쓰이는 Appbar 를 한번 추가해 보도록 하자.
참고로 Appbar 는 api level 11 부터 지원하는 Actionbar 와 api level 21 부터 지원하는 Toolbar 를 포괄적으로 부르는 용어이다.
AppBarLayout 내에 Toolbar 를 추가 하고 앱을 실행시켜 보도록 한다.
허? 근데 뭔가 Appbar 가 두개가 생겨 버렸다.
이유는 프로젝트를 api level 19 로 생성 하다 보니 Toolbar가 아닌 Actionbar 가 기본으로 보여졌기 때문이다.
지금은 Actionbar 대신 Toolbar 를 사용할 예정이니 Actionbar 는 안보이도록 styles.xml을 수정하도록 한다.
DarkActionBar 를 NoActionBar 로 변경 후 다시 앱을 실행시켜 보면 기존의 Actionbar 는 사라져 있는 것을 볼 수 있다.
이제 고정되어 있는 Toolbar 를 Scroll 에 따라서 커지기도 하고 작아지기도 하는 효과를 만들어 보기 위해 AppBarLayout 의 height 을 300dp 정도로 수정해 주도록 한다.
수정후 다시 실행해서 AppBarLayout 영역을 스크롤링 해보면 아래처럼 ToolBar 영역의 title이 자동으로 줄어들었다 커졌다 하는 것을 볼 수 있다.
참고로 파란색으로 된 부분이 AppBarLayout 영역이다.
뭔가 별로 해준게 없는데 저런 효과가 나는게 왠지 불안하다.
꼭 뭔가 외워서 써야만 할 것 같고..결론만 말하자면 외워야 하는 부분도 있고 이해해야 하는 부분도 있다.
이제 스크롤링 시 Toolbar 를 보여지게 하거나 감추는 flag 를 적용해보자.
그 설정은 app:layout_scrollFlags 에 따라서 결정이 된다.
이것을 테스트 해보기 위해 Toolbar 아래에 recyclerView 를 하나 추가해서 테스트 해보도록 하자.
activity_main.xml 에 아래와 같이 NestedScrollView 를 복사해서 붙여넣어 준다.
그리고 MainActivity.java 파일에 아래 코드를 복사해서 붙여넣기 해준다.
실행해 보면 100개의 아이템이 아래에 추가 되어 있는 것을 볼 수 있고, 이를 스크롤 하면 위에 AppbarLayout 이 동작하는 것을 볼 수 있다.
이제 layout_scrollFlags 설정을 하나씩 실행해 가면서 차이점을 살펴 보도록 하자.
enterAlways는 스크롤을 아래로 이동 시 AppbarLayout 이 완전히 사라졌다가 스크롤을 위쪽으로 이동하게 되면 AppbarLayer 전체가 보여진다. 이 flag 는 스크롤 이동 시 바로 메뉴같은게 보여지고 싶을 때 사용하면 유용하다. 예를 들어 웹브라우저 같은 경우 스크롤을 아래로 내릴 땐 주소창이 감춰지다가 살짝 위로 스크롤을 하게 되면 주소창이 보여지는 경우를 생각해 보면 된다.
enterAlwaysCollapsed는 스크롤을 아래로 이동 시 AppbarLayout 이 완전히 사라졌다가 스크롤을 위쪽으로 이동하게 되면 Toolbar 가 minHeight 만큼만 내려오고 스크롤이 최 상단에 도착 시 나머지 Appbar의 전체가 내려오게 된다.
고로, 이 flag 는 Toolbar 의 minHeight 에 영향을 받는다. 따라서 Toolbar size 를 조금 변경 시켜놓고 테스트를 해야한다. 아래처럼 Toolbar 의 height 와 minHeight 를 변경해 놓고 실행해 보자.
응? 근데 실행시켜 보면 알겠지만 enterAlways 때와 별 차이가 없어 보인다. 그 이유는 이 flag는 enterAlways 와 조합을 해서 사용해야 되는 것이기 때문이다.
이 조합으로 수정하여 다시 앱을 실행시켜 보자.
스크롤을 아래로 내리면 AppbarLayout 이 완전히 사라졌다가 반대 방향으로 스크롤을 올리게 되면 딱 Toolbar의 minHeight 만큼만 보여지게 되고 스크롤 최 상단에 도착 시 모든 Appbar 영역이 나타나게 된다.
enterAlwaysCollapsed 를 사용할 때는 반드시 enterAlways 와 조합해서 사용해야 한다는 점을 명심하자.
exitUntilCollapsed는 스크롤을 아래, 위로 이동 시 Toolbar 의 minHeight 만큼만 보여지고 스크롤이 최 상단에 도착 시 나머지 Appbar의 전체가 내려오게 된다. 위의 enterAlways | enterAlwaysCollapsed 을 조합했을 때와 다른 점은 위쪽으로 스크롤링 해도 AppbarLayout 이 완전히 사라지지 않는 다는 것이다.
프로젝트를 생성했으면 activity_main.xml 파일을 수정하도록 한다.
단, api level 24 이상에서는 support:design library 가 포함되어 있어서 바로 CoordinatorLayout 을 추가해도 되지만 그 이하에서는 gradle 파일에 아래 dependency 를 추가해 준다.
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.jirancomms.kr.coordinatorlayoutexam1"
minSdkVersion 19
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
// 자동추가 되는 depedencies
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.1.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
// 새로 추가 할 dependencies
compile 'com.android.support:support-annotations:27.1.1'
compile 'com.android.support:design:26.1.0'
}
build.gradle
gradle sync 를 마친 후 activity_coordinator.xml 파일을 열어서 싹 지운 후 아래 코드를 붙여넣기 한다. (context 부분만 자신의 package 명에 맞게 변경해 주면 된다)
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.jirancomms.kr.coordinatorlayoutexam1.MainActivity">
</android.support.design.widget.CoordinatorLayout>
이 상태에서 빌드 후 앱을 실행 시켜 본다. Hello World! 가 보인다면 성공한 것이다. 여기에 하나씩 추가를 해보면서 익혀보도록 하자.
CoordinatorLayout 은 frameLayout 처럼 parent view 역할을 한다. 이제 이 안에 적절한 view 들을 넣어줄 차례인데, 가장 일반적으로 많이 쓰이는 Appbar 를 한번 추가해 보도록 하자.
참고로 Appbar 는 api level 11 부터 지원하는 Actionbar 와 api level 21 부터 지원하는 Toolbar 를 포괄적으로 부르는 용어이다.
AppBarLayout 내에 Toolbar 를 추가 하고 앱을 실행시켜 보도록 한다.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.jirancomms.kr.coordinatorlayoutexam1.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="Test Appbar">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
Toolbar 를 추가한 실행화면 |
허? 근데 뭔가 Appbar 가 두개가 생겨 버렸다.
이유는 프로젝트를 api level 19 로 생성 하다 보니 Toolbar가 아닌 Actionbar 가 기본으로 보여졌기 때문이다.
지금은 Actionbar 대신 Toolbar 를 사용할 예정이니 Actionbar 는 안보이도록 styles.xml을 수정하도록 한다.
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
styles.xml
DarkActionBar 를 NoActionBar 로 변경 후 다시 앱을 실행시켜 보면 기존의 Actionbar 는 사라져 있는 것을 볼 수 있다.
Actionbar 가 사라졌다 |
이제 고정되어 있는 Toolbar 를 Scroll 에 따라서 커지기도 하고 작아지기도 하는 효과를 만들어 보기 위해 AppBarLayout 의 height 을 300dp 정도로 수정해 주도록 한다.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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:layout_width="match_parent"
android:layout_height="300dp"
tools:context="com.jirancomms.kr.coordinatorlayoutexam1.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="Test Appbar">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
Toolbar 를 CollapsingToolbarLayout 으로 감싼다.
수정후 다시 실행해서 AppBarLayout 영역을 스크롤링 해보면 아래처럼 ToolBar 영역의 title이 자동으로 줄어들었다 커졌다 하는 것을 볼 수 있다.
참고로 파란색으로 된 부분이 AppBarLayout 영역이다.
뭔가 별로 해준게 없는데 저런 효과가 나는게 왠지 불안하다.
꼭 뭔가 외워서 써야만 할 것 같고..
이제 스크롤링 시 Toolbar 를 보여지게 하거나 감추는 flag 를 적용해보자.
그 설정은 app:layout_scrollFlags 에 따라서 결정이 된다.
이것을 테스트 해보기 위해 Toolbar 아래에 recyclerView 를 하나 추가해서 테스트 해보도록 하자.
activity_main.xml 에 아래와 같이 NestedScrollView 를 복사해서 붙여넣어 준다.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.jirancomms.kr.coordinatorlayoutexam1.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="300dp"
>
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|enterAlways"
android:minHeight="200dp">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionbarSize"
app:title="Test Appbar">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="@+id/main.scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:fillViewport="true"
android:scrollbars="none"
android:descendantFocusability="blocksDescendants"
>
<android.support.v7.widget.RecyclerView
android:id="@+id/main.scrollview.recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
activity_main.xml
그리고 MainActivity.java 파일에 아래 코드를 복사해서 붙여넣기 해준다.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final List<String> testStrings = new ArrayList<>();
for(int i = 0; i < 100; i++) {
testStrings.add(i + " 번째 item");
}
RecyclerView recyclerView = findViewById(R.id.main_scrollview_recyclerview);
recyclerView.setAdapter(new RecyclerView.Adapter<TestViewHolder>() {
@Override
public TestViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = View.inflate(getApplicationContext(), android.R.layout.simple_list_item_1, null);
return new TestViewHolder(view);
}
@Override
public void onBindViewHolder(TestViewHolder holder, int position) {
holder.textView.setText(testStrings.get(position));
}
public int getItemCount() {
return testStrings.size();
}
});
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
public static class TestViewHolder extends RecyclerView.ViewHolder {
public TextView textView;
public TestViewHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(android.R.id.text1);
}
@Override
public String toString() {
return super.toString();
}
}
}
MainActivity.java
실행해 보면 100개의 아이템이 아래에 추가 되어 있는 것을 볼 수 있고, 이를 스크롤 하면 위에 AppbarLayout 이 동작하는 것을 볼 수 있다.
이제 layout_scrollFlags 설정을 하나씩 실행해 가면서 차이점을 살펴 보도록 하자.
scroll | enterAlways
scroll | enterAlways |
enterAlways는 스크롤을 아래로 이동 시 AppbarLayout 이 완전히 사라졌다가 스크롤을 위쪽으로 이동하게 되면 AppbarLayer 전체가 보여진다. 이 flag 는 스크롤 이동 시 바로 메뉴같은게 보여지고 싶을 때 사용하면 유용하다. 예를 들어 웹브라우저 같은 경우 스크롤을 아래로 내릴 땐 주소창이 감춰지다가 살짝 위로 스크롤을 하게 되면 주소창이 보여지는 경우를 생각해 보면 된다.
scroll | enterAlwaysCollapsed
enterAlwaysCollapsed는 스크롤을 아래로 이동 시 AppbarLayout 이 완전히 사라졌다가 스크롤을 위쪽으로 이동하게 되면 Toolbar 가 minHeight 만큼만 내려오고 스크롤이 최 상단에 도착 시 나머지 Appbar의 전체가 내려오게 된다.
고로, 이 flag 는 Toolbar 의 minHeight 에 영향을 받는다. 따라서 Toolbar size 를 조금 변경 시켜놓고 테스트를 해야한다. 아래처럼 Toolbar 의 height 와 minHeight 를 변경해 놓고 실행해 보자.
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="150dp"
android:minHeight="100dp"
app:title="Test Appbar">
응? 근데 실행시켜 보면 알겠지만 enterAlways 때와 별 차이가 없어 보인다. 그 이유는 이 flag는 enterAlways 와 조합을 해서 사용해야 되는 것이기 때문이다.
scroll | enterAlways | enterAlwaysCollapsed
이 조합으로 수정하여 다시 앱을 실행시켜 보자.
scroll | enterAlways | enterAlwaysCollapsed |
스크롤을 아래로 내리면 AppbarLayout 이 완전히 사라졌다가 반대 방향으로 스크롤을 올리게 되면 딱 Toolbar의 minHeight 만큼만 보여지게 되고 스크롤 최 상단에 도착 시 모든 Appbar 영역이 나타나게 된다.
enterAlwaysCollapsed 를 사용할 때는 반드시 enterAlways 와 조합해서 사용해야 한다는 점을 명심하자.
scroll | exitUntilCollapsed
exitUntilCollapsed |
exitUntilCollapsed는 스크롤을 아래, 위로 이동 시 Toolbar 의 minHeight 만큼만 보여지고 스크롤이 최 상단에 도착 시 나머지 Appbar의 전체가 내려오게 된다. 위의 enterAlways | enterAlwaysCollapsed 을 조합했을 때와 다른 점은 위쪽으로 스크롤링 해도 AppbarLayout 이 완전히 사라지지 않는 다는 것이다.
scroll | snap
scroll | snap |
snap 은 마치 자석에 달라붙는 것 같은 느낌으로 AppbarLayout size 의 절반 크기를 기준으로 아래 위로 달라 붙는 flag 이다.
이 다섯개의 flag 는 적절히 조합을 해서 사용해야 완전한 기능을 사용할 수 있다.
각 flag 의 역할을 정확히 알고 적절한 곳에 사용하도록 하자.
각 flag 의 역할을 정확히 알고 적절한 곳에 사용하도록 하자.
정리 감사합니다!
답글삭제