I have a Fragment with bottom tabs named TabsFragment
class BottomTabsFragment : Fragment(R.layout.fragment_tabs) {
private val bottomNavigationView: BottomNavigationView by lazy {
requireView().findViewById(R.id.bottom_navigation_view)
}
private val tabsNavigation: NavController by lazy {
(childFragmentManager.findFragmentById(R.id.tabs_host_fragment) as NavHostFragment).navController
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
bottomNavigationView.setupWithNavController(tabsNavigation)
}
}
Here is a menu for bottom navigation view:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#id/dashboard_navigation"
android:title="Dashboard" />
<item
android:id="#id/search_vehicle_navigation"
android:title="Search" />
<item
android:id="#id/todos_navigation"
android:title="Todos" />
<item
android:id="#id/activities_navigation"
android:title="Activities" />
<item
android:id="#id/more_navigation"
android:title="More" />
</menu>
Graph for bottom menu:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/tabs_navigation"
app:startDestination="#id/search_vehicle_navigation">
<include app:graph="#navigation/dashboard_navigation" />
<include app:graph="#navigation/search_vehicle_navigation" />
<include app:graph="#navigation/todos_navigation" />
<include app:graph="#navigation/activities_navigation" />
<include app:graph="#navigation/more_navigation" />
</navigation>
Everything is done according Google tutorials and samples and it does not work. Only 1 default fragment that is setted as StartDestination is saved (Becouse it is in stack to be displayed when user press back button):
https://developer.android.com/guide/navigation/navigation-multi-module
https://github.com/android/architecture-components-samples/tree/main/NavigationAdvancedSample
Related
I am using fragment and in that fragment i have ViewPager and in ViewPager i have added two fragments.when i open the app Everything works fine but my status bar becomes black and to see the icon i need to scroll down and this is happening in android 11,below android 11 Eveything working fine.now please let me know how to fix it...please don't ignore this and answer should be in Kotlin if Possible
I am attaching the code for it also
Main Activity:
class dashact : AppCompatActivity() {
lateinit var toolbar: Toolbar
lateinit var coordinator: CoordinatorLayout
lateinit var navigationdrawer: NavigationView
lateinit var drawerLayout: DrawerLayout
var nameofuser :String?="jdghjg"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.dashact)
toolbar = findViewById(R.id.toolbar)
coordinator = findViewById(R.id.coordinator)
navigationdrawer = findViewById(R.id.navigationview)
drawerLayout = findViewById(R.id.drawerlayout)
actionbar()
var toggle = ActionBarDrawerToggle(
this#dashact,
drawerLayout,
R.string.open,
R.string.close
)
toggle.syncState()
drawerLayout.addDrawerListener(toggle)
hideSystemBars()
navigtiontitle("home")
supportFragmentManager.beginTransaction()
.replace(R.id.frame, frag1())
.commit()
drawerLayout.closeDrawers()
navigationdrawer.setNavigationItemSelectedListener {
if (it.isChecked==true){
it.isCheckable=true
}else{
it.isCheckable=false
}
when (it.itemId) {
R.id.home -> {
navigtiontitle("home")
supportFragmentManager.beginTransaction()
.replace(R.id.frame, frag1())
.commit()
drawerLayout.closeDrawers()
}
R.id.fav ->{
navigtiontitle("Favourites")
supportFragmentManager.beginTransaction()
.replace(R.id.frame,Viewpager2())
.commit()
drawerLayout.closeDrawers()
}
R.id.privacy ->{
navigtiontitle("Privacy Policies")
supportFragmentManager.beginTransaction()
.replace(R.id.frame,privacy())
.commit()
drawerLayout.closeDrawers()
}
R.id.details ->{
navigtiontitle("My Details")
supportFragmentManager.beginTransaction()
.replace(R.id.frame,MyFrag())
.commit()
drawerLayout.closeDrawers()
}
}
return#setNavigationItemSelectedListener true
}
}
fun navigtiontitle(title: String) {
supportActionBar?.title = title
}
fun actionbar() {
super.setSupportActionBar(toolbar)
supportActionBar?.title = "Bookhub"
supportActionBar?.setHomeButtonEnabled(true)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> drawerLayout.openDrawer(GravityCompat.START)
}
return super.onOptionsItemSelected(item)
}
fun hideSystemBars() {
val windowInsetsController =
ViewCompat.getWindowInsetsController(window.decorView) ?: return
// Configure the behavior of the hidden system bars
windowInsetsController.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
// Hide both the status bar and the navigation bar
windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
}
}
xml of main activity:
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawerlayout"
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"
>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="#+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark"
android:elevation="0dp" >
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
/>
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout
android:id="#+id/frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigationview"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:headerLayout="#layout/headers"
app:menu="#menu/icons"
android:layout_gravity="start"/>
</androidx.drawerlayout.widget.DrawerLayout>
themes.xml:
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Test" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">#color/purple_200</item> //for action bar
<item name="colorPrimaryVariant">#color/white</item> //can use to set status bar
<item name="colorOnPrimary">#color/purple_200</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">#color/teal_200</item>
<item name="colorSecondaryVariant">#color/teal_700</item>
<item name="colorOnSecondary">#color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">#color/purple_200</item>
<!-- Customize your theme here. -->
</style>
<style name="splashs" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="android:windowBackground">#drawable/splash</item>
<item name="android:statusBarColor" tools:targetApi="l">#color/purple_200</item>
</style>
</resources>
You are hiding your system bars(status and navigation) in hideSystemBars() method. You are getting a black status bar probably due to a display cutout.
Find more about supporting display cutout here
my application has a menu of 3 options, and what I want is that according to a condition that I define, it shows only 2 options, or it shows 3.
I have tried all the options that I have found on google and here, but none have worked for me.
My idea is that as soon as the view is created, the menu already shows the options that it can show according to the condition. But as I have been able to achieve it, I added a button to simulate the event.
I would greatly appreciate your help.
Here I attach the code:
1) activity_home.xml (some part)
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
android:onClick="ActivarMenus"/>
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:menu="#menu/home_menu"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" >
2) Aqui el archivo home_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/menu_item"
android:icon="#drawable/ic_baseline_more_vert_24"
app:showAsAction="ifRoom"
tools:ignore="MenuTitle">
<menu>
<item
android:id="#+id/newRegister"
android:icon="#drawable/ic_baseline_add_24"
app:showAsAction="always"
android:visible="true"
android:title="Nueva Orden Swab" />
<item
android:id="#+id/newAnexoo"
android:icon="#drawable/ic_baseline_add_24"
app:showAsAction="always"
android:visible="true"
android:title="Nuevo Formulario Anexo O" />
<item
android:id="#+id/sync"
android:icon="#drawable/ic_baseline_sync_24"
app:showAsAction="always"
android:visible="true"
android:title="Sincronizar" />
</menu>
</item>
</menu>
3) And a part of the HomeActivity.kt
class HomeActivity : ActivityViewBinding<ActivityHomeBinding, HomeVM>() {
private var mainMenu: Menu? = null
private lateinit var spm : SharedPreferencesManager
private val adapter: OrderAdapter by inject()
override fun inflateLayout(layoutInflater: LayoutInflater) =
ActivityHomeBinding.inflate(layoutInflater)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
//MenuMain.findItem(R.id.newAnexoo).isVisible = true
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater: MenuInflater = menuInflater
inflater.inflate(R.menu.home_menu, menu)
mainMenu = menu;
return true
}
fun ActivarMenus(view: View) {
mainMenu?.findItem(R.id.newRegister)?.isVisible = true
}
You should try this one it might be work.
if you want to change Menu Items at Run time You can use onPrepareOptionsMenu
#Override
public boolean onPrepareOptionsMenu(Menu menu){
if (//Your condition) {
menu.findItem(R.id.newRegister).setVisible(true);
}else {
menu.findItem(R.id.newRegister).setVisible(false);
}
return true;
}
In my app, i have an Activity, which has a FrameLayout in it. In this FrameLayout, there is a fragment, containing a ToolBar and a RecyclerView.
In this toolbar, i have a search button, which should start an Activity on item click. However, when i try to use onOptionsItemSelected, the apps gets built and installed succesfully, but when i try to tap that button in question, nothing happens. The Logcat, doesnt say anything either.
Can some points me what im doing wrong? Are there simpler or other easy ways to manage on ToolBar item clicks?
Fragment.kt
class FragmentTrack : Fragment() {
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = inflater.inflate(R.layout.fragment_track, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
...
topToolbar.setNavigationOnClickListener {
val dialog = FragmentBottomSheetDrawer()
dialog.show(childFragmentManager, dialog.tag)
}
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu_toolbar, menu)
super.onCreateOptionsMenu(menu, inflater)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when(item.itemId) {
R.id.fsvSearch -> Toast.makeText(context, "Clicked search button", Toast.LENGTH_SHORT).show()
}
return true
}
}
fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:theme="#style/Theme.Design.NoActionBar">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/topToolbar"
android:background="#color/colorPrimaryDark"
app:navigationIcon="#drawable/ic_outline_menu_24"
app:popupTheme="#style/popupMenuThemeDark"
app:titleTextColor="#android:color/white"
app:title="Revo"
app:menu="#menu/menu_toolbar"
app:layout_scrollFlags="scroll|enterAlways" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvTracks"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:clipToPadding="false"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
toolbar_menu.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/fsvSearch"
android:icon="#drawable/ic_search_24px"
android:title="#string/search"
app:showAsAction="always"/>
<item
android:id="#+id/fsvOrder"
android:icon="#drawable/ic_sort_24px"
android:title="#string/sort"
app:showAsAction="ifRoom">
<menu>
<group android:id="#+id/sortMenu" android:checkableBehavior="single">
<item
android:id="#+id/sortIncrease"
android:title="#string/increasing"/>
<item
android:id="#+id/sortDecrease"
android:title="#string/decreasing"/>
<item
android:id="#+id/sortMArtist"
android:title="#string/artist"/>
<item
android:id="#+id/sortAlbum"
android:title="#string/albums"/>
<item
android:id="#+id/sortYear"
android:title="#string/year"/>
<item
android:id="#+id/sortDate"
android:title="#string/date"/>
</group>
</menu>
</item>
<item
android:id="#+id/fsvGrid"
android:icon="#drawable/ic_grid_on_24px"
android:title="#string/grid"
app:showAsAction="ifRoom">
<menu>
<group android:id="#+id/gridMenu" android:checkableBehavior="single">
<item
android:id="#+id/gridOne"
android:title="1"/>
<item
android:id="#+id/gridTwo"
android:title="2"/>
<item
android:id="#+id/gridThree"
android:title="3"/>
<item
android:id="#+id/gridFour"
android:title="4"/>
</group>
</menu>
</item>
</menu>
I found a solution thanks to some external help. Its possible to work on the Toolbars item in an easier way.
In the onViewCreated method, we must add:
topToolbar.inflateMenu(R.menu.menu_toolbar)
topToolbar.setOnMenuItemClickListener {
when(it.itemId) {
R.id.fsvSearch -> //your code
}
true
}
Also, if the menu gets duplicated, remove the app:menu tag in the Toolbars xml
thanks Meltix for this, I've done a lot of research but most of the posts in SO are about Java and old fashioned ActionBar. There is not much info about material ToolBar and kotlin examples.
In my case I'm working on an old app developed mostly in Java but now developing new functionalities in Kotlin. In my fragment, I wasn't able to change the ActionBar's icons and behaviour (I wanted a particular ActionBar for my fragment). The solution I found is to hide the ActionBar and create a Toolbar inflating a custom menu inside. Also I added a back arrow button (thanks to John: here).
I've came to the conclusion (maybe I'm wrong) that you can't manage ActionBars from kotlin fragments, that's why you have to use toolbars. Here is my code in case it can help someone.
MyFragment.kt
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// hide the old actionBar
(activity as AppCompatActivity).supportActionBar!!.hide()
// create the toolbar
val toolbar = binding?.myToolbar
// add the back arrow button, see function below
val resId = getResIdFromAttribute(toolbar.context, android.R.attr.homeAsUpIndicator)
toolbar.navigationIcon = ContextCompat.getDrawable(toolbar.context, resId)
// tapping on the arrow will pop the current fragment
toolbar.setNavigationOnClickListener { parentFragmentManager?.popBackStackImmediate() }
// change toolbar title
toolbar.title = "Some title"
// inflate a custom menu, see code below
toolbar.inflateMenu(R.menu.my_custom_menu)
toolbar.setOnMenuItemClickListener {
when (it.itemId) {
R.id.infoButton -> someAction()
}
true
}
}
// get back arrow icon
#AnyRes
fun getResIdFromAttribute(context: Context, #AttrRes attr: Int): Int {
if (attr == 0) return 0
val typedValueAttr = TypedValue()
context.theme.resolveAttribute(attr, typedValueAttr, true)
return typedValueAttr.resourceId
}
my_fragment.xml
...
<androidx.appcompat.widget.Toolbar
android:id="#+id/myToolBar"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:visibility="visible"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:background="#color/azulOscuro"
>
</androidx.appcompat.widget.Toolbar>
my_custom_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:jsmovil="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<item
android:id="#+id/infoButton"
android:icon="#drawable/ic_info_blanco"
android:title="#string/tutorial"
android:textColor="#color/blanco"
jsmovil:showAsAction="always"
/>
</menu>
Result
I know may be duplicate but i am not finding any solution for that.
Actually, i want to show menu with text and icon inside fragment which having a toolbar, i have just add one line in fragment to show menu is
class JustTry : Fragment(){
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater?.inflate(R.layout.fragment_try, container, false)
}
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
var mToolbar = view!!.findViewById<Toolbar>(R.id.toolbar)
mToolbar.inflateMenu(R.menu.dashboard_menu)
}
}
I got this output from this code.
here is my menu 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/nav_home"
android:icon="#mipmap/ic_launcher"
android:title="Home" />
<item
android:id="#+id/nav_messages"
android:icon="#mipmap/ic_launcher"
android:title="Messages" />
</menu>
My question is why i am not getting Icon in Message and Home items even i am adding android:icon tag.
Any help will be appreciated.
You can try
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:balloonberry="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/menu_item"
android:icon="#drawable/img_menu"
balloonberry:showAsAction="always">
<menu>
<item
android:id="#+id/btn_delete"
android:title="delete"
android:icon="#android:drawable/ic_delete"/>
<item
android:id="#+id/btn_message"
android:title="Message"
android:icon="#android:drawable/ic_dialog_alert"/>
</menu>
</item>
</menu>
I prepared 2 xml menu files and placed inside my res/menu folder.
menu_beforeLogin.xml will be displayed if the user didn't logged in.
After they logged in, the menu item will changed to menu_afterLogin.xml.
I tried to called InflateMenu() in my onResume() method, but it ends up with keep adding the items from xml file whenever onResume() is invoked instead of removing/regenerate the menu list.
I would prefer to check user is logged in or not in onResume() method.
What is the proper way to change Navigation Drawer's list dynamically
?
MainActivity.cs
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
...
mDrawer = FindViewById<NavigationView>(Resource.Id.navigation_drawer);
...
}
protected override void OnResume ()
{
base.OnResume ();
string token = pref.GetString (Constant.PREF_TOKEN, "");
mDrawer.InflateMenu ( (token == "") ? Resource.Menu.menu_drawer_notLoggedIn : Resource.Menu.menu_drawer);
mDrawer.Invalidate ();
...
}
layout/main.axml
<android.support.v4.widget.DrawerLayout>
<android.support.design.widget.CoordinatorLayout>
...
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigation_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#drawable/menu_background"
app:headerLayout="#layout/drawer_header" />
</android.support.v4.widget.DrawerLayout>
res/menu/menu_beforeLogin.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/navigation_login"
android:icon="#drawable/navigation_login"
android:title="#string/navigation_login" />
<item
android:id="#+id/navigation_notice"
android:icon="#drawable/navigation_notice"
android:title="#string/navigation_notice" />
<item
android:id="#+id/navigation_contactUs"
android:icon="#drawable/navigation_contactUs"
android:title="#string/navigation_contactUs" />
</menu>
res/menu/menu_afterLogin.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/navigation_notice"
android:icon="#drawable/navigation_notice"
android:title="#string/navigation_notice" />
<item
android:id="#+id/navigation_profile"
android:icon="#drawable/navigation_profile"
android:title="#string/navigation_profile" />
<item
android:id="#+id/navigation_contactUs"
android:icon="#drawable/navigation_contactUs"
android:title="#string/navigation_contactUs" />
<item
android:id="#+id/navigation_logout"
android:icon="#drawable/navigation_logout"
android:title="#string/navigation_logout" />
</menu>
Add this method to clear your menu item before inflating new menu.
mDrawer.Menu.Clear ();