LoginSignup
2
5

More than 5 years have passed since last update.

Navigation(Android Architecture Components)のサンプル

Posted at

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を使う

リソースにnavigationファイルを追加します。
image.png

MainActivityのnavigation設定です。
image.png

MainFragmentのnavigation設定です。
image.png

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のサンプルでした。詳しい人がいましたら、突っ込みお願いします。

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5