There's a NavigationView that opens a fragment, in that fragment there's a BottomNavigationView. The bottom navigation view, should switch between two fragments.
Note: When the app starts, it opens the first blank fragment (called Home), so when I click on the second menu item it opens another fragment (that contains the bottom navigation).
I tried to switch from one fragment to the other using FragmentTransaction in this way:
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.popBackStack();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
final Fragment fragment;
if (item.getItemId() == R.id.menu_alert) {
fragment = new IPAlertFragment();
} else {
fragment = new IPStatsFragment();
}
fragmentTransaction.replace(R.id.nav_host_fragment, fragment).commit();
return false;
}
};
BottomNavigationView navigation = (BottomNavigationView) getActivity().findViewById(R.id.bottom_navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
It works fine when I open the fragment from the navigation menu for the first time, but when I click a second time on the navigation menu, the BottomNavigationView.onNavigationItemSelectedListener doesn't fire anymore and I can't switch from a fragment to the other.
So, I've tried to accomplish my goal using NavController, like the following:
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
final NavController navController = NavHostFragment.findNavController(NavFragment.this);
if (item.getItemId() == R.id.menu_alert) {
navController.navigate(R.id.action_openAlert);
} else {
navController.navigate(R.id.action_openStats);
}
return false;
}
};
BottomNavigationView navigation = (BottomNavigationView) getActivity().findViewById(R.id.bottom_navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
But when I navigate to the other fragment the left menu bar change the icon to "back arrow", it's a kind of new activity, and I have to use the back button (or the menu back icon) in order to show the previous tab.
I would like to navigate to a destination fragment overriding the current "screen", as like as the side menu does.
Here is the mobile_navigation.xml:
<fragment
android:id="#+id/nav_ip_alert"
android:name="IPAlertFragment"
android:label="#string/menu_ip"
tools:layout="#layout/fragment_i_p_alert">
<action
android:id="#+id/action_openStats"
app:destination="#id/nav_ip_stats"
app:launchSingleTop="false" />
</fragment>
<fragment
android:id="#+id/nav_ip_stats"
android:name="IPStatsFragment"
android:label="#string/menu_ip"
tools:layout="#layout/stats_tabs">
<action
android:id="#+id/action_openAlert"
app:destination="#id/nav_ip_alert"
app:launchSingleTop="false" />
</fragment>
I don't know what's wrong (espacially with the first solution) any idea?
Thanks.
Finally I solved my problem:
It works fine when I open the fragment from the navigation menu for the first time, but when I click a second time on the navigation menu, the BottomNavigationView.onNavigationItemSelectedListener doesn't fire anymore and I can't switch from a fragment to the other.
The problem was caused by the navigation menu, the listener wasn't called because I used in my activity:
NavigationUI.setupWithNavController(navigationView, navController);
That overrides my OnNavigationItemSelectedListener, so I removed that line and I've setted my listener as the following:
final NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(new
NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
FragmentManager fm = getSupportFragmentManager();
fm.popBackStackImmediate();
boolean handled = NavigationUI.onNavDestinationSelected(item, navController);
if (handled) {
ViewParent parent = navigationView.getParent();
if (parent instanceof DrawerLayout) {
((DrawerLayout) parent).closeDrawer(navigationView);
}
}
return handled;
}
});
Here's a piece of NavigationUI that override my listener:
public static void setupWithNavController(#NonNull final NavigationView navigationView,
#NonNull final NavController navController) {
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
boolean handled = onNavDestinationSelected(item, navController);
//******* CUTTED ***************
return handled;
}
});
}
So, replacing the setupWithNavController, I can navigate through the tabs correctly.
Related
I started a new app with the default android bottom navigation menu.
In the basic main fragment I added the buttons for all the fragments (I want to show them in the bottom navigation but also in the main fragment.)
Then I added this in HomeFragment to handle on button press to switch fragments:
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
homeViewModel = ViewModelProviders.of(this).get(HomeViewModel.class);
View root = inflater.inflate(R.layout.fragment_home, container, false);
final TextView textView = root.findViewById(R.id.text_home);
homeViewModel.getText().observe(this, new Observer<String>() {
#Override
public void onChanged(#Nullable String s) {
textView.setText(s);
}
});
Button btnConnect = (Button) root.findViewById(R.id.btnConnect);
btnConnect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment fragment = new ConnectFragment();
replaceFragment(fragment);
}
});
Button btnOptions = (Button) root.findViewById(R.id.btnOptions);
btnOptions.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment fragment = new OptionsFragment();
replaceFragment(fragment);
}
});
return root;
}
private void replaceFragment(Fragment someFragment) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.nav_host_fragment, someFragment);
transaction.addToBackStack(null);
transaction.commit();
}
Now I am able to switch between the fragments, but the navigation controller isn't being updated, and when I switch from those buttons to another fragment, in the navigation controller at the bottom, the icons are not updated, and t looks like I am still on the home fragment.
this is the code inside MainActivity for the navigation controller:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView navView = findViewById(R.id.nav_view);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_home, R.id.navigation_options, R.id.navigation_contact)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController);
}
So what do I need to do, in order to make the navigation controller update the icons wen I switch fragments from the customized buttons and not from the navigation controller menu?
EDIT:
here is an image to clarify:
on the left is the main activity, on the middle is how it looks like when I switch fragment by pressing on the button "CONNECT" from the main activity, and on the right is how it looks like if I press the "connect" button from the menu.
I want that the menu will be updated, even when I press the "CONNECT" button from the main activity, and not only from the menu.
You can use something like this
yourBottomNavigationView.setSelectedItemId(R.id.navigation_contact);
When you click on your Button
I am using Bottom Navigation Activity from Android Studio
After setting all the needed bottom tabs, I need to add aditional button for one fragment, but outside the tab zone. And that button is only when the second fragment is called.
Something like in image below
I've set new fragment in navigation/mobile_navigation.xml
<fragment
android:id="#+id/navigation_demografski"
android:name="com.home.Fragment1"
android:label="Podaci o osobama"
tools:layout="#layout/fragment_home" />
<fragment
android:id="#+id/navigation_biometrijski"
android:name="com.home.Fragment2"
android:label="Biometrijski podaci - Desna Ruka"
tools:layout="#layout/fragment_dashboard" />
<fragment
android:id="#+id/navigation_biometrijski2"
android:name="com.home.Fragment3"
android:label="Biometrijski podaci - Lijeva Ruka"
tools:layout="#layout/fragment_dashboard2" />
But I don't know how to call the third fragment from the second fragment.
I tried to use fragmet.replace() but it just overlaps one fragment over the other.
Tabbed activity
public class TabbedActivity extends AppCompatActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tabbed);
BottomNavigationView navView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
R.id.navigation_demografski, R.id.navigation_biometrijski).build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController);
}
}
Use FrameLayout as fragment container, then switch fragments inside it. You could do that by setting OnNavigationItemSelectedListener to BottomNavigationView and using
getSupportFragmentManager().beginTransaction().replace(R.id.frameLayout, selectedFragment).commit();
to switch between the fragments. On mentioned button in second fragment add onClickListener and call previous transaction from Activity with desired fragment as selectedFragment
you can implement by following my code below:
public class MainActivity extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//loading the default fragment
loadFragment(new HomeFragment());
//getting bottom navigation view and attaching the listener
BottomNavigationView navigation = findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(this);
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment fragment = null;
switch (item.getItemId()) {
case R.id.navigation_home:
fragment = new HomeFragment();
break;
case R.id.navigation_dashboard:
fragment = new DashboardFragment();
break;
case R.id.navigation_notifications:
fragment = new NotificationsFragment();
break;
case R.id.navigation_profile:
fragment = new ProfileFragment();
break;
}
return loadFragment(fragment);
}
private boolean loadFragment(Fragment fragment) {
//switching fragment
if (fragment != null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, fragment)
.commit();
return true;
}
return false;
}
}
I am novice developer and I'm integrating default (ready-made) Navigation drawer in my app with androidx. I'm having problem with navigating fragments as it doesn't work when I click on the drawer menu items. There are two fragments which are linked with their id's and set onClick listener, but it doesn't work. It just shows the main fragment but doesn't navigate to other fragments.
I'm not familiar with default functions like onCreateOptionsMenu(Menu menu) and onSupportNavigateUp() which are created by itself when I created the default drawer activity, so I just comment these functions and by following a tutorial I implement the NavigationView.OnNavigationItemSelectedListener which gives me onNavigationItemSelected(#NonNull MenuItem item) function where I wrote the code for navigate fragments. But it doesn't worked and when I debug, it shows that the onNavigationItemSelected(#NonNull MenuItem item) is not called.
public class FindBarber extends AppCompatActivity implements.
NavigationView.OnNavigationItemSelectedListener {
private AppBarConfiguration mAppBarConfiguration;
ActionBarDrawerToggle toggle;
Toolbar toolbar;
DrawerLayout drawer;
NavigationView navigationView;
int OPEN, CLOSE;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_find_barber);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
drawer = findViewById(R.id.drawer_layout);
navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
toggle = new ActionBarDrawerToggle(this, drawer, toolbar, OPEN, CLOSE);
drawer.addDrawerListener(toggle);
toggle.syncState();
// 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_profile, R.id.nav_kutit_wallet,
R.id.nav_terms_of_use, R.id.nav_rate_the_app, R.id.nav_contact_us)
.setDrawerLayout(drawer)
.build();*/
/* NavController navController = Navigation.findNavController(this, R.id.content_frame);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);*/
FragmentManager fmanager = getSupportFragmentManager();
fmanager.beginTransaction().replace(R.id.content_frame, new GMap()).commit();
}
/*#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.find_barber, menu);
return true;
}
*/
// #Override
/* public boolean onSupportNavigateUp() {
*//*NavController navController = Navigation.findNavController(this, R.id.content_frame);*//*
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}*/
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId())
{
case R.id.nav_home:
getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, new GMap()).commit();
break;
case R.id.nav_profile:
getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, new Profile()).commit();
break;
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
There is no error message nor any app crash occurs. When I click navigation drawer item for navigating any fragment, it doesn't show anything except the main default fragment which I show in screen.
Call loadFragment(new Fragment(),"My Fragment") onNavigationItemSelected
public void loadFragment(Fragment fragment, String title_name){
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.customer_container,fragment,title_name);
fragmentTransaction.addToBackStack(fragment.getClass().getSimpleName());
fragmentTransaction.commit();
}
Please try this below line :
navigationView.getMenu().performIdentifierAction(R.id.posts, 0);
I am developing an app where i am using only 1 Main Activity and Multiple fragment, Including ViewPager , Custom video/Image Gallery, Fullscreen Fragment(Without toolbar or bottom navigation button). I am not sure is it good practice or not but i am facing few issues cause of this.
Image above is actual App hierarchy. Following the issue i am facing.
Toolbar doesn't change title of fragment, when press back button or going forward by clicking button or some link.
Navigation hamburger keep showing if i change into back arrow by using: getSupportActionBar().setDisplayHomeAsUpEnabled(true); then back arrow opens drawers but not going back to last fragment.
Fragment State Loss when pressed back button or jumping directly to some fragment.
Whether is it good practice to doing all task within Fragment with Single Activity.
I am also using single Toolbar whole app.
Toolbar.xml
<android.support.v7.widget.Toolbar
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/primary"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
app:contentInsetStartWithNavigation="0dp"
android:fitsSystemWindows="true"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/toolbar_connections"
android:visibility="visible"
android:orientation="horizontal">
<ImageView
android:layout_width="35dp"
android:layout_height="match_parent"
android:id="#+id/appLogo"
android:layout_gravity="center_vertical" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:textSize="22sp"
android:id="#+id/activityTitle"
android:textColor="#color/primary_text"
/>
</LinearLayout>
<LinearLayout
android:id="#+id/toolbar_chat"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone"
android:orientation="horizontal">
<de.hdodenhof.circleimageview.CircleImageView
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center_vertical"
android:layout_marginRight="5dp"
android:src="#drawable/baby"
android:id="#+id/User_Image_Toolbar"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="#+id/User_Name_Toolbar"
android:textSize="17sp"
android:textStyle="bold"
android:layout_marginBottom="5dp"
android:text="My Name"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Online"
android:textStyle="italic"
android:id="#+id/User_Online_Status_Toolbar"
android:layout_marginBottom="5dp"
android:layout_below="#+id/User_Name_Toolbar" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.Toolbar>
Navigation Drawer (Single Activity which parent of all Fragments)
public class Navigation_Drawer extends AppCompatActivity implements UserData {
Toolbar toolbar;
DrawerLayout drawerLayout;
NavigationView navigationView;
String navTitles[];
TypedArray navIcons;
RecyclerView.Adapter recyclerViewAdapter;
ActionBarDrawerToggle drawerToggle;
public static final String TAG = "###Navigation Drawer###";
boolean nextScreen;
//Header
ImageView headerImage,headerUserImage;
TextView userName,userViews;
Context context = this;
//Setting Tabs
ViewPager viewPager;
TabAdapter tabAdapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.navigation_drawer);
//Initialise Views
drawerLayout = findViewById(R.id.Navigation_Drawer_Main);
navigationView = findViewById(R.id.nvView);
setupToolbar();
navigationView.setItemIconTintList(null);
setupDrawerContent(navigationView);
settingHeaderItems();
drawerToggle = setupDrawerToggle();
getSupportActionBar().setHomeButtonEnabled(true);
drawerLayout.addDrawerListener(drawerToggle);
viewPager = findViewById(R.id.Navigation_Drawer_ViewPager);
tabAdapter = new TabAdapter(getFragmentManager(), this, false);
viewPager.setAdapter(tabAdapter);
}
public void setupToolbar() {
toolbar = findViewById(R.id.Navigation_Drawer_toolbar);
setSupportActionBar(toolbar);
}
private ActionBarDrawerToggle setupDrawerToggle() {
// NOTE: Make sure you pass in a valid toolbar reference. ActionBarDrawToggle() does not require it
// and will not render the hamburger icon without it.
//return new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close);
return new ActionBarDrawerToggle(this, drawerLayout,toolbar, R.string.drawer_open, R.string.drawer_close);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
// inflater.inflate(R.menu.main_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
//Handle Item Selection
return super.onOptionsItemSelected(item);
}
private void setupDrawerContent(NavigationView navigationView) {
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
selectDrawerItem(menuItem);
return true;
}
});
}
public void ChangeFragment_ViewPager(int position, boolean outside) {
if (outside) {
Log.d(TAG, "Change Fragment Calling From Outside");
tabAdapter = new TabAdapter(getFragmentManager(), this, false);
viewPager.setAdapter(tabAdapter);
}
viewPager.setCurrentItem(position);
}
#Override
public void onBackPressed() {
super.onBackPressed();
showSystemUI();
Log.d(TAG, "On Back Pressed");
}
public void showSystemUI() {
if (getWindow() != null) {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getSupportActionBar().show();
} else {
return;
}
}
public void selectDrawerItem(MenuItem menuItem) {
// Create a new fragment and specify the fragment to show based on nav item clicked
Fragment fragment = null;
switch (menuItem.getItemId()) {
case R.id.HeaderImageView:
fragment = new EditProfile();
break;
case R.id.home_Fragment:
Log.d(TAG,"Home Fragment Pressed ");
getFragmentManager().popBackStack(null, android.app.FragmentManager.POP_BACK_STACK_INCLUSIVE);
ChangeFragment_ViewPager(0,false);
// Highlight the selected item has been done by NavigationView
menuItem.setChecked(true);
// Set action bar title
setTitle(menuItem.getTitle());
// Close the navigation drawer
drawerLayout.closeDrawers();
return;
case R.id.ppl_Fragment:
Log.d(TAG,"PPL Fragment Pressed ");
ChangeFragment_ViewPager(1,false);
// Highlight the selected item has been done by NavigationView
menuItem.setChecked(true);
// Set action bar title
setTitle(menuItem.getTitle());
// Close the navigation drawer
drawerLayout.closeDrawers();
return;
case R.id.message_Fragment:
Log.d(TAG,"Message Fragment Pressed ");
fragment = new Messages_Fragment();
break;
case R.id.addMedia_Fragment:
Log.d(TAG,"Add Media Fragment Pressed ");
fragment = new UserProfile_Photos();
break;
case R.id.invite_Fragment:
Log.d(TAG,"Invite Fragment Pressed ");
//fragmentClass = fragment_1.class;
onInviteClicked();
// Highlight the selected item has been done by NavigationView
menuItem.setChecked(true);
// Set action bar title
setTitle(menuItem.getTitle());
// Close the navigation drawer
drawerLayout.closeDrawers();
return;
case R.id.setting_Fragment:
Log.d(TAG,"Setting Fragment Pressed ");
fragment = new Setting_NavigationDrawer();
break;
case R.id.help_Fragment:
Log.d(TAG,"Help Fragment Pressed ");
//fragmentClass = fragment_1.class;
fragment=new FullScreen_WebView();
Bundle urlToSend=new Bundle();
urlToSend.putString("webViewURL","http://boysjoys.com/test/Android/Data/help.php");
//urlToSend.putString("webViewURL",chat_wrapper.getGoogleSearch().get(2));
fragment.setArguments(urlToSend);
FragmentTransaction transaction=((Activity)context).getFragmentManager().beginTransaction();
//fragmentTrasaction.replace(R.id.Chat_Screen_Main_Layout,gallery);
//transaction.replace(R.id.Chat_Screen_Main_Layout,fullScreen_webView);
transaction.replace(R.id.Navigation_Main_Layout,fragment);
transaction.addToBackStack(null);
transaction.commit();
// Highlight the selected item has been done by NavigationView
menuItem.setChecked(true);
// Set action bar title
setTitle(menuItem.getTitle());
// Close the navigation drawer
drawerLayout.closeDrawers();
return;
case R.id.signOut_Fragment:
new CheckLoginStatus(this, 0).execute();
new Send_Session_Logout(this).execute();
drawerLayout.closeDrawers();
return;
}
FragmentTransaction fragmentTransaction=getFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.Navigation_Main_Layout, fragment);
fragmentTransaction.setCustomAnimations(R.animator.enter_anim,R.animator.exit_anim);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
// Highlight the selected item has been done by NavigationView
menuItem.setChecked(true);
// Set action bar title
setTitle(menuItem.getTitle());
// Close the navigation drawer
drawerLayout.closeDrawers();
}
private void settingHeaderItems(){
View HeaderLayout = navigationView.inflateHeaderView(R.layout.navigation_header_image);
//Main Screen Tabs With VIew Pager
headerImage = HeaderLayout.findViewById(R.id.HeaderImageView);
headerImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentTransaction fragmentTransaction=getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.Navigation_Main_Layout, new EditProfile());
fragmentTransaction.setCustomAnimations(R.animator.enter_anim,R.animator.exit_anim);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
drawerLayout.closeDrawers();
}
});
headerUserImage = HeaderLayout.findViewById(R.id.HeaderProfilePicture);
userName = HeaderLayout.findViewById(R.id.myImageViewText);
userViews = HeaderLayout.findViewById(R.id.profileViews);
if (Session.getUserCover().equals("Invalid Image")){
headerImage.setBackgroundResource(R.drawable.cam_icon);
}else {
Log.d(TAG,"Path Of Cover Photo "+Session.getUserCover());
Bitmap coverPhoto= BitmapFactory.decodeFile(Session.getUserCover());
headerImage.setImageBitmap(coverPhoto);
// Glide.with(context).load(Session.getUserCover()).apply(new RequestOptions().skipMemoryCache(true).onlyRetrieveFromCache(false).diskCacheStrategy(DiskCacheStrategy.NONE)).into(holder.HeaderImage);
}
Bitmap bitmap = BitmapFactory.decodeFile(Session.getUserImage());
userName.setText(Session.getUserFname()+" "+Session.getUserLname());
headerUserImage.setImageBitmap(bitmap);
if (Session.getProfileCounter().equals("0")){
userViews.setText("No Profile VIsits");
}
else {
userViews.setText("Profile views: "+ Session.getProfileCounter());
}
}
#Override
protected void onPostCreate(#Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
drawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
drawerToggle.onConfigurationChanged(newConfig);
}
}
I tired alot to resolve this issue and after months of googling and stackoverflow i m still stuck in same issue.
Issue example of Point 1:- When navigation drawer load first everything looks good, view pager changes title as per fragment. then if i click on Navigation Drawer's Menu which also open another fragment (For Ex: Recent Message). then title change successfully but when i press back button or trying to press home button which calls viewpager then title remain same as before i.e. Recent Message.
Setting Title in each fragment like this.
toolbar = (Toolbar) getActivity().findViewById(R.id.Navigation_Drawer_toolbar);
ImageView appLogo = toolbar.findViewById(R.id.appLogo);
TextView fragmentTitle = toolbar.findViewById(R.id.activityTitle);
appLogo.setImageResource(DrawableImage);
fragmentTitle.setText(Title);
If application have to use Navigation Drawer which should be present in all views, then Fragment should be used. And its not a bad practice.
Toolbar doesn't change title of fragment, when press back button or
going forward by clicking button or some link.
Create a method in Base Activity
public void setFragmentTitle(String title){
if(!TextUtils.isEmpty(title))
mTitleText.setText(title);
}
Access this method from your individual Fragments in onCreateView
((LandingActivity) getActivity()).setFragmentTitle(getActivity().getString(R.string.fragment_title));
Navigation hamburger keep showing if i change into back arrow by using: getSupportActionBar().setDisplayHomeAsUpEnabled(true); then back arrow opens drawers but not going back to last fragment.
Use onOptionItemSelected on click of android.R.id.home , pop the current Fragment
Fragment State Loss when pressed back button or jumping directly to some fragment
You have to mention the values which needs to be persisted and repopulate it.
public class ActivityABC....{
private String mFName;
private TableSelectFragment mFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FragmentManager fm = getSupportFragmentManager();
if (savedInstanceState != null) {
mFragment=(TableSelectFragment)fm.getFragment(savedInstanceState,"TABLE_FRAGMENT");
mFName = savedInstanceState.getString("FNAMETAG");
}else{
mFragment = new TableSelectFragment();
fm.beginTransaction().add(R.id.content_frame,mFragment,"TABLE_FRAGMENT").commit();
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getSupportFragmentManager().putFragment(outState,"TABLE_FRAGMENT",mFragment);
}
}
In your Fragment
TableSelectFragment{
....
private String mFName;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
outState.putString("FNAMETAG", mFName);
super.onSaveInstanceState(outState);
}
}
EDIT 1: For Fragment Title not getting updated in BackButton press
While adding Fragment to backstack , do the following.
In your parent Activity
FragmentManager fragMan = getSupportFragmentManager();
FragmentTransaction fragTrans = fragMan.beginTransaction();
LandingFrag landingFrag = LandingFrag.newInstance();
fragTrans.replace(R.id.landing_view, landingFrag,"LandingFrag");
fragTrans.addToBackStack(null);
fragTrans.commit();
landingFrag.setUserVisibleHint(true);
Now override onBackPressed in parent Activity
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
.. POP Fragment Backstack here
Fragment fragment = getActiveFragment();
if(fragment instanceof LandingFrag)
{
LandingFrag landingFrag = (LandingFrag)fragment;
landingFrag.setUserVisibleHint(true);
}
}
public Fragment getActiveFragment() {
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
return null;
}
Fragment fragment=null;
int trackBackValue = 1;//INCREASE OR DECREASE ACCORDING TO YOUR BACK STACK
try {
fragment = getSupportFragmentManager().getFragments().get(getSupportFragmentManager().getBackStackEntryCount() - trackBackValue);
} catch (Exception e) {
}
return fragment;
}
Now in LandingFrag
public class LandingFrag...
{
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setUserVisibleHint(false);
.....
}
#Override
public void onViewStateRestored(#Nullable Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
................
((LandingActivity) getActivity()).setFragmentTitle("Current Fragment Title");
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser){
try {
((LandingActivity) getActivity()).setFragmentTitle("Current Fragment Title");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Whether is it good practice to doing all task within Fragment with
Single Activity.
It is a good practice to use fragments when you use with navigation drawers, tabs or bottom navigation.
Other than that, fragments are mostly preferred for reusable UI with different data.
You are doing all task within fragment with Single Activity because you are using navigation draw and tabs, so It is a good practice, I'd say.
Toolbar doesn't change title of fragment, when press back button or
going forward by clicking button or some link.
You need to manually set the title for fragment whenever you are adding/replacing new fragment OR
on back press(backstack change), through Fragment only or using OnBackStackChangedListener as mentioned in docs.
You are just setting them while you are clicking through navigation items and not while clicking button or some link
Navigation hamburger keep showing if i change into back arrow by
using: getSupportActionBar().setDisplayHomeAsUpEnabled(true); then
back arrow opens drawers but not going back to last fragment.
That too you'd need to handle manually. using onOptionItemSelected on click of android.R.id.home item.
Like poping fragments out from stack.
The cause of your title persistence on back is setting title from Activity.
ie using this setTitle(menuItem.getTitle()); instead set them through Fragment or if you are setting them trough Fragment remove from selectDrawerItem method.
Also at the end of selectDrawerItem method you are using fragmentTransaction.add instead use fragmentTransaction.replace
I have created MainActivity with NavigationView. When Activity is opened I want to automatically select the first item in the navigation drawer and open Fragment under that item. I've searched a lot but didn't find any proper solutions.
What is the proper way to do this ?
Main Activity:
public class MainActivity extends AppCompatActivity implements Config {
private NavigationView navigationView;
private DrawerLayout drawerLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setTitleTextColor(getResources().getColor(R.color.colorIcons));
if (null != getSupportActionBar())
getSupportActionBar().setLogo(R.drawable.ic_blogger_white);
//Start PostListFragmentWebView
/*PostListFragmentWebView postListFragmentWebView = new PostListFragmentWebView();
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame, postListFragmentWebView)
.commit();*/
//Initializing NavigationView
navigationView = (NavigationView) findViewById(R.id.navigationView);
//Setting Navigation View Item Selected Listener to handle the item click of the navigation menu
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
//Checking if the item is in checked state or not, if not set it to checked state.
if (menuItem.isChecked()) menuItem.setChecked(false);
else menuItem.setChecked(true);
//Closing drawer on item click
drawerLayout.closeDrawers();
//Check to see which item was clicked and perform the appropriate action.
switch (menuItem.getItemId()) {
case R.id.posts:
PostListFragmentWebView postListFragment = new PostListFragmentWebView();
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame, postListFragment)
.commit();
return true;
case R.id.pages:
PageListFragmentWebView pagetListFragment = new PageListFragmentWebView();
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame, pagetListFragment)
.commit();
return true;
case R.id.blog:
BlogInfoFragmentWebView blogInfoFragment = new BlogInfoFragmentWebView();
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame, blogInfoFragment)
.commit();
return true;
default:
Toast.makeText(getApplicationContext(), getResources().getString(R.string.drawer_error), Toast.LENGTH_SHORT).show();
return true;
}
}
});
// Initializing Drawer Layout and ActionBarToggle
drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.open_drawer, R.string.close_drawer) {
#Override
public void onDrawerClosed(View drawerView) {
// Code here will be triggered once the drawer closes as we don't want anything to happen so we leave this blank.
super.onDrawerClosed(drawerView);
}
#Override
public void onDrawerOpened(View drawerView) {
// Code here will be triggered once the drawer open as we dont want anything to happen so we leave this blank.
super.onDrawerOpened(drawerView);
}
};
//Setting the actionbarToggle to drawer layout
drawerLayout.setDrawerListener(actionBarDrawerToggle);
drawerLayout.getChildAt(0).setSelected(true);
//calling sync state is necessary or else your hamburger icon wont show up
actionBarDrawerToggle.syncState();
}
}
In onCreate(), following code will load the first item's fragment upon first start:
if (savedInstanceState == null) {
navigationView.getMenu().performIdentifierAction(R.id.posts, 0);
}
Thanks to calvinfly for this comment.
Add android:checked="true" to your first menu item.
And manually select one item, using
getSupportFragmentManager().beginTransaction().replace(R.id.frame, postListFragment).commit();
to open fragment.
Instead of normal listener ...
navView.setNavigationItemSelected(new Navigation.View.OnNavigationItemSelectedListener() {bla, bla, bla})
Create the listener as an Obj:
NavigationView.OnNavigationItemSelectedListener navViewListener;
navView.setNavigationItemSelectedListener(navViewListener = new NavigationView.OnNavigationItemSelectedListener() {bla, bla, bla})
...and use the Obj to trigger the listener event:
navViewListener.onNavigationItemSelected(navView.getMenu().getItem(0));
...where getItem(0) is the first menu item.
Use a method getItem(0).setChecked(true) or android:checked="true" at its menu item XML definition.
You could also use navigationView.setCheckedItem(R.id.default)(javadoc) after you setup your navigationview.
just add this code in onCreate method:
FragmentTransaction ftrans = getFragmentManager().beginTransaction();
ftrans.replace(R.id.container, <yourfragment>).commit();
Work for me !
This can be done even better while considering orientation and other configuration changes. We could select whatever nav drawer menuitem depending on whether we are coming from a previous state. Check: For the Navigation drawer wielding Activity:-
public static final String SELECTED_NAV_MENU_KEY = "selected_nav_menu_key";
// The selected grid position
private int mSelectedNavMenuIndex = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
...........................................................
navigationView.setNavigationItemSelectedListener(this);
if (savedInstanceState != null) {
// Recover assets
mSelectedNavMenuIndex = savedInstanceState.getInt(SELECTED_NAV_MENU_KEY);
// Recover menu as selected
MenuItem menuItem = navigationView.getMenu().getItem(mSelectedNavMenuIndex);
toggleNavMenuItemCheck(menuItem);
navigationView.getMenu().performIdentifierAction(menuItem.getItemId(), mSelectedNavMenuIndex);
return;
} else {
MenuItem menuItem = navigationView.getMenu().getItem(mSelectedNavMenuIndex);
toggleNavMenuItemCheck(menuItem);
navigationView.getMenu().performIdentifierAction(menuItem.getItemId(), mSelectedNavMenuIndex);
}
}
The toggle method that helps uncheck or check the menu item
private void toggleNavMenuItemCheck(MenuItem menuItem) {
if (menuItem.isChecked()){
menuItem.setChecked(false);
} else {
menuItem.setChecked(true);
}
}
This is how I save the state of the selected menu item. Check:-
#Override
public boolean onNavigationItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.nav_explore:
showExploreFragment(null);
mSelectedNavMenuIndex = 0;
break;
case R.id.nav_orders:
mSelectedNavMenuIndex = 1;
break;
case R.id.nav_settings:
mSelectedNavMenuIndex = 2;
break;
default:
showExploreFragment(null);
mSelectedNavMenuIndex = 0;
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
// Save any important data for recovery
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(SELECTED_NAV_MENU_KEY, mSelectedNavMenuIndex);
}
NB: The line with code:
navigationView.getMenu().performIdentifierAction(menuItem.getItemId(), mSelectedNavMenuIndex);
Can be replaced by the code:
onNavigationItemSelected(menuItem);
in menu.xml remember to mention android:checkable="true" for single item and android:checkableBehavior="single" for a group of items.
<item
android:id="#+id/pos_item_help"
android:checkable="true"
android:title="Help" />
<group
android:id="#+id/group"
android:checkableBehavior="single">
<item
android:id="#+id/menu_nav_home"
android:icon="#drawable/ic_home_black_24dp"
android:title="#string/menu_nav_home" />
</group>
then inside NavigationItemSelectedListener use setCheckedItem(R.id.item_id_in_menu) to make it selected.
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.pos_item_pos:
navigationView.setCheckedItem(R.id.pos_item_pos);
break;
case R.id.pos_item_orders:
navigationView.setCheckedItem(R.id.pos_item_orders);
break;
default:
}
return true;
}
And you do not have to do the dirty task of managing the selected item anymore. navigationView manages it by self.
1.) To land to the HomeFragment initially, use this inside your onCreate() in MainActivity:
Fragment fragment = new HomeFragment();
// replacing the fragment
if (fragment != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.commit();
}
2.) To set the item as selected in navigationDrawer set the item as checked in navigation_menu.xml
android:checked = "true"