Issue
I'm currently trying to add a navigation drawer to my weather app, so I watched a youtube tutorial on it and was able to implement it the way I wanted to until I realized that the tutorial I watched didn't cover how I can implement the up/top back button for the nav drawer so as a matter of fact, I currently cannot get back to my default fragment after opening any of the nav tabs. I searched several sites and youtube videos looking for tutorials on how to implement the top back button but haven't seen/been able to find it. I also searched this site and still haven't found anyone with a similar issue here. Please, can anyone be of help?
Here's a screenshot of how my app currently is: https://i.stack.imgur.com/SeSjV.png but if I open any of the navbar options i.e settings and click back, I can't return back to the default fragment where the weather is displayed. It also doesn't have an up-back button as well.
Currently, clicking back only exits the app.
This is the only code I've tried and it didn't work:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
int backStackCount = fragmentManager.getBackStackEntryCount();//check currently how many frags loaded
if (backStackCount > 0) {
fragmentManager.popBackStack(); //go back to previously loaded fragment
}
}
return super.onOptionsItemSelected(item);
}
It gave the following error:
error: cannot find symbol int backStackCount = fragmentManager.getBackStackEntryCount();//check currently how many frags loaded
Here's my activity code:
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.dubai, R.drawable.norway, R.drawable.eiffel_tower, R.drawable.hong_kong, R.drawable.statue_of_liberty,
R.drawable.beijing, R.drawable.chicago, R.drawable.colombia, R.drawable.vienna,R.drawable.tokyo};
Timer _t;
private WeatherDataViewModel viewModel;
@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);
viewModel = new ViewModelProvider(this).get(WeatherDataViewModel.class);
// Trigger action to open & close nevigation 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();
NavigationUI.setupWithNavController(bottomNavigationView, navController);
// Make hourly & daily tab unusable
bottomNavigationView.setOnNavigationItemSelectedListener(item -> {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
}
return false;
});
navController.addOnDestinationChangedListener((controller, destination, arguments) -> navController.popBackStack(destination.getId(), false));
// For scheduling background image change
constraintLayout = findViewById(R.id.layout);
constraintLayout.setBackgroundResource(R.drawable.dubai);
_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.settings_id:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment,
new Settings()).commit();
break;
case R.id.ads_upgrade_id:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment,
new Upgrade()).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
}
}
Solution
if (item.getItemId() == android.R.id.home) {
int backStackCount = fragmentManager.getBackStackEntryCount();//check currently how many frags loaded
if (backStackCount > 0) {
fragmentManager.popBackStack(); //go back to previously loaded fragment
}
}
Currently, clicking back only exits the app.
Using popBackStack()
will pop up the backstack making your app exists, but you just need to return to the default fragment.
To fix this, you need to change the behavior of the drawer burger button, so that it can be used sometimes to open the drawer navView layout, and other times to back to the default fragment; the later is when you want to add the top back button instead.
how I can implement the up/top back button for the nav drawer
This requires to access the setToolbarNavigationClickListener
method which enables you add a listener to burger clicks.
In this case you need to return back to the home fragment as you need, in the onCreate()
method add:
toggle.setToolbarNavigationClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Enable the functionality of opening the side drawer, when the burger icon is clicked
toggle.setDrawerIndicatorEnabled(true); // Show the burger icon & enable the drawer funcionality
navController.navigate(R.id.home); // Back to default fragment (replace home with your default fragment id in the navGraph)
}
});
The remaining part is to show the back button whenever you want to go to certain fragment
And use toggle.setDrawerIndicatorEnabled()
to enable/disable the functionality of opening/closing the drawer when the home/burger icon is clicked
navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
@Override
public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) {
// Repeat this condition for all the Fragments that you want to show the back button
if (destination.getId() == R.id.settings_id) { // replace `settings_id` with your fragment id in the navGraph that you want to show the back button
// Disable the functionality of opening the side drawer, when the burger icon is clicked & show the UP button instead
toggle.setDrawerIndicatorEnabled(false);
}
}
});
Answered By - Zain
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.