💡 툴바 구현은 다음 포스팅에 살펴보도록 하고, 이번에는 페이지 및 액티비티를 구현하면서 고민했던 것을 중점으로 글을 쓰겠습니다.
MainApplication 이라는 액티비티를 하나 만듭니다.
MainApplication 클래스는 Application()
과 Configuraion.Provider
클래스를 상속 받고 있습니다.
//build.gradle(app)
implementation "androidx.work:work-runtime-ktx:$rootProject.workVersion" //WorkManager
프로젝트 단위의 gradle 파일에서 라이브러리들의 version을 관리하고, $rootProject
를 통해 가져옵니다.
앱 안의 어떤 컴포넌트에서도 공유할 수 있는 전역 클래스입니다. Application 클래스를 상속 받은 클래스는 공동으로 관리해야 되는 데이터를 작성하기에 적합합니다. 저는 WorkManager 구성을 초기화하는 작업을 하는 데에 해당 클래스를 사용했습니다. 기본적으로 WorkManager는 앱이 시작될 때 자동으로 구성되는데, 이것을 커스텀하면 컴포넌트가 실행될 때 필요한 작업을 따로 WorkManager로 관리할 수 있습니다.
관련 자료 : Android developer
위의 관련 자료에서 보여지는 것처럼 AndroidManifest.xml 파일을 수정하면 됩니다.
application
태그의 name 속성을 Application() 클래스를 상속받은 클래스명으로 바꿔줍니다. 저의 경우 ".MainApplication" 으로 바꿔 주었습니다.
그 다음, provider
태그의 내용을 변경해주는데,
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<!-- If you are using androidx.startup to initialize other components -->
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
이렇게 바꿔주면 됩니다. 이러면 처음 앱을 시작할 때 WorkManager를 자동으로 시작하지 않게 됩니다.
window는 MainApplication
다음으로 실행되는 MainActivity
에서 생성합니다. AndroidManifest.xml
에서 activity 태그에 MainActivity가 오도록 추가합니다.
안드로이드에서 UI를 렌더링 하기 위해 사용하는 개념으로는 window, surface, canvas, view 가 있고 각 요소의 크기는 window > surface > canvas > view 순입니다.
MainApplication에서 WorkManager Configuration을 빌드한 후, 처음 실행되는 Activity에서 window를 생성합니다.
windowCompat
: window 클래스의 속성을 사용하도록 도와주는 클래스setDecorFitsSystemWindows
: 전체 화면 UI를 기기의 해상도(가로 X 세로)에 맞춰준다. 파라미터를 false로 설정해야 “SYSTEM_UI_LAYOUT_FLAG” 중에서 deprecated될 flag 값을 무시하고 window inset을 통해 화면을 구성할 수 있습니다.class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
setContentView(R.layout.activity_timeline)
}
}
MainActivity.kt
을 보면 알 수 있듯이, activity_timeline.xml을 먼저 보여줍니다. 카카오버스의 메인페이지를 보면, 즐겨찾기로 설정한 버스정류장의 버스도착 정보를 보여주고 해당 아이템 클릭 시 세부 정보 화면으로 이동하기에 FragmentContainerView
로 전체를 감싼 뒤 네비게이션으로 fragment들을 연결시키면 될 것 같았습니다.
res 디렉토리 안에 [navigation] 폴더를 생성합니다. 그 다음 시작점이 될 Fragment를 하나 만듭니다. Fragment 생성 같은 경우는 app에서 우클릭 → [New] → Fragment → Fragment(Blank) 로 들어가서 생성하면 자동으로 layout 파일과 activity 파일이 생성됩니다. 저 같은 경우는 viewpager를 첫번째 fragment로 설정하기 위해 HomeViewPagerFragment
를 생성했습니다. 이렇게 생성된 Fragment를 navigation 파일에서 startDestination으로 지정해주고, fragment
태그로 삽입합니다.
activity_timeline.xml 파일에서 navGraph 속성값으로 방금 생성한 navigation 파일을 지정해줍니다.
NavGraph란?
모든 Navigation 정보가 모여있는 XML 리소스 파일입니다. 위의 사진에서 보이는 것과 같이, NavGraph는 앱에서 각 화면들이 어떻게 Navigation이 이루어져야 하는지 보여줍니다.
구글에서 현재 추천하는 Navigation 구현방식은, 액티비티는 앱의 entry point로만 사용하고 BottomNavigation이나 Drawer Navigation 같은 global Navigation을 가질 수 있도록 하는 것입니다. 즉, 단일 액티비티가 있고, Fragment들 사이에서 Navigation이 이루어져야 합니다. 이렇게 구현하기 위해서는 NavHost
관련 정의가 필요합니다.
NavHostFragment
widget이며, NavGraph에 정의된 대로 Fragment를 Navigation시켜주고 각 destination들을 보여주는 역할을 합니다. NavHostFragment라는 그릇이 있고, NavGraph에서 정의한 Fragment들이 담겨져서 보여집니다.
android:name
속성에 NavHostFragment를 지정해줌으로써 정의할 수 있습니다.
defaultNavHost
defaultNavHost 속성값을 true로 지정하면 System의 back 버튼과 연결됩니다. 해당 속성은 단 하나만 지정되어야 한다는 제약조건이 있습니다.
이렇게 base 페이지 설계하며 네비게이션까지 구현한 것을 살펴 보았습니다. 다음 포스팅에서는 ToolBar를 구현하며 고민했던 부분들을 살펴 보겠습니다 :)