본문 바로가기

Android

NavIndicator와 NavigationUp

현재 Drawer를 사용해서 메뉴를 선택하는 구조를 사용하고 있다.
그리고 Drawer와 ActionBar는 Activity에 속해 있으며, 이 부분을 제외한 부분을 Fragment가 사용한다.

우선 Navigation Component에서 NavigationView 동작을 사용할 수 있도록 연결시키자.

// navController와 drawer를 연결하여 동작하도록 이어준다.
NavigationUI.setupActionbarWithNavController(this, navController, drawer);


navController와 Drawer를 연결시키는 코드를 적용하고 실행해보면
navController.navigateTo()의 메소드를 실행함과 동시에 ActionBar의 Icon이 자동으로 변경되는 것을 알 수 있다.

하지만 Icon 모양만 바꼈을뿐 Up Icon(뒤로가기 화살표 아이콘)을 눌러도 이전화면으로 돌아가지 않는다.
기존 navIndicator(햄버거 아이콘)을 눌렀을때처럼 Drawer가 열리는 동작을 수행한다.

Up 아이콘을 누름으로써 이전화면으로 이동할 수 있도록 수정하기전에 XML 구조를 한 번 살펴보자.

<!-- Architecture of ActionBar -->
<DrawerLayout>
  <NavigationView>
    <AppBarLayout>
      <CollapsingToolbarLayout>
        <Toolbar/>
      </CollapsingToolbarLayout>
    </AppBarLayout>
  </NavigationView>  
</DrawerLayout>

가장 바깥에 위치한 레이아웃은 DrawerLayout 그리고 NavigationView이다.
구조상 Touch Action을 우선적으로 가져가는 녀석이 Drawer가 된다는 말이다.

그래서 Up 아이콘을 선택해도 Drawer가 Touch를 가져가기 때문에 NavigationView가 열리는 것이다.

가장 간단한 해결책은 Drawer에서 Touch Action을 가져가는 것을 막아주면 된다.

DrawerLayout drawer = findViewById(R.id.drawer);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(Activity, drawer, ..., ...);
toggle.setNavigationIndicatorEnabled(false);

ActionBarDrawerToggle은 DrawerLayout.DrawerListener 인터페이스의 구현체이다.
즉 Drawer에서 사용되는 Listener를 조작하는 인터페이스를 구현한 것이다.
이 toggle을 이용해서 Navigation Indicator를 Disable 시켜주면 Drawer의 onClickListener가 작동하지 않게된다.

그렇다면 Drawer가 소비하지 않는 Touch Action을 소비할 다른 Listener를 등록해줘야한다.

알맞은 소비자는 Toolbar가 될 것이다.

ActionBarDrawerToggle을 살펴보면 Drawer를 disable 시키고 Toolbar의 Action를 위한 Listener를 세팅하는 메소드가 구현되어 있다. 그리고 주석으로 잘 설명되어있다.

View.OnClickListener listener = new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        navController.navigateUp();
    }
};
toggle.setToolbarNavigationClickListener(listener)

이제 정상적으로 Up icon이 navigateUp() 동작을 수행할 수 있게 되었다.

또 다른 문제점은 Fragment의 변화에 맞춰서 Activity에 있는 Drawer의 Listener를 바꿔줘야한다는 점이다.
Fragment내의 어느 지점에서 동작을 수행하는게 가장 좋을 것인가 생각해보자.

Drawer Disable은 Fragment가 시작되고 onViewCreated()에서 Drawer의 id를 얻으면서 적용한다.
Fragment에서는 Drawer동작이 필요 없기 때문이다.

Fragment에서 작업을 마치고 다시 이전 화면으로 돌아갈때 navigateUp(), 뒤로가기 버튼, 저장버튼 3가지의 이동방법이 있다.
그리고 이전 화면이 되었을때는 ToolbarListener는 해제되어야하고 Drawer는 다시 Enable되어야한다.

3가지 이동방법에 모두 해당 작업을 추가하지 않고 Activity에서 화면 전환을 읽는 Listener에서 화면이 전환되는 것을 기준으로 작업을 진행하던가, Fragment가 종료될때 호출되는 Fragment.onDestroy()에서 작업을 진행하는 방법이 가능하다.

Activity에 있는 Toolbar이지만 Drawer를 비활성화하고 활성화 하는 작업은 특정한 Fragment에서만 요구되는 작업이므로 가능하면 Fragment안에서 로직을 처리하는 것으로 결정한다.

// onDestroy()에서 할 작업.
toggle.setNavigationIncidatorEnabled(true)
drawer.removeDrawerToggle(toggle);

'Android' 카테고리의 다른 글

EditText Scrollable  (0) 2019.10.25
자동 Keypad 보여주기  (0) 2019.10.25
FloatingActionButton Anchor to Appbar  (0) 2019.10.08
Navigation Component 사용하기  (0) 2019.10.03
Fragment에 리스트 출력하기 Part.2  (0) 2019.09.29