I am a newbie to Android development. I am learning UI designing as of now. I want a solution where there is a bottom bar with 5 options linked directly to 5 different activities. I got Java solutions from other stack overflow answers (How to change activity on bottom navigation button click? ) - 2nd Answer by sushil, but it has no activity - XML files in it for me to understand.
Bottom bar like this:
Activity to be loaded based on bottom bar:
As per your attached image, you should used Fragment instead of Activity for 5 different MenuItem or options to achieve your desired output.
1. Create 5 different Fragments for 5 different MenuItem.
For example: MatchingFragment, WatchListFragment, RatesFragment, DealsFragment and ListingFragment.
2. Add OnNavigationItemSelectedListener to your NavigationView and change Fragment as per your selected MenuItem. Use below code to change Fragment:
// Set action to perform when any menu-item is selected.
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
// Change Fragment
selectFragment(item);
return false;
}
});
/**
* Perform action when any item is selected.
*
* #param item Item that is selected.
*/
protected void selectFragment(MenuItem item) {
item.setChecked(true);
switch (item.getItemId()) {
case R.id.action_matching:
// Action to perform when Matching Menu item is selected.
pushFragment(new MatchingFragment());
break;
case R.id.action_watch_list:
// Action to perform when WatchList Menu item is selected.
pushFragment(new WatchListFragment());
break;
case R.id.action_rates:
// Action to perform when Rates Menu item is selected.
pushFragment(new RatesFragment());
break;
case R.id.action_deals:
// Action to perform when Deals Menu item is selected.
pushFragment(new DealsFragment());
break;
case R.id.action_listing:
// Action to perform when Listing Menu item is selected.
pushFragment(new ListingFragment());
break;
}
}
/**
* Method to push any fragment into given id.
*
* #param fragment An instance of Fragment to show into the given id.
*/
protected void pushFragment(Fragment fragment) {
if (fragment == null)
return;
FragmentManager fragmentManager = getFragmentManager();
if (fragmentManager != null) {
FragmentTransaction ft = fragmentManager.beginTransaction();
if (ft != null) {
ft.replace(R.id.rootLayout, fragment);
ft.commit();
}
}
}
Here is the complete Tutorial: Android Bottom Navigation View Tutorial With Example
Hope this will help~
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.action_favorites:
Intent intent1 = new Intent(this, AnActivity.class);
startActivity(intent1);
break;
case R.id.action_schedules:
Intent intent2 = new Intent(this, AnotherActivity.class);
startActivity(intent2);
break;
case R.id.action_music:
Intent intent3 = new Intent(this, AnotherActivity.class);
startActivity(intent3);
break;
}
return true;
}
});
Base Activity :
public abstract class BaseActivity extends AppCompatActivity implements BottomNavigationView.OnNavigationItemSelectedListener {
protected BottomNavigationView navigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getContentViewId());
navigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation);
navigationView.setOnNavigationItemSelectedListener(this);
}
#Override
protected void onStart() {
super.onStart();
updateNavigationBarState();
}
// Remove inter-activity transition to avoid screen tossing on tapping bottom navigation items
#Override
public void onPause() {
super.onPause();
overridePendingTransition(0, 0);
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
navigationView.postDelayed(() -> {
int itemId = item.getItemId();
if (itemId == R.id.navigation_analysis) {
startActivity(new Intent(getApplicationContext(), AnalysisActivity.class));
} else if (itemId == R.id.navigation_dashboard) {
startActivity(new Intent(getApplicationContext(), DashboardActivity.class));
} else if (itemId == R.id.navigation_profile) {
startActivity(new Intent(getApplicationContext(), ProfileActivity.class));
}
finish();
}, 100);
return true;
}
private void updateNavigationBarState(){
int actionId = getNavigationMenuItemId();
selectBottomNavigationBarItem(actionId);
}
void selectBottomNavigationBarItem(int itemId) {
Menu menu = navigationView.getMenu();
for (int i = 0, size = menu.size(); i < size; i++) {
MenuItem item = menu.getItem(i);
boolean shouldBeChecked = item.getItemId() == itemId;
if (shouldBeChecked) {
item.setChecked(true);
break;
}
}
}
abstract int getContentViewId();
abstract int getNavigationMenuItemId();
}
Make sure to use getApplicationContext in onNavigationSelected().
Dashboard Activity:
public class DashboardActivity extends BaseActivity {
#Override
int getContentViewId() {
return R.layout.activity_dashboard ;
}
#Override
int getNavigationMenuItemId() {
return R.id.navigation_dashboard;
} }
Similarly - make the other activities just like this.
XML PART
bottom_navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.BottomNavigationView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"
app:menu="#menu/navigation"
/>
navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/navigation_analysis"
android:icon="#drawable/ic_home_black_24dp"
android:title="#string/title_analysis" />
<item
android:id="#+id/navigation_dashboard"
android:icon="#drawable/ic_dashboard_black_24dp"
android:title="#string/title_dashboard" />
<item
android:id="#+id/navigation_profile"
android:icon="#drawable/ic_notifications_black_24dp"
android:title="#string/title_profile" />
</menu>
activity_dashboard.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="#+id/frame_dashboard">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/title_dashboard"/>
</FrameLayout>
<include
layout="#layout/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
/>
</LinearLayout>
Similarly - make other xml files just like this.
This should hopefully help
Related
I created a setting activity. When the user clicks setting it move from mainactivity to settingsactivity but it does not go to the previous page when I click the back button at the top of the action bar it says app keeps stopping. If I click phone back button it works.
Here I attached my coding correct it. How can I do this?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_activity);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.settings, new SettingsFragment())
.commit();
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
NavUtils.navigateUpFromSameTask(this);
}
return super.onOptionsItemSelected(item);
}
public static class SettingsFragment extends PreferenceFragmentCompat {
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey)
{
setPreferencesFromResource(R.xml.root_preferences, rootKey);
}
}
It's preferred to use finish() in an activity, since it'll automatically go back to the last activity.
first, add to the tollbar in the XML file
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary" >
<ImageView
android:id="#+id/home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_back"/>
</androidx.appcompat.widget.Toolbar>
and
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent intent = new Intent(this, HomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
I have an android Activity with a bottom menu navigation bar, That navigates between three fragments and a single top menu item that should open a new activity, But the top menu ActionBar item is not responding to click events. Maybe there is something am missing? Or should I be handling the menu from within my fragments?
Here is my code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Set Network Connection Listener
setConnectionListener(this);
//check the network connectivity when activity is created
checkConnection();
BottomNavigationView bottomNavigation = (BottomNavigationView) findViewById(R.id.bottom_navigation);
bottomNavigation.setOnNavigationItemSelectedListener(this);
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.frame_layout, HomeFragment.newInstance());
transaction.commit();
// Used to select item programmatically
// bottomNavigation.getMenu().getItem(0).setChecked(true);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.top, menu);
// return super.onCreateOptionsMenu(menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.i(TAG, "Menu Clicked " + item.getItemId());
switch (item.getItemId()){
case R.id.tab_cart:
Intent intent = new Intent(this, CartActivity.class);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
My Menu top.xml res menu file
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.shopcentra.activities.MainActivity">
<item
android:id="#+id/tab_cart"
android:icon="#mipmap/cart"
android:title="#string/cart"
app:actionLayout="#layout/notification_layout"
app:showAsAction="always">
</item>
</menu>
I can't see where you've added a View.OnClickListener on the "tab_cart". If you have set one, please share that code as well otherwise, add an OnCLickListener on that view and see if the problem persists then as well.
EDIT: code to add OnClickListener on menu item:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuItem tabCartMenuItem = menu.findItem(R.id.tab_cart);
View notificationActionView = menuItem.getActionView();
notificationActionView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onOptionsItemSelected(tabCartMenuItem));
}
});
}
Try adding this code to your onCreateOptionsMenu() method.
Let me say that before facing this problem i had almost fucked up my entire project, had bugs for a few days and eventually solved them.
My Android app is now almost fine except that whenever I click on the Options Menu (in ANY activity, not just this one i'm posting here) it crashes unexpectedly with a strange message which doesn't make ANY reference to my code.
Here's the stack trace:
12-28 22:15:07.842 11672-11672/com.cats.timemanager E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.cats.timemanager, PID: 11672
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
at android.support.v7.view.menu.ListMenuItemView.setTitle(ListMenuItemView.java:127)
at android.support.v7.view.menu.ListMenuItemView.initialize(ListMenuItemView.java:113)
at android.support.v7.view.menu.MenuAdapter.getView(MenuAdapter.java:100)
at android.support.v7.view.menu.MenuPopup.measureIndividualMenuWidth(MenuPopup.java:160)
at android.support.v7.view.menu.StandardMenuPopup.tryShow(StandardMenuPopup.java:153)
at android.support.v7.view.menu.StandardMenuPopup.show(StandardMenuPopup.java:187)
at android.support.v7.view.menu.MenuPopupHelper.showPopup(MenuPopupHelper.java:290)
at android.support.v7.view.menu.MenuPopupHelper.tryShow(MenuPopupHelper.java:175)
at android.support.v7.widget.ActionMenuPresenter$OpenOverflowRunnable.run(ActionMenuPresenter.java:803)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
It just looks like my app is crashing with no reason.
Here is my code:
package com.cats.timemanager.activities;
//Cannot write imports here sorry, StackOverflow editor sucks
public class MainActivity extends AppCompatActivity {
/**
* The {#link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {#link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {#link android.support.v4.app.FragmentStatePagerAdapter}.
*/
private SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {#link ViewPager} that will host the section contents.
*/
private ViewPager mViewPager;
AppSettingsData myAppSettingsData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myAppSettingsData = new AppSettingsData(getApplicationContext());
if (myAppSettingsData.getBoolean("first_start", true)) {
Intent tempIntent = new Intent(getBaseContext(), IntroActivity.class);
startActivity(tempIntent);
}
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
mViewPager = (ViewPager) findViewById(R.id.container);
setSupportActionBar(toolbar);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
setTitle(mSectionsPagerAdapter.getPageTitle(position));
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
setTitle(mSectionsPagerAdapter.getPageTitle(0));
/**
* TODO find out sth else to check whether the service is on
*/
if (isServiceRunning(ScreenService.class) == false) {
Intent intentScreenService = new Intent(getApplicationContext(), ScreenService.class);
intentScreenService.putExtra("EVENT", 1);
getApplicationContext().startService(intentScreenService);
}
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent myIntent = new Intent(getBaseContext(), ApplicationStatisticsActivity.class);
startActivity(myIntent);
}
});
}
#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_activity_menu, menu);
Log.i("CATs", "THIS LOG APPEARS-> THE APP IS WORKING FINE TILL NOW.");
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.main_activity_action_settings) {
Intent myIntent = new Intent(getBaseContext(), SettingsActivity.class);
startActivity(myIntent);
return true;
}
if (id == R.id.main_activity_action_per_app_statistics) {
Intent myIntent = new Intent(getBaseContext(), ApplicationStatisticsActivity.class);
startActivity(myIntent);
return true;
}
if (id == R.id.main_activity_action_timeline) {
Intent myIntent = new Intent(getBaseContext(), TimeLineActivity.class);
startActivity(myIntent);
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a ApplicationStatisticsFragment (defined as a static inner class below).
switch (position+1) {
case 1:
return DailyFragment.newInstance(position + 1);
case 2:
return WeeklyFragment.newInstance(position + 1);
case 3:
return MonthlyFragment.newInstance(position + 1);
case 4:
return YearlyFragment.newInstance(position + 1);
}
return null;
}
#Override
public int getCount() {
// Show 4 total pages.
return 4;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position+1) {
case 1:
return "Usage stats - Today";
case 2:
return "Usage stats - This Week";
case 3:
return "Usage stats - This Month";
case 4:
return "Usage stats - This Year";
}
return null;
}
}
private boolean isServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
}
Here's the most important part of it:
#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_activity_menu, menu);
Log.i("CATs", "THIS LOG APPEARS-> THE APP IS WORKING FINE TILL NOW.");
//THE APP IS WORKING FINE TILL HERE. PROBABLY onCreateOptionsMenu is NOT THE PROBLEM.
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.main_activity_action_settings) {
Intent myIntent = new Intent(getBaseContext(), SettingsActivity.class);
startActivity(myIntent);
return true;
}
if (id == R.id.main_activity_action_per_app_statistics) {
Intent myIntent = new Intent(getBaseContext(), ApplicationStatisticsActivity.class);
startActivity(myIntent);
return true;
}
if (id == R.id.main_activity_action_timeline) {
Intent myIntent = new Intent(getBaseContext(), TimeLineActivity.class);
startActivity(myIntent);
return true;
}
return super.onOptionsItemSelected(item);
}
Here's main_activity_menu.xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.cats.timemanager.activities.MainActivity">
<item
android:id="#+id/main_activity_action_per_app_statistics"
android:orderInCategory="100"
android:title="#string/main_activity_action_per_app_statistics" />
<item
android:id="#+id/main_activity_action_timeline"
android:orderInCategory="101"
android:title="#string/main_activity_action_timeline" />
<item
android:id="#+id/main_activity_action_settings"
android:orderInCategory="102"
android:title="#string/main_activity_action_settings" />
</menu>
And here the layout activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.cats.timemanager.activities.MainActivity">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="#dimen/fab_margin"
android:tint="#color/white"
app:srcCompat="#drawable/apps_icon" />
</android.support.design.widget.CoordinatorLayout>
Why is it crashing that strange way?
Sorry the question is so long, you can just ignore the first code i posted cause i don't think the error is there (if there is any...).
For the brave souls who're trying to solve this error.
The menu kept crashing the application: so i decided to create a new project importing all the old files and I updated support libraries to v27.0.2 (from 25.3.1).
Worked on it for an hour or so: now when i launch the app it tells me it crashes WITHOUT throwing any error.
When I tap on "Close application", the app keeps working just fine and the menu works perfect.
TLDR
Just give up and
git checkout [olderVersionWithNoErrors]
I can't seem to figure this one out. I have MainActivity and created SecondActivity and ThirdActivity that I want to be able to navigate to.
I'm using BottomNavigation in my MainActivity to navigated between activities:
public class MainActivity extends AppCompatActivity {
protected BottomNavigationView navigationView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_menuItem1:
Intent intent = new Intent(MainActivity.this, MainActivity.class);
startActivity(intent);
return true;
case R.id.navigation_menuItem2:
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
return true;
case R.id.navigation_menuItem3:
Intent intent = new Intent(MainActivity.this, ThirdActivity.class);
startActivity(intent);
return true;
}
return false;
}
};
navigationView = (BottomNavigationView) findViewById(R.id.navigation);
navigationView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
Any clue why it's not switching pages/activities?
EDIT: Added these lines to make it work:
protected BottomNavigationView navigationView;
AND
navigationView = (BottomNavigationView) findViewById(R.id.navigation);
navigationView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
Thanks for the help!
just in case you missed something, make sure you didn't forget something:
Create a BottomNavigationView in xml of your layout:
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="0dp"
android:layout_marginStart="0dp"
android:background="?android:attr/windowBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="#menu/navigation" />
Create a file here navigation.xml in menu resource folder. This file is used for providing the MenuItems in BottomNavigationView
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/navigation_menuItem1"
android:icon="#drawable/ic_home_black_24dp"
android:title="#string/menuItem1" />
<item
android:id="#+id/navigation_menuItem2"
android:icon="#drawable/ic_dashboard_black_24dp"
android:title="#string/menuItem2" />
<item
android:id="#+id/navigation_menuItem3"
android:icon="#drawable/ic_notifications_black_24dp"
android:title="#string/menuItem3" />
</menu>
Now lets set the listener for the Click Events OnNavigationItemSelectedListener and OnNavigationItemReselectedListener on Menu Items:
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_menuItem1:
return true;
case R.id.navigation_menuItem2:
return true;
case R.id.navigation_menuItem3:
return true;
}
return true;
}
};
private BottomNavigationView.OnNavigationItemReselectedListener mOnNavigationItemReselectedListener = new BottomNavigationView.OnNavigationItemReselectedListener() {
#Override
public void onNavigationItemReselected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_menuItem1:
Log.d(TAG, "navigation_menuItem1 Reselected ===");
break;
case R.id.navigation_menuItem2:
Log.d(TAG, "navigation_menuItem2 Reselected ===");
break;
case R.id.navigation_menuItem3:
Log.d(TAG, "navigation_menuItem3 Reselected ===");
break;
}
}
};
bottomNavigationView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
bottomNavigationView.setOnNavigationItemReselectedListener(mOnNavigationItemReselectedListener);
EDIT
Add this to your onCreate()
BottomNavigationView bottomNavigationView;
bottomNavigationView = findViewById(R.id.navigation);
When the app first starts up, it checks the last menuitem as if it was clicked. It displays the first menuitem content. In Android Studio, no errors, warnings, or logs are displayed that hint at anything going wrong.
Once the app is running, if I click on any of the other menuitems, it works normal. I can click on each of the menuitems and the correct fragment populates accordingly.
Here is MainActivity.java:
public class MainActivity extends AppCompatActivity {
private static final String SELECTED_ITEM = "arg_selected_item";
private BottomNavigationView mBottomNav;
private int mSelectedItem;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBottomNav = (BottomNavigationView) findViewById(R.id.navigation);
mBottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
selectFragment(item);
return true;
}
});
MenuItem selectedItem;
if (savedInstanceState != null) {
mSelectedItem = savedInstanceState.getInt(SELECTED_ITEM, 0);
selectedItem = mBottomNav.getMenu().findItem(mSelectedItem);
} else {
selectedItem = mBottomNav.getMenu().getItem(0);
}
selectFragment(selectedItem);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(SELECTED_ITEM, mSelectedItem);
super.onSaveInstanceState(outState);
}
#Override
/* This is never called on start up */
public void onBackPressed() {
MenuItem homeItem = mBottomNav.getMenu().getItem(0);
if (mSelectedItem != homeItem.getItemId()) {
// select home item
selectFragment(homeItem);
} else {
super.onBackPressed();
}
}
private void selectFragment(MenuItem item) {
Fragment frag = null;
// init corresponding fragment
switch (item.getItemId()) {
case R.id.menu_home:
frag = HomeFragment.newInstance();
break;
case R.id.menu_archives:
frag = ArchivesFragment.newInstance();
break;
case R.id.menu_inspirational:
frag = InspirationalFragment.newInstance();
break;
case R.id.menu_search:
frag = SearchFragment.newInstance();
break;
}
// update selected item
mSelectedItem = item.getItemId();
// unchecked the other items.
//THIS LINE HERE
for (int i = 0; i < mBottomNav.getMenu().size(); i++) {
MenuItem menuItem = mBottomNav.getMenu().getItem(i);
menuItem.setChecked(menuItem.getItemId() == mSelectedItem);
}
updateToolbarText(item.getTitle());
if (frag != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, frag, frag.getTag());
ft.commit();
}
}
private void updateToolbarText(CharSequence text) {
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(text);
}
}
Here is activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:design="http://schemas.android.com/apk/res-auto"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.ourdailystrength.mobile.android.MainActivity">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#f1f1f1">
</FrameLayout>
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
design:menu="#menu/bottom_nav_items" />
</LinearLayout>
Here is bottom_nav_items.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/menu_home"
android:title="#string/menu_home"
android:icon="#drawable/ic_home_black_48dp"
android:checked="true" <!-- Doesn't matter if this line is included or not -->
app:showAsAction="ifRoom"/>
<item
android:id="#+id/menu_archives"
android:title="#string/menu_archives"
android:icon="#drawable/ic_archive_black_48dp"
app:showAsAction="ifRoom"/>
<item
android:id="#+id/menu_search"
android:title="#string/menu_search"
android:icon="#drawable/ic_search_black_48dp"
app:showAsAction="ifRoom"/>
<item
android:id="#+id/menu_inspirational"
android:title="#string/menu_inspirational"
android:icon="#drawable/ic_photo_black_48dp"
app:showAsAction="ifRoom"/>
</menu>
Here is a screenshot of when it first boots up:
Why is the last menuitem being checked and not the first menuitem?
EDIT:
So, from answers given below, I made this change and it works:
private void selectFragment(MenuItem item) {
Fragment frag = null;
// update selected item
mSelectedItem = item.getItemId();
// unchecked the other items.
for (int i = 0; i < mBottomNav.getMenu().size(); i++) {
MenuItem menuItem = mBottomNav.getMenu().getItem(i);
menuItem.setChecked(false);
}
// init corresponding fragment
switch (mSelectedItem) {
case R.id.menu_home:
frag = HomeFragment.newInstance();
mBottomNav.getMenu().findItem(R.id.menu_home).setChecked(true);
break;
case R.id.menu_archives:
frag = ArchivesFragment.newInstance();
mBottomNav.getMenu().findItem(R.id.menu_archives).setChecked(true);
break;
case R.id.menu_inspirational:
frag = InspirationalFragment.newInstance();
mBottomNav.getMenu().findItem(R.id.menu_inspirational).setChecked(true);
break;
case R.id.menu_search:
frag = SearchFragment.newInstance();
mBottomNav.getMenu().findItem(R.id.menu_search).setChecked(true);
break;
}
updateToolbarText(item.getTitle());
if (frag != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.container, frag, frag.getTag());
ft.commit();
}
}
Why would the THIS LINE HERE in the above code cause it to do this weird error?
Hope this may help you to resolve your issue.
Call this method whenever you change the Fragment. Pass checkedcolor and unchecked color according to your needs.
private void changeMenuItemCheckedStateColor(int checkedColor, int uncheckedColor) {
int[][] states = new int[][]{
new int[]{-android.R.attr.state_checked}, // unchecked
new int[]{android.R.attr.state_checked}, // checked
};
int[] colors = new int[]{
uncheckedColor,
checkedColor
};
ColorStateList colorStateList = new ColorStateList(states, colors);
bottomNavigationView.setItemTextColor(colorStateList);
bottomNavigationView.setItemIconTintList(colorStateList);
}
There is 2 Solutions
1) Use Group
<group android:checkableBehavior="single">
<item .../>
<item .../>
<item .../>
</group>
2) Do it by programmatically
Menu bottomMenu;
BottomNavigationView bottomNavigationMenu = (BottomNavigationView) findViewById(R.id.bottom_navigation);
bottomMenu = navigation.getMenu();
bottomMenu.findItem(R.id.menu_home).setChecked(true);
Hope it will help , If you have any queries please comment.
Remove below code:
// unchecked the other items.
for (int i = 0; i < mBottomNav.getMenu().size(); i++) {
MenuItem menuItem = mBottomNav.getMenu().getItem(i);
menuItem.setChecked(menuItem.getItemId() == mSelectedItem);
}
and give tint color in BottomNavigationView:
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="start"
app:itemIconTint="#drawable/nav_item_color_state"
design:menu="#menu/bottom_nav_items" />