Android Kotlin Bottom navigation bar - android

I use bottom navigation bar (xx_activity bottom by default) but I have problems.
When I click on the item it's OK, the activity is good but the item of the activity not change...
import android.content.Intent
import android.os.Bundle
import android.support.design.widget.BottomNavigationView
import android.support.v7.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_grammaire.*
class GrammaireActivity : AppCompatActivity() {
private val mOnNavigationItemSelectedListener=BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_grammaire -> {
val intent = Intent(this,GrammaireActivity::class.java)
startActivity(intent)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_situations -> {
val intent = Intent(this,SituationsActivity::class.java)
startActivity(intent)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_lexiquefrsa -> {
val intent = Intent(this,LexiqueFrSaActivity::class.java)
startActivity(intent)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_lexiquesafr -> {
val intent = Intent(this,LexiqueSaFrActivity::class.java)
startActivity(intent)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_infos -> {
val intent = Intent(this,InfosActivity::class.java)
startActivity(intent)
return#OnNavigationItemSelectedListener true
}
}
false
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_grammaire)
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
}
}

I believe it's recommended to use Fragments with bottom navigation, rather than Activities.
With the onClick you would swap out the current Fragment with the one identified by the click.

I am not sure about "item of the activity not change" but i think you mean to say that the content of your current Activity doesn't change.
So for that you should replace Fragments in an Activity on the click of the BottomNavigation item. This is how it should be done
when (item.itemId) {
R.id.navigation_grammaire -> {
supportFragmentManager.beginTransaction.replace(R.id.container, FragmnetGrammaire().commit())
}
where "container" is the id of the view above your BottomNavigation bar. It can be FrameLayout.
FragmnetGrammaire(), is the instance of your Fragment.

Related

when i press back fragments change but navigation view does not select the menu item

package com.example.backstack
import android.os.Bundle
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.navigation.NavigationBarView
Main Activity on create function overriden
lateinit var bottomNavigationView:BottomNavigationView
class MainActivity : AppCompatActivity(), NavigationBarView.OnItemSelectedListener,FragmentManager.OnBackStackChangedListener {
// lateinit var fragmentManager:FragmentManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
loadFragments(FeedFragment())
bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottomNavigation)
bottomNavigationView.setOnItemSelectedListener(this)
getSupportFragmentManager().addOnBackStackChangedListener(this)
}
Fragments are loaded
fun loadFragments(fragment:Fragment?):Boolean{
if(fragment != null){
getSupportFragmentManager().beginTransaction().
replace(R.id.parentFrame,fragment).
addToBackStack(null)
.commit()
}
return true
}
which navigation item clicked
override fun onNavigationItemSelected(item: MenuItem): Boolean {
var fragment:Fragment? = null
when(item.itemId){
R.id.feedFragment -> fragment = FeedFragment()
R.id.videosFragment -> fragment = VideosFragment()
R.id.exploreFragment -> fragment = ExploreFragment()
}
return loadFragments(fragment)
}
Backstack function is written but i don't know how to make it function provide me with some possible solutions
override fun onBackStackChanged() {
val bse = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().backStackEntryCount - 1)
//bse will be the backstack entry for current fragment
if (bse.name == FeedFragment::class.java.getName()) {
bottomNavigationView.getMenu().getItem(0).setChecked(true)
} else if (bse.name == VideosFragment::class.java.getName()) {
bottomNavigationView.getMenu().getItem(1).setChecked(true)
}
else if (bse.name == ExploreFragment::class.java.getName()) {
bottomNavigationView.getMenu().getItem(2).setChecked(true)
}
}
}
when i press back fragments change but navigation view does not select the menu item

onItemSelectedListener for bottomnavigationbar

I am new to android and Kotlin, developing a bottom navigation bar using onitemselectedListener, since setOnNavigationItemSelectedListener is deprecated and I couldn't find any youtube tutorial that explains how to used onitemselectedlistener for navigationbar. navigation shows up on the emulator, but fragments are not showing up when i click on navigation Icons. here are my codes.
adding image of activity_main and emulator error image
fragmentWord image, that is connected to the first icon of "A" but doesn't show up
MainActivity
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.Fragment
import com.aryanvedh.vocabapp2.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val wordFragment = WordFragment()
val memorisedFragment = MemorisedFragment()
setCurrentFragment(wordFragment)
binding.bottomNavigationView.setOnItemSelectedListener { item ->
when (item.itemId) {
R.id.words -> setCurrentFragment(wordFragment)
R.id.memorised -> setCurrentFragment(memorisedFragment)
}
true
}
}
private fun setCurrentFragment(fragment: Fragment) =
supportFragmentManager.beginTransaction().apply {
replace(R.id.flFragment, fragment)
commit()
}
}```
any help? thanks
Use the function like this:
val navBar = findViewById<NavigationBarView>(R.id.navBar)
navBar.setOnItemSelectedListener {
when(it.itemId) {
R.id.item01 -> {
setCurrentFragment(Fragment01())
true
}
R.id.item02 -> {
setCurrentFragment(Fragment02())
true
}
R.id.item03 -> {
setCurrentFragment(Fragment03())
true
}
else -> {
false
}
}
}
It now should raise the fragments when each navigation bar item is selected.
You need to use the OnNavigationItemSelectedListener Method to capture once the item is selected in Bottom Navigation.
Here is the sample code attached from Documentation.
BottomNavigationView.OnNavigationItemSelectedListener { item ->
when(item.itemId) {
R.id.item1 -> {
// Respond to navigation item 1 click
true
}
R.id.item2 -> {
// Respond to navigation item 2 click
true
}
else -> false
}
}
Please refer to the Official Documentation for more information about BottomNavigationView.

how to put 2 different Fragments in a BottomNavigationView?

I try to put a BottomNavigationView like this in my main Activity, and I have a recycler view too :
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
loadFragment(HomeFragment(this))
//import the bottomNavigationView
val navigationView = findViewById<BottomNavigationView>(R.id.barre_nav)
navigationView.setOnNavigationItemSelectedListener {
when(it.itemId) {
R.id.nav_home -> {
loadFragment(HomeFragment(this))
return#setOnNavigationItemSelectedListener true
}
R.id.nav_choose -> {
loadFragment(ChooserFragment(ChooserActivity()))
return#setOnNavigationItemSelectedListener true
}
else -> false
}
}
}
private fun loadFragment(fragment: Fragment) {
val transactionMuscle = supportFragmentManager.beginTransaction()
transactionMuscle.replace(R.id.fragment_container, fragment)
transactionMuscle.addToBackStack(null)
transactionMuscle.commit()
}
But my problem with this code which is fine if I would to put the two view in the same container, but I wouldn't, is : I have a ChooserActivity and I would the second part of my bottomNavigationView to redirect to this page, and not the MainActivity Fragment with the Chooser composant. I would do the same as it do for the main Activity but with the ChooserActivity.
I doesn't know if I am clear, but I Thank you in advance.
EDIT to clarify :
My aim is to with mybottomNavigationView, when we click on the first button, it redirect to the MainActivity, and when we click on the second button, it redirect to the ChooserActivity. Th two must have there own containers. Hopefully it is better...
Solution
try this code:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val bottomNavigation: BottomNavigationView = findViewById(R.id.barre_nav)
bottomNavigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
} //onCreate() end here
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.nav_home -> {
val homeFragment = HomeFragment.newInstance()
loadFragment(homeFragment)
return#OnNavigationItemSelectedListener true
}
R.id.nav_choose -> {
val chooserFragment = ChooserFragment.newInstance()
loadFragment(chooserFragment)
return#OnNavigationItemSelectedListener true
}
}
false
}
private fun loadFragment(fragment: Fragment) {
val transactionMuscle = supportFragmentManager.beginTransaction()
transactionMuscle.replace(R.id.fragment_container, fragment)
transactionMuscle.addToBackStack(null)
transactionMuscle.commit()
}
In You Fragments OnCreateView() Method add these lines too :
1.HomeFragment
companion object {
fun newInstance(): HomeFragment = HomeFragment()
}
2.ChooserFragment
companion object {
fun newInstance(): ChooserFragment= ChooserFragment()
}
Hope so it works :)
If you still face any issue , please add it into comments

show existing navigation menu connected to one activity in another activity

I am in the process of building an app and have a navigation menu in my first activity, however, when I go to the second it doesn't show, so which bits of code do I copy from my first activity for the navigation menu to show there too?
I have tried to copy what I thought was relevant bits of code from the first activity into the second, however that second activity crashed, so I tried to remove that added code and failed to reverse it, so I imported the code from a backup to get it working again.
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar: Toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
val fab: FloatingActionButton = findViewById(R.id.fab)
fab.setOnClickListener { view ->
val intent = Intent(this, Main2Activity::class.java)
val sharedPref = this?.getPreferences(Context.MODE_PRIVATE)
val mystr = sharedPref.getInt(getString(R.string.STR), 0)
intent.putExtra("data", mystr)
startActivity(intent)
}
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
val toggle = ActionBarDrawerToggle(
this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close
)
drawerLayout.addDrawerListener(toggle)
toggle.syncState()
navView.setNavigationItemSelectedListener(this)
//val db = FirebaseFirestore.getInstance()
}
override fun onBackPressed() {
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
drawerLayout.closeDrawer(GravityCompat.START)
} else {
super.onBackPressed()
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// 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.
return when (item.itemId) {
R.id.action_settings -> true
else -> super.onOptionsItemSelected(item)
}
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Handle navigation view item clicks here.
when (item.itemId) {
R.id.nav_home -> {
// Handle the camera action
val i = Intent(Intent.ACTION_VIEW, Uri.parse("https://www.facebook.com/brobostigon/"))
startActivity(i)
}
R.id.nav_gallery -> {
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
}
R.id.nav_slideshow -> {
val intent = Intent(this, Main2Activity::class.java)
startActivity(intent)
}
R.id.nav_tools -> {
}
R.id.nav_share -> {
val i = Intent(Intent.ACTION_VIEW, Uri.parse("http://taylorworld.me.uk/privacy-policy.html"))
startActivity(i)
}
R.id.nav_send -> {
}
}
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
drawerLayout.closeDrawer(GravityCompat.START)
return true
}
Here is my second activity
class Main2Activity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
//val mystr: Int = intent.getIntExtra("data", 0)
//editText8.setText(Integer.toString(mystr))
}
Is is not feasible. You have to make separate navigation drawer on each activity and this is not feasible.
Instead you can use fragments, even you need to use fragments with navigation drawer if you want to keep same navigation drawer on different layouts too.
val fragmentManager = supportFragmentManager val fragmentTransaction = fragmentManager.beginTransaction()
val fragment = TitleFragment() val fragment2 = MiscFragment() fragmentTransaction.add(R.id.contentlayout, fragment)
fragmentTransaction.remove(fragment2) fragmentTransaction.commit()
I put that in my mainactivity oncreate(), with the thinking when the activity loads it forces it to load a specific fragment, and only that fragment. contentlayout is the ID of the layout to which that will be applied, ie in my case it is the constraintlayout in content_main.xml.
check AndroidManifest.xml (app/manifests/AndroidManifest.xml), find correct activity and check line android:theme="#style/... />

How to load fragment on BottomNavigationView depending on selected item?

I have a simple application written in Kotlin that has a BottomNavigationView. The idea is to have a single activity (MainActivity) with a fragment to be loaded for each tab on the BottomNavigationView.
I have already created a fragment I would like to load when a tab is selected (HomeFragment) and am already changing the text under the icons on the BottomNavigationView when the active tab changes.
Now I would like to inflate / load the fragment when I change tabs. How would I go about doing this?
MainActivity.kt:
class MainActivity : AppCompatActivity() {
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_enrollments -> {
message.setText(R.string.title_enrollments)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_timeline -> {
message.setText(R.string.title_timeline)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_home -> {
message.setText(R.string.title_home)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_alerts -> {
message.setText(R.string.title_alerts)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_profile -> {
message.setText(R.string.title_profile)
return#OnNavigationItemSelectedListener true
}
}
false
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
}
override fun onResume() {
super.onResume()
setContentView(R.layout.activity_main)
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.navigation)
bottomNavigationView.selectedItemId = R.id.navigation_home
}
}
Instead of message.setText(R.string.title_enrollments) do
supportFragmentManager.beginTransaction()
.replace(containerViewId, fragmentInstance, "TAG")
.commitAllowingStateLoss()
Or you can use an extension function I use in my code to make it cleaner. Just add this in some .kt file
inline fun FragmentManager.transactStateless(func: FragmentTransaction.() -> Unit) {
val transaction = beginTransaction()
transaction.func()
transaction.commitAllowingStateLoss()
}
and now you can add remove fragment this way:
supportFragmentManager.transactStateless {
replace(containerViewId, fragmentInstance, "TAG")
}

Categories

Resources