Search code examples
javaandroidandroid-fragmentsandroid-activitynavigation-drawer

Android Navigation Drawer Activity call Click event from Fragment


I created a Navigation Drawer Activity project in Android Studio and added some Fragments. Navigating through them works fine.

Now in the main fragment, I want to add some buttons that will take the user to some of the fragments, where the user would otherwise need to navigate to through the drawer menu. In other words, when the user opens the app, he should have the option to navigate to some fragments without opening the drawer menu. But I can't get it to work.

The closest I have come so far is with the following code in the main activity. However, this only works once. When I navigate to other fragments and go back to the main fragment, it will not work anymore. Clicking on the button should do the same as if the user navigated through the drawer menu.

public class MainActivity extends AppCompatActivity {

    private AppBarConfiguration mAppBarConfiguration;
    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        setSupportActionBar(binding.appBarMain.toolbar);
        binding.appBarMain.fab.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        DrawerLayout drawer = binding.drawerLayout;
        NavigationView navigationView = binding.navView;
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        mAppBarConfiguration = new AppBarConfiguration.Builder(
                R.id.nav_home, R.id.nav_hpfragment, R.id.nav_gallery, R.id.nav_slideshow)
                .setOpenableLayout(drawer)
                .build();
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
        NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
        NavigationUI.setupWithNavController(navigationView, navController);

        Button btnTest = binding.getRoot().findViewById(R.id.btnGotoDensityAlt);
        View.OnClickListener cl = new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                View x = navigationView.findViewById(R.id.nav_hpfragment);
                x.callOnClick();
            }
        };
        btnTest.setOnClickListener(cl);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onSupportNavigateUp() {
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
        return NavigationUI.navigateUp(navController, mAppBarConfiguration)
                || super.onSupportNavigateUp();
    }
}

What is the correct way to do this?


Solution

  • I solved this issue like this:

    I added this function to the main activity:

    public void navigateToHpCalc()
        {
            View view = binding.navView.findViewById(R.id.nav_hpfragment);
            view.callOnClick();
        }
    

    I called this function in the fragment like this:

    View.OnClickListener onGoToHpFragmentListener = new View.OnClickListener() {
                @Override
                public void onClick(View view) {
    
                    MainActivity fa = (MainActivity)getActivity();
                    fa.navigateToHpCalc();
                }
            };
    

    Full code:

    public class MainActivity extends AppCompatActivity {
    
        private AppBarConfiguration mAppBarConfiguration;
        private ActivityMainBinding binding;
    
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
    
            binding = ActivityMainBinding.inflate(getLayoutInflater());
            setContentView(binding.getRoot());
    
            setSupportActionBar(binding.appBarMain.toolbar);
            binding.appBarMain.fab.setOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View view) {
                    Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                            .setAction("Action", null).show();
                }
            });
            DrawerLayout drawer = binding.drawerLayout;
            NavigationView navigationView = binding.navView;
            // Passing each menu ID as a set of Ids because each
            // menu should be considered as top level destinations.
            mAppBarConfiguration = new AppBarConfiguration.Builder(
                    R.id.nav_home, R.id.nav_hpfragment, R.id.nav_gallery, R.id.nav_slideshow)
                    .setOpenableLayout(drawer)
                    .build();
            NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
            NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
            NavigationUI.setupWithNavController(navigationView, navController);
    
    
        }
    
        public void navigateToHpCalc()
        {
            View view = binding.navView.findViewById(R.id.nav_hpfragment);
            view.callOnClick();
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
        @Override
        public boolean onSupportNavigateUp() {
            NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
            return NavigationUI.navigateUp(navController, mAppBarConfiguration)
                    || super.onSupportNavigateUp();
        }
    }
    

    and

    public class HomeFragment extends Fragment {
    
        private FragmentHomeBinding binding;
    
        public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
        {
            HomeViewModel homeViewModel = new ViewModelProvider(this).get(HomeViewModel.class);
    
            binding = FragmentHomeBinding.inflate(inflater, container, false);
            View root = binding.getRoot();
    
            final TextView textView = binding.textHome;
            final Button btn = binding.btnGotoDensityAlt;
    
            homeViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
    
    
            View.OnClickListener onGoToHpFragmentListener = new View.OnClickListener() {
                @Override
                public void onClick(View view) {
    
                    MainActivity fa = (MainActivity)getActivity();
                    fa.navigateToHpCalc();
                }
            };
    
            View.OnClickListener onGoToGallery = new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    //Navigation.findNavController(root).navigate(R.id.action_nav_home_to_nav_gallery);
                }
            };
            binding.btnGotoDensityAlt.setOnClickListener(onGoToHpFragmentListener);
            binding.btnGoToGallery.setOnClickListener(onGoToGallery);
    
    
            return root;
        }
    
    
    
    
    
        @Override
        public void onDestroyView() {
            super.onDestroyView();
            binding = null;
        }
    }
    

    I am stil not sure this is the best practice way to do it though.