Created an app using Kotlin for the bottom navigation component but after launching it crashes each time.
MainActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val bottomNav = findViewById<BottomNavigationView>(R.id.bottomNavigationView)
val fragmentContainer = findViewById<View>(R.id.fragmentContainer)
bottomNav.setupWithNavController(fragmentContainer.findNavController())
}
}
navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<navigation 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/navigation"
app:startDestination="#id/kotlinFragment">
<fragment
android:id="#+id/kotlinFragment"
android:name="com.example.bottomnavigation.ui.KotlinFragment"
android:label="fragment_kotlin"
tools:layout="#layout/fragment_kotlin" />
<fragment
android:id="#+id/javaFragment"
android:name="com.example.bottomnavigation.ui.JavaFragment"
android:label="fragment_java"
tools:layout="#layout/fragment_java" />
<fragment
android:id="#+id/flutterFragment"
android:name="com.example.bottomnavigation.ui.FlutterFragment"
android:label="fragment_flutter"
tools:layout="#layout/fragment_flutter" />
</navigation>
bottomnav.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:title="#string/kotlin"
android:id="#+id/kotlinFragment"
android:icon="#drawable/code"/>
<item
android:title="#string/java"
android:id="#+id/javaFragment"
android:icon="#drawable/code"/>
<item
android:title="#string/flutter"
android:id="#+id/flutterFragment"
android:icon="#drawable/code"/>
</menu>
Error after crash
E/libc: Access denied finding property "ro.odm.prev.product.name"
I/Perf: Connecting to perf service.
E/Perf: perftest packageName : com.example.bottomnavigation App is allowed to use Hide APIs
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
E/libEGL: Invalid file path for libcolorx-loader.so
E/MultiApp.Impl: OplusMultiAppImpl
D/AppCompatDelegate: Checking for metadata for AppLocalesMetadataHolderService : Service not found
I/oplus.android.OplusFrameworkFactoryImpl: getOplusRedPacketManager
W/ottomnavigatio: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
W/ottomnavigatio: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
E/OplusCustomizeRestrictionManager: sInstance is null, start a new sInstance
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.bottomnavigation, PID: 9514
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.bottomnavigation/com.example.bottomnavigation.MainActivity}: java.lang.IllegalStateException: View androidx.fragment.app.FragmentContainerView{13e6350 V.E...... ......I. 0,0-0,0 #7f0800c5 app:id/fragmentContainer} does not have a NavController set
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3729)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3896)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:140)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:100)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2326)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:263)
at android.app.ActivityThread.main(ActivityThread.java:8296)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1006)
Caused by: java.lang.IllegalStateException: View androidx.fragment.app.FragmentContainerView{13e6350 V.E...... ......I. 0,0-0,0 #7f0800c5 app:id/fragmentContainer} does not have a NavController set
at androidx.navigation.Navigation.findNavController(Navigation.kt:71)
at androidx.navigation.ViewKt.findNavController(View.kt:28)
at com.example.bottomnavigation.MainActivity.onCreate(MainActivity.kt:18)
at android.app.Activity.performCreate(Activity.java:8153)
at android.app.Activity.performCreate(Activity.java:8137)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1310)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3698)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3896)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:140)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:100)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2326)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:263)
at android.app.ActivityThread.main(ActivityThread.java:8296)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:612)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1006)
I/Process: Sending signal. PID: 9514 SIG: 9
I made 3 menu items "kotlin", "java" & "flutter" to switch between the fragments using bottom navigation. Created the app using Android Studio (Kotlin)
Try
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navController = this.findNavController(R.id.nav_host_fragment)
// Find reference to bottom navigation view
val navView: BottomNavigationView = findViewById(R.id.bottomNavigationView)
// Hook your navigation controller to bottom navigation view
navView.setupWithNavController(navController)
}
}
and bottomnav.xml remove #+id/
<item
android:title="#string/kotlin"
android:id="#id/kotlinFragment"
android:icon="#drawable/code"/>
<item
android:title="#string/java"
android:id="#id/javaFragment"
android:icon="#drawable/code"/>
<item
android:title="#string/flutter"
android:id="#id/flutterFragment"
android:icon="#drawable/code"/>
Related
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
I want to show search icon in app bar for implementing search functionality.I have created menu resource file and inflate that in MainActivity but unable to see search icon.
Below is my code:
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/search"
android:icon="#drawable/ic_search"
android:title="Item"
app:showAsAction="always"
app:actionViewClass="androidx.appcompat.widget.SearchView"/>
</menu>
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu,menu)
return true
}
}
Someone let me know why icon is not showing.
in your Activity's onCreate add this:
setSupportActionBar(binding.IdentifierOfYourToolBarInYourMainActivityXML)
Android newbe here, I have am trying to get a menu option in the inflated menu in MainActivity to trigger a navigation to another screen, the issue I am having is finding the view of MainActivity for findNavController() ,I need it where I have put the ????, can anyone help ?
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(findViewById(R.id.toolbar))
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.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.
when (item.itemId) {
R.id.menu_settings -> {
val controller: NavController = Navigation.findNavController(????)
controller.navigate(R.id.settingsFragment)
}
else -> super.onOptionsItemSelected(item)
}
return true
}
}
<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.ebookfrenzy.sos.MainActivity">
<item
android:id="#+id/menu_settings"
android:orderInCategory="11"
android:title="#string/action_settings"
app:showAsAction="never" />
<item
android:id="#+id/menu_removeads"
android:orderInCategory="20"
android:title="#string/remove_ads"
app:showAsAction="never" />
<item
android:id="#+id/menu_about"
android:orderInCategory="20"
android:title="#string/about"
app:showAsAction="never"/>
As advised in the documentation to do this you require one of the following:
Fragment.findNavController()
View.findNavController()
Activity.findNavController(viewId: Int)
How to use the above information:
Your code is located in MainActivity so the function you have to call is the 3rd Activity.findNavController(viewId: Int) the ???? is the viewId.
What is the viewId:
viewId is R.id.theIdentifierYouSetInYourXML so you have to navigate in your code to the layout you set in method setContentView this layout is called R.layout.activity_main or in xml words activity_main.xml. Within this file there should be something like the following:
<?xml version="1.0" encoding="utf-8"?>
<!-- irrelevant code -->
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
...
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph" />
<!-- irrelevant code -->
The FragmentContainerView is important here. We require its id. In my example case above the answer will be R.id.nav_host_fragment.
Putting all together:
Navigation.findNavController(????) will be Activity.findNavController(R.id.nav_host_fragment) but you have to check your code in activity_main.xml to find your own id.
If you don't have this code in your activity_main.xml then I would suggest to start from here.
I am trying to use a SearchView in my actionbar (for only one fragment) but the SearchView keeps on returning null.
fragment
import android.os.Bundle
import android.view.*
import androidx.appcompat.widget.SearchView
import androidx.fragment.app.Fragment
import com.StockMarketAlarms.StockAlarm.R
import com.google.firebase.auth.FirebaseAuth
class SearchFragment : Fragment() {
private lateinit var auth: FirebaseAuth
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_search, container, false)
setHasOptionsMenu(true)
return root
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.search_menu, menu)
val searchView: SearchView = menu.findItem(R.id.menuitem_search) as SearchView
searchView.setMaxWidth(Int.MAX_VALUE)
}
}
its loaded in a tabactivity that extends AppCompatActivity
The search menu looks like this
search_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"
xmlns:tools="http://schemas.android.com/tools">
<android.support.v7.widget.SearchView
android:id="#+id/menuitem_search"
android:icon="#drawable/search_black_48"
app:actionViewClass="android.widget.SearchView"
android:title="#string/title_search"
app:searchIcon="#drawable/search_black_48"
app:showAsAction="collapseActionView|ifRoom"
app:queryBackground="#color/colorWhite"
app:iconifiedByDefault="false" />
</menu>
I dont understand why it returns null, I tried a lot.
Process: com.jfvh.stockalarm, PID: 1845
kotlin.TypeCastException: null cannot be cast to non-null type androidx.appcompat.widget.SearchView
at com.jfvh.stockalarm.activities.fragments.SearchFragment.onCreateOptionsMenu(SearchFragment.kt:48)
at androidx.fragment.app.Fragment.performCreateOptionsMenu(Fragment.java:2711)
at androidx.fragment.app.FragmentManagerImpl.dispatchCreateOptionsMenu(FragmentManagerImpl.java:2711)
at androidx.fragment.app.Fragment.performCreateOptionsMenu(Fragment.java:2713)
at androidx.fragment.app.FragmentManagerImpl.dispatchCreateOptionsMenu(FragmentManagerImpl.java:2711)
at androidx.fragment.app.FragmentController.dispatchCreateOptionsMenu(FragmentController.java:386)
at androidx.fragment.app.FragmentActivity.onCreatePanelMenu(FragmentActivity.java:326)
at androidx.appcompat.view.WindowCallbackWrapper.onCreatePanelMenu(WindowCallbackWrapper.java:94)
at androidx.appcompat.app.AppCompatDelegateImpl$AppCompatWindowCallback.onCreatePanelMenu(AppCompatDelegateImpl.java:2830)
at androidx.appcompat.app.AppCompatDelegateImpl.preparePanel(AppCompatDelegateImpl.java:1746)
at androidx.appcompat.app.AppCompatDelegateImpl.doInvalidatePanelMenu(AppCompatDelegateImpl.java:2026)
at androidx.appcompat.app.AppCompatDelegateImpl$2.run(AppCompatDelegateImpl.java:260)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
search_menu.xml has an error.
It should be:
<?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">
<!-- tag name should be <item> -->
<item
android:id="#+id/menuitem_search"
android:icon="#drawable/search_black_48"
app:actionViewClass="android.widget.SearchView"
android:title="#string/title_search"
app:searchIcon="#drawable/search_black_48"
app:showAsAction="collapseActionView|ifRoom"
app:queryBackground="#color/colorWhite"
app:iconifiedByDefault="false"/>
</menu>
Source: https://developer.android.com/training/search/setup#add-sv
Menus allow only two tags <group>, <item>:
And for action view class you can select basically anything. Note, that actionViewClass attribute uses app namespace prefix:
UPDATE
I noticed one more problem, that is in your fragment. When you find menu item by its id it does not return you an action view, instead what you get is MenuItem instance. It cannot be casted to any kind of View.
To fix this issue you should get the value of actionView attribute of MenuItem object.
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.search_menu, menu)
// `.actionView` was missing
val searchView: SearchView = menu.findItem(R.id.menuitem_search).actionView as SearchView
searchView.setMaxWidth(Int.MAX_VALUE)
}
please help. i got this error but don't know what is going on. i tried to make a search view in my fragment.
i make this code for menu item
<item
android:id="#+id/action_search"
android:icon="#drawable/ic_search"
android:title="search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="ifRoom|collapseActionView" />
and make this code in my fragment
override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) {
menu?.clear()
inflater?.inflate(R.menu.menu_home, menu)
val searchItem = menu?.findItem(R.id.action_search)
val searchView = MenuItemCompat.getActionView(searchItem) as SearchView
searchView.backgroundColorResource = Color.WHITE
searchView.queryHint = "Search Review Title"
searchView.setOnQueryTextListener(object: SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
presenter.getSearchReviewList(query)
return true
}
override fun onQueryTextChange(query: String?): Boolean {
presenter.getSearchReviewList(query)
return true
}
})
super.onCreateOptionsMenu(menu, inflater)
}
but i got this error
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.mqa.android.moviereview, PID: 22280
android.content.res.Resources$NotFoundException: Resource ID #0xffffffff
at android.content.res.ResourcesImpl.getValue(ResourcesImpl.java:204)
at android.content.res.Resources.getColor(Resources.java:949)
at android.content.res.Resources.getColor(Resources.java:925)
at org.jetbrains.anko.CustomViewPropertiesKt.setBackgroundColorResource(CustomViewProperties.kt:36)
at com.mqa.android.moviereview.module.fragment.home.HomeFragment.onCreateOptionsMenu(HomeFragment.kt:97)
at android.support.v4.app.Fragment.performCreateOptionsMenu(Fragment.java:2561)
at android.support.v4.app.FragmentManagerImpl.dispatchCreateOptionsMenu(FragmentManager.java:3321)
at android.support.v4.app.FragmentController.dispatchCreateOptionsMenu(FragmentController.java:331)
at android.support.v4.app.FragmentActivity.onCreatePanelMenu(FragmentActivity.java:379)
at android.support.v7.view.WindowCallbackWrapper.onCreatePanelMenu(WindowCallbackWrapper.java:94)
at android.support.v7.app.AppCompatDelegateImpl$AppCompatWindowCallback.onCreatePanelMenu(AppCompatDelegateImpl.java:2549)
at android.support.v7.app.AppCompatDelegateImpl.preparePanel(AppCompatDelegateImpl.java:1589)
at android.support.v7.app.AppCompatDelegateImpl.doInvalidatePanelMenu(AppCompatDelegateImpl.java:1869)
at android.support.v7.app.AppCompatDelegateImpl$2.run(AppCompatDelegateImpl.java:227)
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)
please help me what is going on
searchView.backgroundColorResource = Color.WHITE is the problem. You need to set a resource id here but Color.WHITE is a color value, not a resource id. You can try
searchView.backgroundColorResource = android.R.color.white
You're using a Color value, not a resource reference, so you can't use
searchView.backgroundColorResource = Color.WHITE
As an alternative to Henry's answer, you can use the old Java-style method with
searchView.setBackgroundColor(Color.WHITE)
Use
getApplicationContext().getColor(R.color.white);
And put your color values in xml file, such as
res/values/colors.xml
looking like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="white">#ffffff</color>
//other colors...
</resources>