I have 2 activities with a separate NavHostFragment
which hosts 3 fragments, these 3 fragments are then displayed in my activity's layout ContainerView
.
Note: My 2 activities have the same name and use the same layout, the only difference is that they are in different directories and handle slightly different tasks.
Initially, I planned on using all fragments for the app but now, I decided to use only one for the first release, then work on the others later because it was tasking to handle all at once
So I want to safely remove the bottom navigation view and the other two fragments(second & third fragment).
Already, I have initially tried doing it on my own by deleting those fragments and erasing any code related to it but it came up with a lot of errors, so I decided to bring it here to see if anyone could help with the safest possible way that I could remove them so that my first fragment can continue to function without any issues.
It is a weather app, so I receive current city updates on the first fragment. I was supposed to receive hourly & daily updates on the second & third fragments but I've halted my plan, for now, I want to use only the first fragment.
Here are the principal codes:
Activity\HomeActivity:
public class HomeActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
private DrawerLayout drawer;
// Last update time, click sound, search button, search panel.
TextView timeField;
MediaPlayer player;
ImageView Search;
EditText textfield;
// For scheduling background image change(using constraint layout, start counting from dubai, down to statue of liberty.
ConstraintLayout constraintLayout;
public static int count = 0;
int[] drawable = new int[]{R.drawable.nyc, R.drawable.lofoten_islands, R.drawable.parque, R.drawable.moraine_lake, R.drawable.eiffel_tower,
R.drawable.whitehaven_beach, R.drawable.london, R.drawable.cape_town, R.drawable.burj_al_arab,R.drawable.atuh_beach};
Timer _t;
private WeatherDataViewModel viewModel;
private AppBarConfiguration appBarConfiguration;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
// use home activity layout.
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Allow activity to make use of the toolbar
drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
// Hiding default Drawer fragment that has the BottomNavView
navigationView.getMenu().findItem(R.id.main_id).setVisible(false);
viewModel = new ViewModelProvider(this).get(WeatherDataViewModel.class);
// Trigger action to open & close navigation drawer
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar
, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
timeField = findViewById(R.id.textView9);
Search = findViewById(R.id.imageView4);
textfield = findViewById(R.id.textfield);
// find the id's of specific variables.
BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavigationView);
// host 3 fragments along with bottom navigation.
final NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
assert navHostFragment != null;
final NavController navController = navHostFragment.getNavController();
// Make hourly & daily tab unusable
bottomNavigationView.setOnNavigationItemSelectedListener(item -> {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
}
return false;
});
toggle.setToolbarNavigationClickListener(v -> {
// Enable the functionality of opening the side drawer, when the burger icon is clicked
toggle.setDrawerIndicatorEnabled(true);
navController.navigate(R.id.main_id);
});
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
// remove up button from all these fragments
appBarConfiguration = new AppBarConfiguration.Builder(
R.id.main_id) // remove up button from all these fragments >> Keep up button in R.id.nav_setting, R.id.nav_slideshow
.setOpenableLayout(drawer)
.build();
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
// navController.addOnDestinationChangedListener((controller, destination, arguments) -> navController.popBackStack(destination.getId(), false));
// navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
// });
navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
// Hide/show top search bar
if (destination.getId() == R.id.main_id) {
Search.setVisibility(View.VISIBLE);
textfield.setVisibility(View.VISIBLE);
} else {
Search.setVisibility(View.GONE);
textfield.setVisibility(View.GONE);
}
// Fragments that you want to show the back button
if (destination.getId() == R.id.about_id || destination.getId() == R.id.privacy_policy_id) {
// Disable the functionality of opening the side drawer, when the burger icon is clicked
toggle.setDrawerIndicatorEnabled(false);
}
});
// For scheduling background image change
constraintLayout = findViewById(R.id.layout);
constraintLayout.setBackgroundResource(R.drawable.nyc);
_t = new Timer();
_t.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
// run on ui thread
runOnUiThread(() -> {
if (count < drawable.length) {
constraintLayout.setBackgroundResource(drawable[count]);
count = (count + 1) % drawable.length;
}
});
}
}, 5000, 5000);
Search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// make click sound when search button is clicked.
player = MediaPlayer.create(HomeActivity.this, R.raw.click);
player.start();
getWeatherData(textfield.getText().toString().trim());
// make use of some fragment's data
Fragment currentFragment = navHostFragment.getChildFragmentManager().getFragments().get(0);
if (currentFragment instanceof FirstFragment) {
FirstFragment firstFragment = (FirstFragment) currentFragment;
firstFragment.getWeatherData(textfield.getText().toString().trim());
} else if (currentFragment instanceof SecondFragment) {
SecondFragment secondFragment = (SecondFragment) currentFragment;
secondFragment.getWeatherData(textfield.getText().toString().trim());
} else if (currentFragment instanceof ThirdFragment) {
ThirdFragment thirdFragment = (ThirdFragment) currentFragment;
thirdFragment.getWeatherData(textfield.getText().toString().trim());
}
}
private void getWeatherData(String name) {
ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
Call<Example> call = apiInterface.getWeatherData(name);
call.enqueue(new Callback<Example>() {
@Override
public void onResponse(@NonNull Call<Example> call, @NonNull Response<Example> response) {
try {
assert response.body() != null;
timeField.setVisibility(View.VISIBLE);
timeField.setText("First Updated:" + " " + response.body().getDt());
} catch (Exception e) {
timeField.setVisibility(View.GONE);
timeField.setText("First Updated: Unknown");
Log.e("TAG", "No City found");
Toast.makeText(HomeActivity.this, "No City found", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(@NotNull Call<Example> call, @NotNull Throwable t) {
t.printStackTrace();
}
});
}
});
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.about_id:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment,
new About()).commit();
break;
case R.id.privacy_policy_id:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment,
new Privacy_Policy()).commit();
break;
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
@Override
public void onBackPressed() {
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
// Open/close drawer animation
}
}
@Override
protected void onPause () {
super.onPause();
if (viewModel.getMediaPlayer() != null)
viewModel.getMediaPlayer().pause();
}
@Override
protected void onResume () {
super.onResume();
if (viewModel.getMediaPlayer() != null) {
viewModel.getMediaPlayer().start();
viewModel.getMediaPlayer().setLooping(true);
}
}
@Override
public boolean onSupportNavigateUp() {
final NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
assert navHostFragment != null;
final NavController navController = navHostFragment.getNavController();
return NavigationUI.navigateUp(navController, appBarConfiguration)
|| super.onSupportNavigateUp(); // navigateUp tries to pop the backstack
}
}
Lightweatherforecast\HomeActivity:
public class HomeActivity extends AppCompatActivity {
private DrawerLayout drawer;
// Last update time, click sound, search button, search panel.
TextView timeField;
MediaPlayer player;
ImageView Search;
ConstraintLayout searchbar;
EditText textfield;
// For scheduling background image change(using constraint layout, start counting from dubai, down to statue of liberty.
ConstraintLayout constraintLayout;
public static int count = 0;
int[] drawable = new int[]{R.drawable.nyc, R.drawable.lofoten_islands, R.drawable.parque, R.drawable.moraine_lake, R.drawable.eiffel_tower,
R.drawable.whitehaven_beach, R.drawable.london, R.drawable.cape_town, R.drawable.burj_al_arab, R.drawable.atuh_beach};
Timer _t;
private WeatherDataViewModel viewModel;
private AppBarConfiguration appBarConfiguration;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
// use home activity layout.
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Allow activity to make use of the toolbar
drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
// host 3 fragments along with bottom navigation.
final NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
assert navHostFragment != null;
final NavController navController = navHostFragment.getNavController();
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
// remove up button from all these fragments
appBarConfiguration = new AppBarConfiguration.Builder(
R.id.main_id) // remove up button from all these fragments >> Keep up button in R.id.nav_setting, R.id.nav_slideshow
.setOpenableLayout(drawer)
.build();
// Hiding default Drawer fragment that has the BottomNavView
navigationView.getMenu().findItem(R.id.main_id).setVisible(false);
viewModel = new ViewModelProvider(this).get(WeatherDataViewModel.class);
// Trigger action to open & close navigation drawer
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar
, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
timeField = findViewById(R.id.textView9);
Search = findViewById(R.id.imageView4);
textfield = findViewById(R.id.textfield);
searchbar = findViewById(R.id.searchbar);
// find the id's of specific variables.
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
toggle.setToolbarNavigationClickListener(v -> {
// Enable the functionality of opening the side drawer, when the burger icon is clicked
toggle.setDrawerIndicatorEnabled(true);
navController.navigate(R.id.main_id);
});
navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
// Hide/show top search bar
if (destination.getId() == R.id.main_id) {
searchbar.setVisibility(View.VISIBLE);
toggle.setHomeAsUpIndicator(R.drawable.nav_back_arrow);
toggle.setDrawerIndicatorEnabled(true); // <<< Add this line of code to enable the burger icon
} else {
searchbar.setVisibility(View.GONE);
}
// Fragments that you want to show the back button
if (destination.getId() == R.id.about_id || destination.getId() == R.id.privacy_policy_id) {
// Disable the functionality of opening the side drawer, when the burger icon is clicked
toggle.setDrawerIndicatorEnabled(false);
}
});
// For scheduling background image change
constraintLayout = findViewById(R.id.layout);
constraintLayout.setBackgroundResource(R.drawable.nyc);
_t = new Timer();
_t.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
// run on ui thread
runOnUiThread(() -> {
if (count < drawable.length) {
constraintLayout.setBackgroundResource(drawable[count]);
count = (count + 1) % drawable.length;
}
});
}
}, 5000, 5000);
Search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// make click sound when search button is clicked.
player = MediaPlayer.create(HomeActivity.this, R.raw.click);
player.start();
getWeatherData(textfield.getText().toString().trim());
// make use of some fragment's data
Fragment currentFragment = navHostFragment.getChildFragmentManager().getFragments().get(0);
if (currentFragment instanceof MainFragment) {
((MainFragment) currentFragment).getWeatherData(textfield.getText().toString().trim());
}
}
private void getWeatherData(String name) {
ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
Call<Example> call = apiInterface.getWeatherData(name);
call.enqueue(new Callback<Example>() {
@Override
public void onResponse(@NonNull Call<Example> call, @NonNull Response<Example> response) {
try {
assert response.body() != null;
} catch (Exception e) {
Log.e("TAG", "No City found");
Toast.makeText(HomeActivity.this, "No City found", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(@NotNull Call<Example> call, @NotNull Throwable t) {
t.printStackTrace();
}
});
}
});
}
@Override
public void onBackPressed() {
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
// Open/close drawer animation
}
}
@Override
protected void onPause() {
super.onPause();
if (viewModel.getMediaPlayer() != null)
viewModel.getMediaPlayer().pause();
}
@Override
protected void onResume() {
super.onResume();
if (viewModel.getMediaPlayer() != null) {
viewModel.getMediaPlayer().start();
viewModel.getMediaPlayer().setLooping(true);
}
}
@Override
public boolean onSupportNavigateUp() {
final NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
assert navHostFragment != null;
final NavController navController = navHostFragment.getNavController();
// return NavigationUI.navigateUp(navController,drawer);
return NavigationUI.navigateUp(navController, appBarConfiguration)
|| super.onSupportNavigateUp(); // navigateUp tries to pop the backstack
}
}
MainFragment(The Navhost fragment):
public class MainFragment extends Fragment {
private NavHostFragment navHostFragment;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
//
BottomNavigationView bottomNavigationView = rootView.findViewById(R.id.bottomNavigationView);
navHostFragment = (NavHostFragment) getChildFragmentManager().findFragmentById(R.id.nav_host_fragment_content_bottom_nav_view);
if (navHostFragment != null) {
NavController navController = navHostFragment.getNavController();
NavigationUI.setupWithNavController(bottomNavigationView, navController);
}
requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
// Exit the app when back is pressed
requireActivity().finish();
}
});
return rootView;
}
public void getWeatherData(String name) {
Fragment currentFragment = navHostFragment.getChildFragmentManager().getFragments().get(0);
if (currentFragment instanceof FirstFragment) {
FirstFragment firstFragment = (FirstFragment) currentFragment;
firstFragment.getWeatherData(name);
} else if (currentFragment instanceof SecondFragment) {
SecondFragment secondFragment = (SecondFragment) currentFragment;
secondFragment.getWeatherData(name);
} else if (currentFragment instanceof ThirdFragment) {
ThirdFragment thirdFragment = (ThirdFragment) currentFragment;
thirdFragment.getWeatherData(name);
}
}
}
Others include:
*FirstFragment
*SecondFragment
*ThirdFragment with their respective layouts
*Navigation and menu layouts.
I will not post them, for now, to reduce complexity if needed please don't hesitate to ask.
So, the current navigation in summary would be:
HomeActivity
MainFragment
BottomNavigationView navGraph
FirstFragment
SecondFragment
ThirdFragment
Other fragments...
And you need to:
BottomNavigationView
FirstFragment
and Get rid of SecondFragment
& ThirdFragment
As the MainFragment
only hosts the BottomNavigationView
; then you can replace it directly with the FirstFragment
; so the navigation would be:
HomeActivity
FirstFragment
Other fragments...
And to do that:
1. In the main navGraph of the HomeActivity:
MainFragment
with FirstFragment
(copy the FirstFragment
section from the BottomNavigationView
navGraph to the main navGraph.FirstFragment
to the one associated with the MainFragment
, because this id is utilized in HomeActivity
(or you can do the other way by refactoring it to the FirstFragment
)2. In HomeActivity
, Replace the MainFragment
in below snippet with the FirstFragment:
if (currentFragment instanceof MainFragment) {
((MainFragment) currentFragment).getWeatherData(textfield.getText().toString().trim());
}
So, it'll be:
if (currentFragment instanceof FirstFragment) {
((FirstFragment) currentFragment).getWeatherData(textfield.getText().toString().trim());
}
This is what appears in the shared code; but you'd replace every single occurrence of MainFragment
with FirstFragment
, and do any needed refactoring.
Now, you can safely remove the MainFragment
will all of its descendants, BottomNavigationView
, second & third fragments; and their resources (layouts, menus...), or keep them aside if you're planning to reuse them in the future.