Issue
In my Android app (Java) I'm trying to figure out how to change my icon focus color to accurately indicate the fragment that is visible. If I press on a bottom nav icon, the icon I pressed is in focus and the navigation takes me to the fragment associated with that icon.
However, when I press the back arrow to go back to the home screen, the icon I previously pressed is still in focus instead of the home icon. How can I only have the icon associated with the visible fragment be in focus?
EDIT:
Here's my NavigationActivity xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background"
tools:context=".activity.NavigationActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar" />
<ImageView
android:id="@+id/backArrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="54dp"
android:layout_marginBottom="20dp"
android:src="@drawable/arrow_left"
android:visibility="gone" />
<ImageView
android:id="@+id/logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginStart="98dp"
android:layout_marginTop="46dp"
android:layout_marginBottom="20dp"
android:layout_toEndOf="@+id/backArrow"
android:src="@drawable/logo" />
<fragment
android:id="@+id/fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/bottomBar"
android:layout_below="@+id/logo"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomBar"
style="@style/BottomNavTheme"
android:layout_width="match_parent"
android:layout_height="70dp"
android:layout_alignParentBottom="true"
android:paddingTop="7dp"
android:paddingBottom="7dp"
android:theme="@style/app_theme"
app:itemIconTint="@drawable/bottom_nav_icon_color_selector"
app:itemTextColor="@drawable/bottom_nav_icon_color_selector"
app:menu="@menu/bottom_bar_nav" />
</RelativeLayout>
Nav icon color selector xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:color="@android:color/white" />
<item android:state_pressed="true" android:state_enabled="true" android:color="@android:color/white" />
<item android:color="#8E8392" />
</selector>
NavigationActivity:
@AndroidEntryPoint
public class NavigationActivity extends DeviceBaseActivity {
NavController navController;
private AppBarConfiguration appBarConfiguration;
private ActivityNavigationBinding navigationBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
navigationBinding = ActivityNavigationBinding.inflate(getLayoutInflater());
View view = navigationBinding.getRoot();
setContentView(view);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
navController = Navigation.findNavController(NavigationActivity.this, R.id.fragment);
appBarConfiguration =
new AppBarConfiguration.Builder(navController.getGraph()).build();
setupActionBar(navController, appBarConfiguration);
navigationBinding.bottomBar.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.mainFragment:
navController.navigate(R.id.mainFragment);
return true;
case R.id.scheduleFragment:
navController.navigate(R.id.scheduleFragment);
return true;
case R.id.settingsFragment:
navController.navigate(R.id.settingsFragment);
return true;
}
return false;
}
});
}
private void setupActionBar(NavController navController,
AppBarConfiguration appBarConfig) {
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfig);
}
@Override
public boolean onSupportNavigateUp() {
return NavigationUI.navigateUp(Navigation.findNavController(this, R.id.fragment), appBarConfiguration);
}
}
Solution
No need to setOnItemSelectedListener
, following is my setup:
1. Setup Menu Resource File
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/homeFragment" //must match the id on navigation graph!!
android:icon="@drawable/home"
android:title="Home" />
<item
android:id="@+id/meFragment" //must match the id on navigation graph!!
android:icon="@drawable/person"
android:title="Me" />
</menu>
2. Setup BottomNavigationView
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/main" />
3. Setup MainActivity with BottomNavigationView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
navController = getNavHostFragmentById(R.id.nav_host_fragment).navController
NavigationUI.setupActionBarWithNavController(this, navController)
NavigationUI.setupWithNavController(binding.bottomNavigationView, navController) //key part
}
Demo: https://youtu.be/PSAbsVZz3Xw
Answered By - Sam Chen
Answer Checked By - Mary Flores (JavaFixing Volunteer)