이번 강의에서는 조각을 만들고, 탐색 경로를 정의하고, 외부 활동을 시작합니다. 안드로이드 개발 관련 사소한 질문에 답하고, 이기면 결과를 공유할 수 있는 게임인 안드로이드 트리비아 앱을 완성합니다.
03.1 Create a fragment
- https://github.com/google-developer-training/android-kotlin-fundamentals-starter-apps
- 깃허브에서 AndroidTrivia-Starter를 다운받아서 코드 작성을 진행합니다.
● Add a fragment
- fragment는 활동의 모듈식 섹션
- fragment는 자체 라이프사이클을 가지며 자체 입력 이벤트를 수신
- <fragment> 태그를 사용하여 XML 레이아웃 파일에서 조각에 대한 레이아웃을 정의
- onCreateView()에서 fragment 레이아웃을 올림
- 활동이 실행되는 동안 fragment를 추가하거나 제거
- Fragment's lifecycle 동안 호출되는 방법중 하나인 onCreateView()
- TitleFragment.kt에 아래 코드를 추가해 보기를 확장(inflate)하는 DataBindingUtil.inflate() 호출해 인수 전달
val binding = DataBindingUtil.inflate<FragmentTitleBinding>(inflater,
R.layout.fragment_title,container,false)
03.2 Define navigation paths
● navigation 종속성 추가
- Navigation component : 앱의 화면 간에 전달되는 복잡한 탐색, 전환 애니메이션, 심층 링크 및 컴파일 시간 확인 인수를 관리할 수 있는 라이브러리
- 탐색 라이브러리를 사용하려면 네비게이션 종속성을 Gradle 파일에 추가 (navigationVersion에 대한 변수 추가)
- build.gradle(:app)에 navigation-fragment-ktx , navigation-ui-ktx종속성 추가
implementation "androidx.navigation:navigation-fragment-ktx:$navigationVersion"
implementation "androidx.navigation:navigation-ui-ktx:$navigationVersion"
● Add a navigation graph
● Create the NavHostFragment
- navigation host fragment : 탐색 그래프의 조각에 대한 호스트 역할
- activity_main.xml에 아래 사항들을 추가해 준다.
<fragment
android:id="@+id/myNavHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:navGraph="@navigation/navigation"
app:defaultNavHost="true"
/>
- ID를 myNavHostFragment로 변경
- app:navGraph 특성을 추가하여 탐색 그래프 리소스(@navigation/navigation)로 설정
- app:defaultNavHost = "true" 특성을 추가하여 탐색 호스트가 기본 호스트이며 시스템 뒤로 버튼을 인터셉트
● Add fragments to the navigation graph
- New Destination : TitleFragment, GameFragment
- TitleFragment.kt에 setOnClickListener 추가: 바인딩 클래스를 통해 play button 액세스하는 코드 추가, 게임 fragment로 이동
binding.playButton.setOnClickListener{view : View ->
view.findNavController().navigate(R.id.action_titleFragment_to_gameFragment)}
- conditional navigation: 사용자가 모든 질문에 올바르게 대답하는지 여부에 따라 앱이 다른 Fragment로 이동
- else를 사용해 이기고 진 경우를 나누어 설정
● Change the Back button's destination
- 사용자가 뒤로 버튼을 누르면 앱이 백 스택의 맨 위에 있는 대상으로 이동. 기본적으로 백 스택의 맨 위는 사용자가 마지막으로 본 화면
- 게임이 끝나고 뒤로 버튼을 누르면 TitleFragment로 돌아가도록 설정
- Layout Editor의 Attributes 창에 있는 Pop To 필드를 사용하여 수행(백 스택 관리)
- GameWonFragment.kt에 아래의 코드를 추가해 back stack을 관리
// Add OnClick Handler for Next Match button
binding.nextMatchButton.setOnClickListener{view: View->
view.findNavController()
.navigate(R.id.action_gameWonFragment_to_gameFragment)}
● Add an Up button in the app bar
( app bar = action bar : 앱 브랜딩 및 아이덴티티를 위한 전용 공간 )
- The Up button: app bar에 위치한 뒤로가기 버튼을 사용해 이전 동작으로 돌아갈 수 도 있음
● Add an options menu
- 속성에 id ="aboutFragment", title = "@string/about으로 설정
● Add an onClick handler
TitleFragment.kt
package com.example.android.navigation
import android.os.Bundle
import android.view.*
import androidx.fragment.app.Fragment
import androidx.databinding.DataBindingUtil
import androidx.navigation.findNavController
import androidx.navigation.ui.NavigationUI
import com.example.android.navigation.databinding.FragmentTitleBinding
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
class TitleFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val binding = DataBindingUtil.inflate<FragmentTitleBinding>(inflater,
R.layout.fragment_title,container,false)
binding.playButton.setOnClickListener{view : View ->
view.findNavController().navigate(R.id.action_titleFragment_to_gameFragment)}
setHasOptionsMenu(true)
return binding.root
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.options_menu, menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return NavigationUI.
onNavDestinationSelected(item,requireView().findNavController())
|| super.onOptionsItemSelected(item)
}
}
- setHasOptionsMenu() 메서드를 호출하고 true로 전달
- 메소드에서 옵션 메뉴를 추가하고 메뉴 리소스 파일 inflate
- onOptionsItemSelected(): 메뉴 항목을 누를 때 적절한 작업을 수행
● Add the navigation drawer
- Material library추가
implementation "com.google.android.material:material:$version"
- ID확인
- drawer menu 생성
- Mainactivity.kt 코드에 SetupActionBarWithNavController() 메소드에 매개 변수로 Drager Layout 추가, UI.navigate Up 반환
class MainActivity : AppCompatActivity() {
private lateinit var drawerLayout: DrawerLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@Suppress("UNUSED_VARIABLE")
val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
drawerLayout = binding.drawerLayout
val navController = this.findNavController(R.id.myNavHostFragment)
NavigationUI.setupActionBarWithNavController(this,navController, drawerLayout)
NavigationUI.setupWithNavController(binding.navView, navController)
}
override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(R.id.myNavHostFragment)
return NavigationUI.navigateUp(navController, drawerLayout)
}
}
03.3 Start an external Activity
Safe Args:
- 한 조각에서 다른 조각으로 데이터를 전달할 때 키 누락 또는 불일치 유형으로 인한 오류를 포착하려면 SafeArgs라는 Gradle 플러그인을 사용(apply plugin: 'androidx.navigation.safeargs' 추가)
- 앱의 각 조각에 대해 SafeArgs 플러그인은 해당 NavDirection 클래스를 생성
- NavDirection 클래스를 조각 코드에 추가한 다음 클래스를 사용하여 조각과 다른 조각 간에 인수를 전달
- NavDirection 클래스는 모든 앱의 동작에서 탐색
● 추가인수 전달
Implicit intents:
- 앱이 다른 앱(카메라 앱 또는 이메일 앱 등)을 대신 수행하기를 원하는 액션을 선언
→ GameFragment.kt : 현재 질문 수와 총 질문수를 나타냄
- TitleFragment, GameOverFragment, GameWonFragment 에 아래 코드를 추가해 필요할 때마다 NavDirection 클래스를 사용하여 인수를 쉽게 전달할 수 있도록 앱이 설정됨
view.findNavController()
.navigate(TitleFragmentDirections.actionTitleFragmentToGameFragment())
※ Intent는 Android 구성 요소 간의 통신에 사용되는 간단한 메시지 개체(명시적/ 암시적)
Sharing functionality:
( 이 예제에서는 암시적 intent 사용 )
- GameWonFragment.kt에 아래와 같은 코드 추가
// Creating our Share Intent
private fun getShareIntent() : Intent {
val args = GameWonFragmentArgs.fromBundle(requireArguments())
val shareIntent = Intent(Intent.ACTION_SEND)
shareIntent.setType("text/plain")
.putExtra(Intent.EXTRA_TEXT, getString(R.string.share_success_text, args.numCorrect, args.numQuestions))
return shareIntent
}
// Starting an Activity with our new Intent
private fun shareSuccess() {
startActivity(getShareIntent())
}
- EXTAR_TEXT에 실제 전송 데이터 포함됨
- 공유 기능은 GameWonFragment 클래스 내의 옵션 메뉴를 통해 액세스
- intent를 구축하기 위해 ACTION_SEND와 같은 수행할 작업을 선언(암묵적)
- 성공 공유 시 Intent action이 Intent.ACTION_SEND 됨
- Fragment 옵션 메뉴를 추가하려면 Fragment 코드에서 setHasOptionsMenu() 메서드를 true로 설정
- startActivity()를 사용해 onOptionsItemSelected()를 오버라이드 해 다른 앱으로
퀴즈 정답
Navigation | Android 개발자 | Android Developers
Create a fragment, define navigation paths, and start an external activity. Complete the AndroidTrivia app, which is a game in which users answer trivia questions about Android development and can share their results if they win.
developer.android.com
'안드로이드' 카테고리의 다른 글
Android 1Team LiveData (0) | 2021.03.01 |
---|---|
Android - 1Team View Model (0) | 2021.03.01 |
[android - 1team] Unit3 : Layout (0) | 2021.01.16 |
[android - 1team] 안드로이드 experince 1 (0) | 2021.01.13 |
[안드로이드 2팀] Layouts - LinearLayout, ConstraintLayout, Data binding (0) | 2020.12.27 |