개발자 끄적끄적
메뉴(Menu), 다이얼로그(Dialog), 네비게이션(Navigation) UI 본문
<App Bar(ActionBar)>
- 앱의 상단에 표시
- 타이틀, 액션아이콘, 옵션메뉴를 표시
- AppBar 또는 Action Bar라고 불린다
- 주의 : 테마에서 NoActionBar를 쓰면 App Bar가 나타나지 않는다
- 참고 : Toolbar
- Jetpack 라이브러리로 제공되며, 레이아웃 내에 한 위젯처럼 취급
- 안드로이드 레이아웃 디자인에서 Toolbar(ID가 toolbar)를 추가
- Theme에서 parent를 NoActionBar로 변경
- Activity에서 setSupportActionBar(findViewById(R.i.toolbar))
- App Bar보다 더 유연하게 커스터마이즈 할 수 있다
<액션아이콘, 메뉴>
- App Bar에 액션아이콘, 옵션메뉴를 하나의 메뉴로 관리
- App Bar에 타이틀 표시하고 남은 공간에 액션아이콘과 메뉴 아이템을 배치
- 공간이 부족하여 배치가 어려운 것들은 오버플로우 메뉴에 표시
- 메뉴 작성 방법
- 메뉴 리소스 정의 : menu/파일이름.xml
- 액티비티의 onCreateOptionsMenu() 에서 메뉴 생성
- 액티비티의 onOptionsItemSelected() 에서 메뉴 선택 처리
<액션아이콘, 메뉴 - 메뉴 리소스 정의>
- menu/파일이름.xml
- <menu>태그 사이에
- <item/> 태그로 메뉴 항복
- 정의
- android:id - 항목 실별자
- android:icon - 항목 아이콘
- android:title - 항목 텍스트
- app:showAsAction
- "always" : 항상 액션 아이콘
- "ifRoom" : 공간이 가능하면
- "" 디폴트 : 항상 옵션 메뉴로
<액션아이콘, 메뉴 - 메뉴 생성>
- 액티비티의 onCreateOptionsMenu()
<액션아이콘, 메뉴 - 메뉴 선택 처리>
- 액티비티의 onOptionsItemSelected()
<팝업 메뉴>
- 안드로이드에서 메뉴 종류
- 옵션 메뉴, 팝업 메뉴, 컨텍스트 메뉴
- 컨텍스트 메뉴 : 롱클릭으로 해당 항목(뷰)와 관련된 메뉴 표시
- 팝업 메뉴
- 뷰 위에 메뉴 표시
- Popup 클래스
- 팝업 메뉴 생성과 선택 처리
private fun showPopup(v: View) { // v는 팝업 메뉴를 보여줄 뷰, 클릭한 뷰를 보통 사용
PopupMenu(requireContext(), v).apply { // requireContext()는 프래그먼트에서
inflate(R.menu.nav_menu) // 메뉴 리소스로 메뉴 생성
setOnMenuItemClickListener { // 메뉴 선택 처리를 위한 리스너
when (it.itemId) {
R.id.homeFragment -> {
Snackbar.make(v, "HomeFragment", Snackbar.LENGTH_SHORT).show()
true
}
else -> false
}
}
}.show() // 팝업 메뉴 나타나게 함
}
- 주의 : Jetpack의 클래스 사용 권장 : androidx.appcompat.widget.PopupMenu
<다이얼로그(Dialog, 대화상자)>
- 사용자의 결정이나 입력을 받기 위해 화면에 표시되는 작은 윈도우
- 다이얼로그 생성 클래스
- AlertDialog
- DatePickerDialog, TimePickerDialog
- DialogFragment 내에서 다이얼로그 클래스로 만들어 사용해야한다
<다이얼로그 - 생성>
- DialogFragment에서 onCreateDialog 정의
- AlertDialog.Builder 사용하여 AlertDialog에 객체 생성 리턴
- requireActivity() : 프래그먼트에서 액티비티 객체를 받는 메소드, 없으면 exception 발생
- requireContext() : 프래그먼트에서 컨텍스트 객체를 받는 메소드, 없으면 exception 발생
보통 activity는 context를 상속 받기 때문에 실제로 같다고 보면 된다
<다이얼로그 - 보이기>
- 다이얼로그 프로그먼트 생성하고 show()호출
- OkCancelDialogFragment().show(supportFragmentManager, "OkCancelDialog")
<다이얼로그 - DatePickerDialog>
- DatePickerDialog 생성, 선택한 날짜 받기 위한 리스터 필요
class DatePickerFragment : DialogFragment(), DatePickerDialog.OnDateSetListener {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return DatePickerDialog(requireContext(), this,
2021, 4, 5) // Jan: 0, Feb:1, Mar:2, Apr: 3, May:4 ...
}
override fun onDateSet(view: DatePicker?, year: Int, month: Int, dayOfMonth: Int) {
println("$year, $month, $dayOfMonth")
}
}
<다이얼로그 - 커스텀 다이얼로그>
- DialogFragmnet의 onCreateView와 onViewCreated 재정의
class MyBottomSheetDialog : BottomSheetDialogFragment() {
private val myViewModel: MyViewModel by activityViewModels()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
isCancelable = false
return inflater.inflate(R.layout.my_bottom_dialog, container,false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
view.findViewById<EditText>(R.id.editTextName)?.setText(myViewModel.nameLiveData.value)
view.findViewById<Button>(R.id.buttonOk)?.setOnClickListener {
myViewModel.nameLiveData.value = view.findViewById<EditText>(R.id.editTextName)?.text.toString()
dismiss()
}
}
- 일반 다이얼로그는 BottomSheetDialogFragment 대신 DialogFragment 사용하면 된다
<네비게이션 UI>
- NavigationUI 클래스
- App Bar, 네비게이션 Drawer, Bottom 네비게이션과 함께 Jetpack Navigation을 도와주는 기능을 갖고 있다
- Jetpack Navigation
- Navigation 그래프
- NavHostFragment
- NavController
<네비게이션 UI : App Bar>
- App Bar에 Up버튼 표시
- App Bar에 프래그먼트 label
- AppBarConfiguration 생성
- Top 목적지 지정, setOf(그래프에서 프래그먼터들의 ID)
- Top 목적지에는 Up버튼 표시하지 않는다
- 따로 정하지 않으면 Home이 Top목적지가 된다
- NavController와 AppBarConfiguration 연결
- onSupportNavigateUp() 재정의
- Up과 Back의 차이
- Up : parent 목적지로 이동
- Back : 이전 목적지로 이동
- 보통은 이전(back)목적지가 parent와 같은 경우가 대부분
<네비게이션UI : App Bar>
- AppBarConfiguration 생성과 NavController 연결
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// setup actionbar with nav controller to show up button
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragment) as NavHostFragment
val navController = navHostFragment.navController
// CAUTION: findNavController(R.id.fragment) in on Create will fail.
appBarConfiguration = AppBarConfiguration(navController.graph) // Home이 Top 목적지
setupActionBarWithNavController(navController, appBarConfiguration) // 연결
}
- AppBarConfiguration(setOf(R.id.homeFragment, R.id.page1Fragment))라고 하면 homeFragment와 page1Fragment가 Top목적지가 되며,
이 프래그먼트가 나타날 때는 Up버튼 표시가 안된다
<네비게이션UI : App Bar>
- onSupportNavigateUp() 재정의
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
// 생략 – 앞 슬라이드 참고
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.fragment)
return navController.navigateUp(appBarConfiguration)
|| super.onSupportNavigateUp()
}
- Jetpack Toolbar를 사용하면 onSupportNavigateUp 재정의 필요 없다
<네비게이션UI : App Bar + 옵션 메뉴>
- 옵션 메뉴의 메뉴 항복 ID를 네비게이션 그래프의 프래그먼트(목적지) ID와 일치시키면, MenuItem의
onNavDestinationSelected() 호출 하여 해당 목적지로 전환
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/page1Fragment"
android:icon="@drawable/ic_baseline_inbox_24"
android:title="@string/page1" />
// 일부 항목 생략 – 전체는 뒤에 나오는 nav_menu.xml 참고
</menu>
class MainActivity : AppCompatActivity() {
// onCreate, onSupportNavigteUp() 생략
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main_menu, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.page1Fragment ->
item.onNavDestinationSelected(findNavController(R.id.fragment))
else -> return super.onOptionsItemSelected(item)
}
return true
}
}
<네비게이션UI : App Bar + Drawer
- 서랍(Drawer)형태로 메뉴가 나왔다 들어가는 UI
- 서랍에 나타낼 메뉴 항목 정의하는 메뉴 리소스 작성
- DrawerLayout 사용하고 그 안에 아래 2개 포함 시켜야한다
- FragmentContainerView - NavHostFragment를 위한 프래그먼터 자리
- Navigation View - 서랍 레이아웃
- onCreate() 코드 추가
- AppBarConfiguration 생성
- NavController와 AppBarConfiguration 연결
- NavController와 NavigationView 연결
<네비게이션 UI: Bottom Navigation>
- 화면 아래 목적지에 해당하는 버튼을 나열, 클릭하면 목적지로 이동
- Bottom Navigation에 나타낼 메뉴 항목 정의하는 메뉴 리소스 작성
- 앞의 Navigation Drawer에서 사용한 메뉴 리소스와 동일한 것 사용
- LinearLayout내에 2개 포함 시켜야 한다
- FragmentContainerView : NavHostFragment를 위한 프래그먼터 자리
- BottomNavigationView : Bottom Navigation 버튼들
- onCreate() 코드 추가
- NavController와 BottomNavigationView 연결
- Bottom Nav도 App Bar와 같이 사용 가능하지만 여기에서는 사용하지 않는다
'안드로이드 프로그래밍' 카테고리의 다른 글
목록표시 UI (0) | 2023.05.14 |
---|---|
Activity, Intent (0) | 2023.04.15 |
위젯, 리소스 (0) | 2023.04.10 |