Navigation(Android Architecture Components)のサンプルを作ってみました。
複数のNavigation設定をLiveDataを使って連携しています。
GitHub
Navigationの導入
Gradleの設定
Navigationを使用するための設定を追加します。
build.gradle(Project)
dependencies {
classpath 'android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0-alpha09'
}
build.gradle(Module)
apply plugin: 'androidx.navigation.safeargs'
dependencies {
implementation 'android.arch.navigation:navigation-fragment:1.0.0-alpha09'
implementation 'android.arch.navigation:navigation-ui:1.0.0-alpha09'
}
Navigation Editorを使う
MainActivityでNavigationにToolbar・DrawerLayout+NavigationViewを連携させる
MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setSupportActionBar(getBinding().toolBar);
// NavHostFragmentからNavControllerを取得する
NavHostFragment host = (NavHostFragment)getSupportFragmentManager().findFragmentById(R.id.nav_host);
NavController controller = NavHostFragment.findNavController(Objects.requireNonNull(host));
// ToolbarとDrawerLayoutを連携させる
NavigationUI.setupActionBarWithNavController(this, controller, getBinding().drawer);
// NavigationViewを連携させる
NavigationUI.setupWithNavController(getBinding().navigation, controller);
}
@Override
public void onBackPressed() {
// Drawerが開いているときにBackした場合にはDrawerを閉じる
if(getBinding().drawer.isDrawerOpen(GravityCompat.START)) {
getBinding().drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// NavigationViewとNavigationを連携させる
return NavigationUI.onNavDestinationSelected(item, controller) || super.onOptionsItemSelected(item);
}
@Override
public boolean onSupportNavigateUp() {
// ToolbarとNavigationを連携させる
return NavigationUI.navigateUp(controller, getBinding().drawer) || super.onSupportNavigateUp();
}
MainFragmentでNavigationにBottomNavigationViewを連携させる
MainFragment.java
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// NavHostFragmentからNavControllerを取得する
NavHostFragment host = (NavHostFragment)getChildFragmentManager().findFragmentById(R.id.nav_host);
NavController controller = NavHostFragment.findNavController(Objects.requireNonNull(host));
// BottomNavigationViewを連携させる
NavigationUI.setupWithNavController(getBinding().bottomNavigation, controller);
}
HomeFragmentからSubFragmentを開くために
Navigationの設定では、HomeFragmentとSubFragmentは繋がっていないため直接開くことはできません。RxやMessenger等を使って連携させる方法があるらしいですが、私はLiveDataを使って連携させてみました。
ShareViewModel.java
public class ShareViewModel extends ViewModel {
public static ShareViewModel get(Fragment fragment) {
return ViewModelProviders.of(Objects.requireNonNull(fragment.getActivity())).get(ShareViewModel.class);
}
// 今回の肝になるLiveDataです
private final MutableLiveData<Long> showSubFragment = new MutableLiveData<>();
// SubFragmentを開く場合にコールします
public void showSubFragment() {
showSubFragment.postValue(System.currentTimeMillis());
}
// SubFragmentを開くためにイベントを登録します
public void setOnShowSubFragment(LifecycleOwner owner, final NavController controller, final NavDirections directions) {
final Observer<Long> observer = new OnChangedObserver<Long>(showSubFragment.getValue()) {
@Override
public void onChangedValue(@Nullable Long value) {
controller.navigate(directions);
}
};
owner.getLifecycle().addObserver(new LifecycleObserver() {
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void onStop() {
showSubFragment.removeObserver(observer);
}
});
showSubFragment.observe(owner, observer);
}
}
MainFragment.java
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// MainFragmentはSubFragmentと繋がっているのでShareViewModelに登録します
ShareViewModel.get(this).setOnShowSubFragment(this, Navigation.findNavController(Objects.requireNonNull(getView())), MainFragmentDirections.actionMainFragmentToSubFragment());
}
HomeFragment.java
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getBinding().test.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// SubFragmentを開きたいのでShareViewModel.showSubFragmentをコールします
ShareViewModel.get(HomeFragment.this).showSubFragment();
}
});
}
以上、Navigationのサンプルでした。詳しい人がいましたら、突っ込みお願いします。