Help us understand the problem. What is going on with this article?

Navigation(Android Architecture Components)のサンプル

More than 1 year has passed since last update.

Navigation(Android Architecture Components)のサンプルを作ってみました。
複数のNavigation設定をLiveDataを使って連携しています。

GitHub

https://github.com/mitchibu/NavSample

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした