관리 메뉴

막내의 막무가내 프로그래밍 & 일상

[안드로이드] 안드로이드 Collapsing Toolbar Layout with Constraint Layout, NestedScroll 구현 본문

안드로이드/코틀린 & 아키텍처 & Recent

[안드로이드] 안드로이드 Collapsing Toolbar Layout with Constraint Layout, NestedScroll 구현

막무가내막내 2020. 8. 2. 03:42
728x90

 

 

[2021-04-14 업데이트]

 

 

Collapsing Toolbar Layout 를 적용하기전에 샘플로 구현해보았습니다. 

 

 

CoordinatorLayout

   -AppBarLayout

     [이 레이아웃의 바로 밑 계층은 일반적인 레이아웃이랑 비슷하다. CollapsingToolbarLayout 을 위해 사용]

       --CollapsingToolbarLayout

        [접히는(스크롤에) 모션에 반응하여 나타나거나 사라질 레이아웃]

            ---ImageView, Toolbar

              [접히는(스크롤에) 모션에도 계속 남아 있을 툴바, 즉 CollapsingToolbarLayout 안에서 Toolbar안에 있는 것은 접혀도 뷰를 보존시킴]

    -NestedScrollView

        --ConstraintLayout

           [일반적인 레이아웃]

    -FloatingActionButton

구조입니다. constraint 로 되어있는 예제는 안보여서 다른 종류의 예제들을 참고하여 만들었습니다. 구현 코드와 함께 원리도 간략하게 살펴보겠습니다 ㅎㅎ

 

 

 

 

 

 

 

 

[Activity] 툴바 세팅

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


        val toolbar = findViewById<View>(R.id.toolbar) as Toolbar
        toolbar.title = "HELLO EXAMPLE"
        setSupportActionBar(toolbar)
        if (supportActionBar != null) supportActionBar!!.setDisplayHomeAsUpEnabled(false) //툴바에 백키(<-) 보이게할거면 이거 사용

 

 

[XML]

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/app_bar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="350dp"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleTextAppearance="@android:color/transparent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <androidx.appcompat.widget.AppCompatImageView
                app:layout_collapseMode="parallax"
                android:src="@drawable/example"
                android:contentDescription="@string/hello_example"
                android:scaleType="centerCrop"
                android:layout_width="match_parent"
                android:layout_height="350dp" />

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


        </com.google.android.material.appbar.CollapsingToolbarLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:fillViewport="true"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:animateLayoutChanges="true"
            android:layout_marginBottom="?attr/actionBarSize">


            <androidx.appcompat.widget.AppCompatTextView
                android:id="@+id/tv_hello"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="28dp"
                android:layout_marginTop="16dp"
                android:text="HELLO!!"
                android:textColor="#000000"
                android:textSize="70dp"
                android:textStyle="bold"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <androidx.appcompat.widget.AppCompatTextView
                android:id="@+id/tv_hello2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="28dp"
                android:layout_marginTop="16dp"
                android:text="HELLO2!!"
                android:textColor="#000000"
                android:textSize="70dp"
                android:textStyle="bold"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/tv_hello" />

            <androidx.appcompat.widget.AppCompatTextView
                android:id="@+id/tv_hello3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="28dp"
                android:layout_marginTop="16dp"
                android:text="HELLO3!!"
                android:textColor="#000000"
                android:textSize="70dp"
                android:textStyle="bold"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/tv_hello2" />

            <androidx.appcompat.widget.AppCompatTextView
                android:id="@+id/tv_hello4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="28dp"
                android:layout_marginTop="16dp"
                android:text="HELLO4!!"
                android:textColor="#000000"
                android:textSize="70dp"
                android:textStyle="bold"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/tv_hello3" />

            <androidx.appcompat.widget.AppCompatTextView
                android:id="@+id/tv_hello5"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="28dp"
                android:layout_marginTop="16dp"
                android:text="HELLO45!!"
                android:textColor="#000000"
                android:textSize="70dp"
                android:textStyle="bold"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@id/tv_hello4" />
        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.core.widget.NestedScrollView>
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:src="@drawable/ic_add_black_24dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:elevation="6dp"
        app:pressedTranslationZ="12dp"
        app:layout_anchor="@id/app_bar_layout"
        app:layout_anchorGravity="bottom|right|end"
        />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

 

 


<com.google.android.material.appbar.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="350dp"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleTextAppearance="@android:color/transparent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

에서 scollFalgs 에는 5가지 종류가 있습니다.

scroll, expandAlways, expandAlwaysCollapsed, snap, exitUntilCollapsed.

scollFalgs 를 사용해서 NestedScrollView에서 스크롤 상태라고 CollapsingToolbarLayout 에 알려줄 수 있습니다.

만약 NestedScrollView 가 스크롤업할 때 CollapsingToolbar 를 접혀서 사라지게하고 스크롤 다운할 때는 CollapsingToolbar를 펼칠 수 있습니다.

예를들어 scroll | enterAlwaysCollapsed 속성은 아래로 스크롤하는 동안 CollapsingToolbar가 확장되는 시간에 대해 lazy한 접근 방식을 사용합니다. 아래로 스크롤되는 순간, CollapsingToolbar는 NestedScrollView가 콘텐의 맨 위로 스크롤 된 후에만 ​​확장됩니다. 즉 만약 엄청 긴 스크롤이 있고 맨아래까지 스크롤한 후 스크롤다운할 때 툴바위치(꼭대기겠죠) 까지 스크롤을 해야 그떄서야 툴바가 펴지기 시작한다는 뜻입니다.

이와 반대의 속성으로는  scroll|enterAlways 가 있겠습니다. 이거는 스크롤이 얼마나 아래에 있든 상관없이 스크롤 다운시 바로 CollapsingToolbar 펴지기 시작합니다.

 

저는 scroll|exitUntilCollapsed 속성을 사용하였는데 이 플래그가 툴바가 상단에 유지되고 스크롤시 사라지지 않도록하는 유일한 스크롤 플래그입니다. 이 플래그는 NestedScrollView가 해당 콘텐츠의 맨 위에 도달하면 CollapsingToolbar 만 확장하므로 enterAlwaysCollapsed 플래그와 유사하게 작동합니다.

 

그 밖의 다른 속성들에 대한 설명과 예시는 다음 사이트에 잘 나와있으니 참고하시면 됩니다. !!
https://medium.com/martinomburajr/android-design-collapsing-toolbar-scrollflags-e1d8a05dcb02

 

Android Design — Collapsing Toolbar: ScrollFlags Illustrated

In this section we will look at CollapsingToolbar scrollflags, combining scrollflags and some considerations when implementing them.

medium.com

 

 

 

 


 <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/app_bar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

AppBarLayout 은 Theme 를  설정하여 툴바의 타이틀 색상 등을 바꿔줄 수 있습니다. 

android:fitsSystemWindows 는 뷰가 차지할 수 있는 영역을 상태바 및 소프트키 영역을 제외한 영역까지 확장해주는 역할 수 있습니다. (출처: https://androidhuman.tistory.com/560 [커니의 안드로이드 이야기])

그래서 상태바까지 앱바 레이아웃의 이미지가 꽉 차게 만들려면 Toolbar 를 제외한 CoordinatorLayout - AppBarLayout - CollapsingToolbarLayout  - ImageView 에 이 속성을 주면 된다고 합니다. (https://black-jin0427.tistory.com/16)

 

 


 

 

 

  <androidx.appcompat.widget.AppCompatImageView
                app:layout_collapseMode="parallax"
                android:src="@drawable/example"
                android:contentDescription="@string/hello_example"
                android:scaleType="centerCrop"
                android:layout_width="match_parent"
                android:layout_height="350dp" />

앱바레이아웃안에 이미지뷰를 넣었는데요 layout_collapseMode 속성은 스크롤 될때마다 parallax 효과가 적용된다고 합니다. 즉 스크롤 app:layout_collapseParallaxMultiplier (0.0~1.0) 와 조합해서 쓸 수 있으며 기본값은 0.5입니다.
(자세한 내용은 https://developer.android.com/reference/androidx/leanback/widget/Parallax참고해주세요)

 


 

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

layout_collapseMode = "pin" 의 경우 스크롤을 할때 Toolbar가 최상단까지 위로 올라가면서 가장 최상단에 올라간 경우 고정 시켜주는 역할을 합니다.

 


 

 <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:fillViewport="true"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

app:layout_behavior="@string/appbar_scrolling_view_behavior" 속성을 설정함으로써 NestedScrollView의 반응에 따라 AppBarLayout이 반응됩니다.

CoordinatorLayout는 NestedScrollView가 스크롤시 layout_behavior에 정의된 레이아웃으로 스크롤 정보를 전달 하는 역할을 합니다. 그럼 AppBarLayout의 ScrollingViewBehavior가 정보를 받아서 AppBarLayout 자신을 변형하도록 하는 구조입니다. (https://blog.kmshack.kr/CoordinatorLayout%EA%B3%BC-Behavior%EC%9D%98-%EA%B4%80%EA%B3%84/)

 

fillViewport 의 경우는 다음을 참고하면 됩니다. https://m.blog.naver.com/PostView.nhn?blogId=snowheeee&logNo=220958929516&proxyReferer=https:%2F%2Fwww.google.com%2F

https://jootc.com/p/201908173053


[P.S]

app:expandedTitleMarginStart
app:expandedTitleGravity
app:expandedTitleMarginBottom
app:expandedTitleTextAppearance
app:collapsedTitleTextAppearance
app:collapsedTitleGravity
등의 속성을 이용해서 툴바의 텍스트를 펼침, 접힘 상태의 모양을 구현해줄 수 있습니다.
Appearance에는 style로 모듈화해서 세팅하면됩니다. (Ex. testSize, testColor, fontFamily등)
그리고 뭐든 마찬가지지만 자주쓸 가능성이 있는 Collapsing Toolbar 는
AppBarLayout~CollapsingToolbarLayout~Toolbar로 모듈화해서
사용할 XML에 최상단 부모레이아웃을 CoordinatorLayout 로 한후 모듈화 한거를 <include> 해서 사용하면 좋습니다 :)

 

 

 

참고 : 예전에 했던거라 여러군데서 참고했는데 생각이 안나네요.

https://m.blog.naver.com/PostView.nhn?blogId=pistolcaffe&logNo=221017061017&proxyReferer=https:%2F%2Fwww.google.com%2F

 

CollapsingToolbarLayout 분석

우리는 CollapsingToolbarLayout 을 사용하여 AppBarLayout 과 함께 툴바의 Collapsing , contentS...

blog.naver.com

https://black-jin0427.tistory.com/16

 

[Android, Collapsing Tool bar] Collapsing Tool bar 에서의 status bar

머티리얼 디자인에서 많이 보는 화면으로 위 이미지는 status bar 가 있는 화면입니다. 하지만 위와 같이 status bar를 투명하게 설정하고 스크롤을 올릴시 status bar 와 툴바가 보이도록 설정하는 법에

black-jin0427.tistory.com

 

추가 포스팅 자료 

youngest-programming.tistory.com/380

 

[안드로이드] 안드로이드 CollapsingToolbarLayout UI 기록

[2021-05-04 업데이트] 이전에 기본적인 CollapsingToolbarLayout 에 대해 구현해보고 알아보는 포스팅을 했었습니다. youngest-programming.tistory.com/353 [코틀린] 안드로이드 Collapsing Toolbar Layout with..

youngest-programming.tistory.com

 

 

 

댓글과 공감은 큰 힘이됩니다. 감사합니다!!

 

728x90
Comments