관리 메뉴

나만을 위한 블로그

[Android] CollapsingToolbarLayout이란? CollapsingToolbarLayout 예제 본문

Android

[Android] CollapsingToolbarLayout이란? CollapsingToolbarLayout 예제

참깨빵위에참깨빵 2022. 6. 19. 19:24
728x90
반응형

스크롤을 할 때 사용자가 보는 글자가 툴바로 올라가면서 밑에 있던 내용들이 올라오는 화면을 만들어야 해서 찾아보니 CollapsingToolbarLayout이란 걸 응용해서 만드는 예제들이 많아 이 레이아웃에 대해 공부하는 포스팅을 적는다.

이 레이아웃에 대해 설명하는 안드로이드 디벨로퍼 링크는 아래와 같다. 본문 내용 일부도 같이 남긴다.

 

https://developer.android.com/reference/com/google/android/material/appbar/CollapsingToolbarLayout

 

CollapsingToolbarLayout  |  Android Developers

 

developer.android.com

CollapsingToolbarLayout은 축소 앱 바를 구현하는 툴바용 래퍼다. AppBarLayout의 직계 자식으로 사용하도록 설계됐다. 이 레이아웃에는 다음 기능이 포함돼 있다

- 축소 제목 : 레이아웃이 완전히 표시될 때 더 커지지만 레이아웃이 화면에서 스크롤될 때 축소되고 작아지는 제목이다. setTitle(charSequence)를 써서 표시할 제목을 설정할 수 있다. 축소된 TextAppearance 및 expandTextAppearance 속성으로 제목 모양을 조절할 수 있다

- 컨텐츠 스크림(Content scrim) : 스크롤 위치가 특정 임계값(threshold)에 도달했을 때 표시되거나 숨겨지는 full-bleed scrim이다. setContentScrim(Drawable)로 바꿀 수 있다

- 상태 바 스크림 : 스크롤 위치가 특정 임계값에 도달했을 때 상태 표시줄 뒤에 표시되거나 숨겨지는 스크림이다. setStatusBarScrim(Drawable)로 바꿀 수 있다. 시스템 창에 맞게 설정할 때 롤리팝 장치에서만 작동한다

- 시차 스크롤링 자식(Parallax scrolling children) : 자식 뷰는 이 레이아웃 안에서 시차 방식으로 스크롤되게 선택할 수 있다. CollapsingToolbarLayout.LayoutParams.COLLAPSE_MODE_PARALLAX 및 CollapsingToolbarLayout.LayoutParams.setParallaxMultiplier(float)을 참고하라

- 고정 위치 자식(Pinned position children) : 자식 뷰는 space globally하게 공간에 고정되게 선택할 수 있다. 이 레이아웃이 이동하더라도 도구 모음을 제자리에 고정할 수 있어 축소를 구현할 때 유용하다. CollapsingToolbarLayout.LayoutParams.COLLAPSE_MODE_PIN을 참고하라

런타임에 툴바에 뷰를 수동으로 추가하지 마라. 제목에 사용 가능한 공간을 계산할 수 있도록 툴바에 사용 가능한 공간을 계산할 수 있도록 툴바에 '더미 뷰'를 추가한다. 이것은 추가하는 모든 보기를 방해할 수 있다

 

이 레이아웃의 상속도는 아래와 같다.

 

 

이것을 사용하면 아래와 같은 화면을 만들 수 있다.

 

https://youngest-programming.tistory.com/353

 

위에 크게 표시되던 제목이 스크롤하자 위로 올라가 툴바쪽에 붙으면서 그 밑의 뷰들이 올라와 표시되는 걸 볼 수 있다.

그럼 CollapsingToolbarLayout과 툴바를 쓰면 이 화면을 만들 수 있을까?

아니다. 2가지를 더 알고 같이 써야 저런 화면을 만들 수 있다. 바로 CoordinatorLayout(코디네이터 레이아웃), AppBarLayout이다. CoordinatorLayout부터 확인해보자.

 

https://developer.android.com/reference/androidx/coordinatorlayout/widget/CoordinatorLayout

 

CoordinatorLayout  |  Android Developers

androidx.health.platform.client.error

developer.android.com

CoordinatorLayout은 강력한 프레임 레이아웃이다. CoordinatorLayout은 2가지 주요 사용 사례를 위한 것이다

- 최상위 앱 장식(데코) 또는 크롬 레이아웃으로써
- 하나 이상의 하위(자식) 뷰와의 특정 상호작용을 위한 컨테이너로써

CoordinatorLayout의 자식 뷰에 대한 동작을 지정하면 단일 부모 안에서 다양한 상호 작용을 제공할 수 있고 이런 뷰도 서로 상호작용할 수 있다. 뷰 클래스는 CoordinatorLayout.AttachedBehavior 인터페이스를 구현해 CoordinatorLayout의 자식으로 사용될 때 기본 동작을 지정할 수 있다. Behavior는 Sliding drawers와 panel에서 이동 및 애니메이션 시 다른 요소에 달라붙는 스와이프 해제 가능한 요소, 버튼에 이르기까지 다양한 상호작용 및 추가 레이아웃 수정을 구현하는 데 쓰일 수 있다
CoordinatorLayout의 자식은 앵커를 가질 수 있다. 이 뷰 id는 CoordinatorLayout의 임의의 하위 항목에 해당해야 하지만 고정된 자식 자체 또는 고정된 하위의 하위 항목이 아닐 수 있다. 이것은 다른 임의의 컨텐츠 창을 기준으로 플로팅 뷰를 배치하는 데 사용할 수 있다
자식은 CoordinatorLayout.LayoutParams.insetEdge를 지정해서 뷰가 CoordinatorLayout을 삽입하는 방법을 설명할 수 있다. CoordinatorLayout.LayoutParams.dodgeInsetEdges에 의해 동일한 삽입 가장자리를 피하도록 설정된 모든 하위 뷰는 뷰가 겹치지 않도록 적절하게 이동된다

 

그냥 여러 기능이 추가된 프레임 레이아웃이라고 보면 될 것 같다. 이 글만으로는 아직 이해할 수 없어서 CoordinatorLayout에 대해 설명하는 글을 더 찾아봤다.

 

https://stackoverflow.com/questions/40929686/constraintlayout-vs-coordinator-layout

 

ConstraintLayout vs Coordinator layout?

What to implement: ConstraintLayout or CoordinatorLayout for proper material design in android ?

stackoverflow.com

...(중략)...기본적으로 프레임 레이아웃에 여러 자식을 추가하면 서로 겹친다. 프레임 레이아웃은 단일 자식 뷰를 유지하는 데 가장 자주 사용해야 한다. CoordinatorLayout의 주요 매력은 애니메이션과 그 안에 있는 뷰의 전환을 조정하는 기능이다. CoordinatorLayout의 자식 뷰에 대한 동작을 지정하면 단일 부모 안에서 다양한 상호작용을 제공할 수 있으며 이런 뷰도 서로 상호작용할 수 있다. 뷰 클래스는 CoordinatorLayout.DefaultBehavior 어노테이션을 써서 CoordinatorLayout의 자식으로 쓰일 때 기본 동작을 지원할 수 있다...(중략)

 

https://rkdxowhd98.tistory.com/119

 

Android in A..Z - CoordinatorLayout (기본)

CoordinatorLayout View간의 상호작용을 처리하기 위한 View이다. CoordinatorLayout이 Child View의 Behavior를 수신하여 다른 Child View에 Behavior를 전달한다. 각 Child View는 미리 정의된 Behavior를 사용..

rkdxowhd98.tistory.com

뷰 간의 상호작용을 처리하기 위한 뷰다. CoordinatorLayout이 자식 뷰의 Behavior를 수신해서 다른 자식 뷰에 전달한다. 각 자식 뷰는 미리 정의된 Behavior를 쓰거나 새로 만든 Behavior를 써서 수신된 Behavior로 특정 작업을 수행할 수 있다

- 스크롤 시 AppBarLayout 변경
- 스낵바 생성 시 FloatingActionButton 위치 변경

 

그 외의 글들을 더 찾아봤지만 강력한 FrameLayout이란 말이 나오거나 안드로이드 디벨로퍼의 설명에서 크게 벗어나지 않는 말들을 늘어놨기 때문에 생략한다.

그리고 Behavior라는 새로운 키워드가 보인다. 이것에 대한 안드로이드 디벨로퍼의 설명은 아래와 같다.

 

https://developer.android.com/reference/androidx/coordinatorlayout/widget/CoordinatorLayout.Behavior

 

CoordinatorLayout.Behavior  |  Android Developers

androidx.wear.watchface.complications.rendering

developer.android.com

CoordinatorLayout의 자식 뷰를 위한 상호작용 동작 플러그인이다. Behavior는 사용자가 자식 뷰에서 수행할 수 있는 하나 이상의 상호작용을 구현한다. 이런 상호작용에는 드래그, 스와이프, 플링(fling) 또는 기타 제스처가 포함될 수 있다

 

자식 뷰에서 하나 이상의 상호작용을 구현하기 위해 사용하는 클래스라고 보면 되겠다. 이것에 대해서도 좀 찾아봤다.

 

https://blog.kmshack.kr/CoordinatorLayout%EA%B3%BC-Behavior%EC%9D%98-%EA%B4%80%EA%B3%84/

 

CoordinatorLayout과 Behavior의 관계

머트리얼 디자인 가이드 라인중 스크롤시 다양한 반응을 위한 테크닉인 Behavior라는 개념이 도입 되었습니다. 기본적으로 액션바를 확장하여 스크롤시 액션바를 줄여들게 하도록 AppBarLayout의 Scro

blog.kmshack.kr

머티리얼 디자인 가이드 라인 중 다양한 반응을 위한 테크닉인 Behavior란 개념이 도입됐다. 기본적으로 액션바를 확장해서 스크롤 시 액션바가 줄어들도록 AppBarLayout의 ScrollingViewBehavior, 스크롤 시 하단으로 숨기기 위해 BottomSheetBehavior를 서포트 라이브러리에서 제공하고 있다
Behavior를 쓰려면 CoordinatorLayout을 써야 하는데 CoordinatorLayout은 자식 뷰의 스크롤 변화 상태를 다른 자식뷰들에게 전달해주는 역할을 한다. NestedScrollView, RecyclerView 등의 뷰의 스크롤 상태를 판단해 정의된 반응을 하기 위한 뷰에 Behavior를 등록하면 된다

 

계속해서 AppBarLayout이 나오는데 이제 이것이 뭔지 알아보자.

 

https://developer.android.com/reference/com/google/android/material/appbar/AppBarLayout

 

AppBarLayout  |  Android Developers

 

developer.android.com

AppBarLayout은 머티리얼 디자인 앱 바 개념의 많은 기능, 즉 스크롤 제스처를 구현하는 Vertical Linear Layout이다. 자식 뷰는 AppBarLayout.LayoutParams.setScrollFlags(int) 및 연결된 레이아웃 XML 속성(app:layout_scrollFlags)을 통해 원하는 스크롤 동작을 제공해야 한다. 이 뷰는 CoordinatorLayout 안에서 직접적인 자식으로 쓰이는 것에 크게 의존한다. 다른 뷰그룹 안에서 AppBarLayout을 쓰는 경우 대부분의 기능이 작동하지 않는다. AppBarLayout은 또한 스크롤 시점을 알기 위해 별도의 스크롤 형제가 필요하다. 바인딩은 AppBarLayout.ScrollingViewBehavior 동작 클래스를 통해 수행된다. 즉 스크롤링 뷰의 동작을 AppBarLayout.ScrollingViewBehavior의 인스턴스로 설정해야 한다. 전체 클래스 이름이 포함된 문자열 리소스를 쓸 수 있다

 

이제 이것들을 사용한 예제를 확인해보자. 이 포스팅의 코드들은 아래 링크의 자바로 된 코드 중 필요없는 부분을 쳐내고 코틀린으로 바꾼 것이다.

 

https://github.com/saulmm/CoordinatorBehaviorExample

 

GitHub - saulmm/CoordinatorBehaviorExample

Contribute to saulmm/CoordinatorBehaviorExample development by creating an account on GitHub.

github.com

 

따로 앱, 프로젝트 수준 gradle에 추가할 의존성은 없고 먼저 자잘한 리소스들부터 추가해주자.

일단 메뉴를 추가한다. res 안에 menu 폴더를 만들고 menu_main.xml을 만든 뒤 아래 코드를 복붙한다.

 

<menu 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"
    tools:context=".MainActivity">
    
    <item android:id="@+id/menu_share"
        app:showAsAction="ifRoom"
        android:title="메뉴" />
    
    <item
        android:id="@+id/action_settings"
        app:showAsAction="never"
        android:title="누르면 나오는 글자" />
    
</menu>

 

그리고 values 안의 strings.xml에 아래 내용을 복붙한다. NestedScrollView에 표시할 긴 글자다.

 

<resources>
    <string name="lorem">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vehicula sem a malesuada rhoncus. Pellentesque ut dolor a dui porttitor porta lacinia non libero. Nunc volutpat arcu quis quam convallis molestie. Etiam ac tristique sem, id commodo justo. Phasellus congue tincidunt lectus, at dignissim ligula maximus eu. Quisque interdum nunc eget tellus bibendum suscipit. Phasellus feugiat ultricies posuere. Nullam porta accumsan velit, ut rutrum massa fermentum eu. Nunc ac bibendum nunc. Mauris eu ultricies ipsum. Ut id dolor dui. Pellentesque dictum dui vel tempus maximus. Vivamus non nisi quis libero scelerisque pretium. Ut eu tristique justo. Sed pellentesque placerat quam, ut ultricies turpis feugiat a. Aliquam a volutpat risus.

Praesent at lectus semper, suscipit elit in, facilisis massa. Phasellus sed vestibulum ante, a euismod sem. Interdum et malesuada fames ac ante ipsum primis in faucibus. Proin tincidunt orci augue, a porta odio lacinia eu. Nunc in congue risus. Maecenas commodo nibh ac enim fermentum, eu sagittis massa blandit. Vestibulum elementum massa nec dapibus mollis. Etiam porta, est sit amet aliquet porta, odio elit finibus risus, id rutrum purus mi non ipsum. Nulla viverra nec enim sed venenatis.

Maecenas mattis, erat et viverra euismod, neque diam porttitor tellus, in fringilla metus est id augue. Nunc at metus cursus, porttitor nisi vitae, congue diam. Curabitur ligula massa, ullamcorper eget scelerisque vel, pharetra ac sapien. Ut auctor luctus ultricies. Nullam semper tortor ac elementum luctus. In et tempus ex. Praesent sodales, dolor id volutpat elementum, ligula enim euismod odio, maximus sodales magna neque nec neque. Curabitur pretium nisl neque, consequat aliquet dui tincidunt ac. Vivamus augue nunc, aliquet eu ex a, ultrices aliquam lorem. Duis nibh lectus, ultricies vel iaculis sit amet, imperdiet id sapien. Duis scelerisque sodales metus eu rutrum. Suspendisse posuere nisi ac magna consequat, eu vestibulum ipsum venenatis. Suspendisse auctor nisi nec leo venenatis tristique.

Praesent tincidunt lorem sit amet mi consequat cursus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Praesent vitae blandit sapien. Curabitur est sapien, lobortis sit amet facilisis vel, faucibus eu quam. Nam tempus libero at tellus tempor laoreet. Pellentesque quam lorem, tincidunt in molestie eget, dictum vel risus. Nunc gravida convallis mattis.
    </string>
</resources>

 

themes 안의 theme.xml에서 style을 NoActionBar로 사용한다. 필요없다면 따로 설정하지 않아도 상관없다.

 

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.KotlinPrac" parent="Theme.MaterialComponents.DayNight.NoActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
    </style>
</resources>

 

준비물들이 다 생겼으니 이제 XML을 만들어준다.

 

<?xml version="1.0" encoding="utf-8"?>
<layout 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">

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/black"
        tools:context=".collapsingtoolbarlayout.CollapsingToolbarActivity">

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

            <com.google.android.material.appbar.CollapsingToolbarLayout
                android:id="@+id/main_collapsing"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

                <FrameLayout
                    android:id="@+id/main_framelayout_title"
                    android:layout_width="match_parent"
                    android:layout_height="200dp"
                    android:layout_gravity="bottom|center_horizontal"
                    android:background="@android:color/holo_blue_light"
                    android:orientation="vertical"
                    app:layout_collapseMode="parallax"
                    app:layout_collapseParallaxMultiplier="0.3">

                    <LinearLayout
                        android:id="@+id/main_linearlayout_title"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center"
                        android:orientation="vertical">

                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_gravity="center_horizontal"
                            android:gravity="bottom|center"
                            android:text="스크롤하지 않았을 때"
                            android:textColor="@android:color/white"
                            android:textSize="30sp" />

                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:layout_gravity="center_horizontal"
                            android:layout_marginTop="4dp"
                            android:text="표시되는 글자들"
                            android:textColor="@android:color/white" />

                    </LinearLayout>

                </FrameLayout>

            </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:layout_marginTop="30dp"
            android:scrollbars="none"
            android:overScrollMode="never"
            android:fillViewport="true"
            tools:showIn="@layout/activity_collapsing_toolbar"
            app:behavior_overlapTop="30dp"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <androidx.cardview.widget.CardView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="8dp"
                app:cardElevation="8dp"
                app:contentPadding="16dp">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:lineSpacingExtra="8dp"
                    android:text="@string/lorem"
                    android:textSize="18sp" />

            </androidx.cardview.widget.CardView>

        </androidx.core.widget.NestedScrollView>

        <!-- 스크롤이 올라갔을 때 표시될 텍스트, 버튼들이 표시되는 툴바
        theme 속성을 @style/ThemeOverlay.AppCompat.Light로 설정하면 툴바 안의 버튼들 색이 검게 변한다 -->
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/main_toolbar"
            android:layout_width="match_parent"
            android:layout_height="?android:attr/actionBarSize"
            android:background="@color/colorAccent"
            app:layout_anchor="@id/main_framelayout_title"
            app:theme="@style/ThemeOverlay.AppCompat.Light"
            app:titleTextColor="@color/black"
            app:subtitleTextColor="@color/black"
            app:title="">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/main_textview_title"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_marginLeft="8dp"
                    android:gravity="center_vertical"
                    android:textColor="@color/black"
                    android:textSize="20sp" />

                <TextView
                    android:id="@+id/main_textview_subTitle"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:layout_marginStart="12dp"
                    android:gravity="center_vertical"
                    android:textColor="#FF0000"
                    android:textSize="14dp" />

            </LinearLayout>

        </androidx.appcompat.widget.Toolbar>

    </androidx.coordinatorlayout.widget.CoordinatorLayout>

</layout>

 

NestedScrollView 태그 안의 마지막 속성을 보면 layout_behavior로 위에서 말한 Behavior를 설정하는 걸 볼 수 있다.

이제 마지막으로 코틀린 파일을 만들어준다.

 

import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.View.INVISIBLE
import android.view.View.VISIBLE
import android.view.animation.AlphaAnimation
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.example.kotlinprac.R
import com.example.kotlinprac.databinding.ActivityCollapsingToolbarBinding
import com.google.android.material.appbar.AppBarLayout
import kotlin.math.abs

class CollapsingToolbarActivity : AppCompatActivity(), AppBarLayout.OnOffsetChangedListener {

    private lateinit var binding: ActivityCollapsingToolbarBinding

    private val PERCENTAGE_TO_SHOW_TITLE_AT_TOOLBAR = 0.9f
    private val PERCENTAGE_TO_HIDE_TITLE_DETAILS = 0.3f
    private val ALPHA_ANIMATIONS_DURATION = 200L

    private var mIsTheTitleVisible = false
    private var mIsTheTitleContainerVisible = true

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_collapsing_toolbar)
        binding.run {
            lifecycleOwner = this@CollapsingToolbarActivity
            mainAppbar.addOnOffsetChangedListener(this@CollapsingToolbarActivity)
            mainToolbar.inflateMenu(R.menu.menu_main)
            setSupportActionBar(mainToolbar)
            supportActionBar!!.setDisplayHomeAsUpEnabled(true)
            startAlphaAnimation(mainTextviewTitle, 0, INVISIBLE)
        }
    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.menu_main, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            android.R.id.home -> {
                Toast.makeText(this, "뒤로가기 버튼 클릭", Toast.LENGTH_SHORT).show()
            }
            R.id.action_settings -> {
                Toast.makeText(this, "클릭", Toast.LENGTH_SHORT).show()
            }
        }
        return super.onOptionsItemSelected(item)
    }

    override fun onOffsetChanged(appBarLayout: AppBarLayout?, offset: Int) {
        val maxScroll = appBarLayout!!.totalScrollRange
        val percentage = abs(offset).toFloat() / maxScroll.toFloat()

        handleAlphaOnTitle(percentage)
        handleToolbarTitleVisibility(percentage)
    }

    private fun handleToolbarTitleVisibility(percentage: Float) {
        if (percentage >= PERCENTAGE_TO_SHOW_TITLE_AT_TOOLBAR) {
            if (!mIsTheTitleVisible) {
                startAlphaAnimation(binding.mainTextviewTitle, ALPHA_ANIMATIONS_DURATION, VISIBLE)
                startAlphaAnimation(binding.mainTextviewSubTitle, ALPHA_ANIMATIONS_DURATION, VISIBLE)
                binding.mainTextviewTitle.text = "Title"
                binding.mainTextviewSubTitle.text = "subTitle"
                mIsTheTitleVisible = true
            }
        } else {
            if (mIsTheTitleVisible) {
                startAlphaAnimation(binding.mainTextviewTitle, ALPHA_ANIMATIONS_DURATION, INVISIBLE)
                startAlphaAnimation(binding.mainTextviewSubTitle, ALPHA_ANIMATIONS_DURATION, INVISIBLE)
                mIsTheTitleVisible = false
            }
        }
    }

    private fun handleAlphaOnTitle(percentage: Float) {
        if (percentage >= PERCENTAGE_TO_HIDE_TITLE_DETAILS) {
            if (mIsTheTitleContainerVisible) {
                startAlphaAnimation(binding.mainLinearlayoutTitle, ALPHA_ANIMATIONS_DURATION, INVISIBLE)
                mIsTheTitleContainerVisible = false
            }
        } else {
            if (!mIsTheTitleContainerVisible) {
                startAlphaAnimation(binding.mainLinearlayoutTitle, ALPHA_ANIMATIONS_DURATION, VISIBLE)
                mIsTheTitleContainerVisible = true
            }
        }
    }

    private fun startAlphaAnimation(view: View, duration: Long, visibility: Int) {
        val alphaAnimation =
            if (visibility == VISIBLE) AlphaAnimation(0f, 1f)
            else AlphaAnimation(1f, 0f)
        alphaAnimation.apply {
            this.duration = duration
            this.fillAfter = true
            view.startAnimation(this)
        }
    }

}

 

그리고 앱을 빌드하면 아래 화면이 나타난다. 화면이 어떻게 표시되는지 공부하기 위해서 색깔을 무작위로 배치해서 색깔들이 산만하다.

 

 

일정 부분까지 스크롤을 올리면 파란 영역 안의 글자들이 지워지고 툴바 안에 검은색, 빨간색 글자들이 생기는 걸 볼 수 있다. 왼쪽 위의 뒤로가기 버튼과 메뉴 버튼, 옵션 버튼을 눌러도 정상적으로 작동하는 걸 볼 수 있다.

예제가 NestedScrollView를 사용했지만 리사이클러뷰를 쓰더라도 똑같을 거라고 생각된다.

이제 이걸 커스텀해서 본인에게 맞는 화면을 만들어보자.

반응형
Comments