I'm trying develope single-activity application using the navigation to corresponding fragment from my home fragment under certain conditions (see my code fragment below). But when I start application with the condition isLoggedIn == true, an exception appears:
2022-05-01 17:42:22.888 14974-14974/com.example.shercofaqapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.shercofaqapp, PID: 14974
java.lang.IllegalStateException: Fragment LoginFragment{d69320f} (2bebfc01-ce4e-435e-be4f-821b5d142eb8 id=0x7f0a0096) did not return a View from onCreateView() or this was called before onCreateView().
at androidx.fragment.app.Fragment.requireView(Fragment.java:2008)
at com.example.shercofaqapp.view.LoginFragment.onCreateView(LoginFragment.kt:47)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2995)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:523)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:2777)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3020)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:551)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2784)
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:262)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:478)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1425)
at android.app.Activity.performStart(Activity.java:7825)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3294)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
This is a fragment of my code:
package com.example.shercofaqapp.view
import android.content.Context
import android.os.Bundle
import android.text.TextUtils
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.navigation.Navigation
import com.example.shercofaqapp.R
import com.example.shercofaqapp.databinding.FragmentLoginBinding
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.FirebaseUser
import kotlin.properties.Delegates
class LoginFragment : Fragment() {
lateinit var binding: FragmentLoginBinding
private var isLoggedIn by Delegates.notNull<Boolean>()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val sharedPref = requireActivity()
.getSharedPreferences("MyPreferences", Context.MODE_PRIVATE)
val editor = sharedPref.edit()
var isLoggingIn = false
binding = DataBindingUtil.inflate(
inflater, R.layout.fragment_login, container, false)
binding.apply {
//Log in / sign up logic
isLoggedIn = sharedPref.getBoolean("isLoggedIn", false)
if (isLoggedIn) {
Navigation.findNavController(requireView())
.navigate(R.id.action_loginFragment_to_garageFragment)
}
}
return binding.root
}
}
The question is: how can I get view for Navigation before onCreateView() return it?
I tried to use this solution, but I don't understand what argument I should pass to .findNavController(...) in my case.
P.S. NavHostFragment is in MainActivity:
<?xml version="1.0" encoding="utf-8"?>
<layout
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=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/containerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph" />
</layout>
As per the Navigate to a destination documentation, you should use the findNavController() Kotlin extension on Fragment, which is a convenience wrapper around calling NavHostFragment.findNavController(this):
binding.apply {
//Log in / sign up logic
isLoggedIn = sharedPref.getBoolean("isLoggedIn", false)
if (isLoggedIn) {
// Make sure to:
// 1. Add a dependency on navigation-fragment-ktx in your build.gradle
// 2. import androidx.navigation.fragment.findNavController
findNavController()
.navigate(R.id.action_loginFragment_to_garageFragment)
}
}
findNavController(requireActivity())
.navigate(R.id.action_loginFragment_to_garageFragment)
use this code of line, I think it is helpful for you
Edit : If you are using it in fragment then,
Navigation.findNavController(getView()).navigate(R.id.action_loginFragment_to_garageFragment)
Related
I am learning MVVM and have run into an issue, and I am getting the following errors:
Resources$NotFoundException: File res/layout/fragment_list.xml from xml type layout resource ID #0x7f0b002f
and
Failed to open file '/data/data/software.genau.dogs/code_cache/.overlay/base.apk/res/layout/fragment_list.xml': No such file or directory
I know the file exists in my layout, and there are no errors or warnings listed for the fragment_list.xml file. In the design view, everything is laid out the way I want and it looks correct.
To try and correct the issue I've tried some of the basic things like clean project and rebuilding, and restarted the program (and my machine). Also, I've tried different ways to override fun onCreateView() with and without binding.
I would appreciate some help.
Here is the MVVM layout:
pic from Android studio folder layout
Here is my code for ListFragment.kt:
package software.genau.dogs.view
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.navigation.Navigation
import androidx.recyclerview.widget.LinearLayoutManager
import software.genau.dogs.R
import software.genau.dogs.databinding.FragmentListBinding
import software.genau.dogs.viewmodel.ListViewModel
class ListFragment : Fragment() {
private lateinit var binding: FragmentListBinding
private lateinit var viewModel: ListViewModel
private val dogsListAdapter = DogsListAdapter(arrayListOf())
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_list, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProviders.of(this).get(ListViewModel::class.java)
viewModel.refresh()
binding.dogsList.apply {
layoutManager = LinearLayoutManager(context)
adapter = dogsListAdapter
}
observeViewModel()
}
fun observeViewModel() {
viewModel.dogs.observe(viewLifecycleOwner, Observer { dogs ->
dogs?.let {
binding.dogsList.visibility = View.VISIBLE
dogsListAdapter.updateDogList(dogs)
}
})
viewModel.dogsLoadError.observe(viewLifecycleOwner, Observer { isError ->
isError?.let {
binding.listError.visibility = View.VISIBLE
}
})
viewModel.loading.observe(viewLifecycleOwner, Observer { isLoading ->
isLoading?.let {
binding.progressBar.visibility = if (it) View.VISIBLE else View.INVISIBLE
if (it) {
binding.listError.visibility = View.INVISIBLE
binding.dogsList.visibility = View.INVISIBLE
}
}
})
}
}
Here is the code for fragment_list.xml:
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/refreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/dogsList"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.recyclerview.widget.RecyclerView>
<TextView
android:id="#+id/listError"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/list_fragment_error_msg"
app:layout_constraintBottom_toBottomOf="#+id/dogsList"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/dogsList" />
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="#+id/dogsList"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="#+id/dogsList" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</layout>
Here is MainActivity.kt:
package software.genau.dogs.view
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.NavAction
import androidx.navigation.NavController
import androidx.navigation.Navigation
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.NavigationUI
import software.genau.dogs.R
import software.genau.dogs.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragmentContainerView) as NavHostFragment
navController = navHostFragment.navController
NavigationUI.setupActionBarWithNavController(this, navController)
}
override fun onSupportNavigateUp(): Boolean {
return NavigationUI.navigateUp(navController, null)
}
}
Here is activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/fragmentContainerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="1dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="1dp"
android:layout_marginBottom="1dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/dog_navigation"
tools:layout="#layout/fragment_list" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Here are the errors from logcat:
2021-11-17 12:29:08.420 12809-12809/software.genau.dogs E/ware.genau.dog: Failed to open file '/data/data/software.genau.dogs/code_cache/.overlay/base.apk/res/layout/fragment_list.xml': No such file or directory
2021-11-17 12:29:08.420 12809-12809/software.genau.dogs D/AndroidRuntime: Shutting down VM
2021-11-17 12:29:08.425 12809-12809/software.genau.dogs E/AndroidRuntime: FATAL EXCEPTION: main
Process: software.genau.dogs, PID: 12809
android.content.res.Resources$NotFoundException: File res/layout/fragment_list.xml from xml type layout resource ID #0x7f0b002f
at android.content.res.ResourcesImpl.loadXmlResourceParser(ResourcesImpl.java:1264)
at android.content.res.Resources.loadXmlResourceParser(Resources.java:2426)
at android.content.res.Resources.loadXmlResourceParser(Resources.java:2402)
at android.content.res.Resources.getLayout(Resources.java:1252)
at android.view.LayoutInflater.inflate(LayoutInflater.java:530)
at software.genau.dogs.view.ListFragment.onCreateView(ListFragment.kt:35)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2963)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:518)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2106)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3138)
at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3065)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2988)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1647)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3128)
at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:3072)
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:251)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:502)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1435)
at android.app.Activity.performStart(Activity.java:8018)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3475)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.io.FileNotFoundException: res/layout/fragment_list.xml
at android.content.res.AssetManager.nativeOpenXmlAsset(Native Method)
at android.content.res.AssetManager.openXmlBlockAsset(AssetManager.java:1092)
at android.content.res.ResourcesImpl.loadXmlResourceParser(ResourcesImpl.java:1248)
at android.content.res.Resources.loadXmlResourceParser(Resources.java:2426)
at android.content.res.Resources.loadXmlResourceParser(Resources.java:2402)
at android.content.res.Resources.getLayout(Resources.java:1252)
at android.view.LayoutInflater.inflate(LayoutInflater.java:530)
at software.genau.dogs.view.ListFragment.onCreateView(ListFragment.kt:35)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2963)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:518)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2106)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3138)
at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3065)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2988)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1647)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3128)
at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:3072)
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:251)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:502)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1435)
at android.app.Activity.performStart(Activity.java:8018)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3475)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
I resolved this issue by making a small change in the XML (code editor) e.g changing or adding a margin to any View in the layout file.
Then I went to top menu Build -> Clean Project followed by Build -> Rebuild Project.
I think what happened is Android Studio/Gradle lost track of the changes made to the file, so it is not included when recompiling as it thinks it is there unmodified. By making a small arbitrary change to the file Gradle sees it has been modified so includes the layout as expected.
Not sure if this is the best way, but I solved my issue.
I renamed the fragment_list.xml to fragment_list2.xml
then added a new fragment_list.xml. Finally, I copied all the data from the original file to the new file.
The new fragment_list.xml is now recognized and the program is running.
This question already has answers here:
ViewPager and RecyclerView issue with fragment transition
(2 answers)
Closed 1 year ago.
ViewPager2 Caused by IllegalStateException FragmentManager is already executing transactions
Replicated Crash : while rotating screen
How to fix Viewpager2 FragmentManager is already executing transactions?
Full source code:
https://github.com/stevdza-san/ViewPager2-with-Navigation-Component-TestApp
ViewPagerFragment.kt
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.test.zigmaster.databinding.FragmentViewPagerBinding
class ViewPagerFragment : Fragment() {
var binding : FragmentViewPagerBinding?= null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
// val view = inflater.inflate(R.layout.fragment_view_pager, container, false)
binding = FragmentViewPagerBinding.inflate(inflater)
val fragmentList = arrayListOf<Fragment>(
FirstScreen(),
SecondScreen(),
ThirdScreen()
)
val adapter = ViewPagerAdapter(
fragmentList,
requireActivity().supportFragmentManager,
lifecycle
)
binding!!.viewPager.adapter = adapter
return binding!!.root
}
override fun onDestroyView() {
super.onDestroyView()
binding=null
}
}
ViewPagerAdapter.kt
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.viewpager2.adapter.FragmentStateAdapter
class ViewPagerAdapter(
list: ArrayList<Fragment>,
fm: FragmentManager,
lifecycle: Lifecycle
) : FragmentStateAdapter(fm, lifecycle) {
private val fragmentList = list
override fun getItemCount(): Int {
return fragmentList.size
}
override fun createFragment(position: Int): Fragment {
return fragmentList[position]
}
}
fragment_view_pager.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".ui.app_intro.ViewPagerFragment">
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
FirstScreen.kt
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.viewpager2.widget.ViewPager2
import com.test.zigmaster.R
import com.test.zigmaster.databinding.FragmentFirstScreenBinding
class FirstScreen : Fragment() {
private var binding : FragmentFirstScreenBinding?= null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
binding = FragmentFirstScreenBinding.inflate(inflater)
val viewPager = activity?.findViewById<ViewPager2>(R.id.viewPager)
binding!!.next.setOnClickListener {
viewPager?.currentItem = 1
}
return binding!!.root
}
override fun onDestroyView() {
super.onDestroyView()
binding=null
}
Change view.viewPager.adapter = adapter to
Handler(Looper.getMainLooper()).post {
view.viewPager.adapter = adapter
}
in https://github.com/stevdza-san/ViewPager2-with-Navigation-Component-TestApp/blob/master/app/src/main/java/com/jovanovic/stefan/mytestapp/onboarding/ViewPagerFragment.kt
Hi I have problem with Navigation drawer. I used the default layout with navigation drawer to learn how to add more. I create similar classes like this default. But these thre clases witch was at the start are working, but another witch I crated don't and when i trying click into this three "naprawa", "oc", "pt" app is crashing.In every fragment....xml i have tools:context=".ui.<folder>.<...Fragment>"with name of Fragments. Someone know where could be problem?
Also I have this errors:
Process: com.example.carplanner, PID: 23240
kotlin.UninitializedPropertyAccessException: lateinit property naprawaViewModel has not been initialized
at com.example.carplanner.ui.naprawa.NaprawaFragment.onCreateView(NaprawaFragment.kt:23)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1997)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1953)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
and this is the code :
package com.example.carplanner
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.navigation.NavigationView
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import androidx.drawerlayout.widget.DrawerLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import android.view.View
import android.content.Intent
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
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 ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
appBarConfiguration = AppBarConfiguration(setOf(
R.id.nav_home,
R.id.nav_paliwo,
R.id.nav_naprawa,
R.id.nav_wydatki,
R.id.nav_oc,
R.id.nav_pt), drawerLayout)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
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 {
val id = item.itemId
if (id == R.id.btn_settings) {
val intent = Intent(
this, SettingsActivity ::class.java)
startActivity (intent)
}else{
if (id == R.id.btn_about){
val intent = Intent(
this, About ::class.java)
startActivity (intent)
}
}
return super.onOptionsItemSelected(item)
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment)
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
}
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_home"
android:icon="#android:drawable/ic_dialog_dialer"
android:title="#string/strona_g_wna" />
<item
android:id="#+id/nav_paliwo"
android:icon="#drawable/ic_paliwo"
android:title="#string/tankowanie" />
<item
android:id="#+id/nav_naprawa"
android:icon="#drawable/ic_naprawa"
android:title="#string/naprawy" />
<item
android:id="#+id/nav_wydatki"
android:icon="#drawable/ic_wydatki"
android:title="#string/wydatki" />
<item
android:id="#+id/nav_oc"
android:icon="#drawable/ic_oc"
android:title="#string/ubezpieczenia" />
<item
android:id="#+id/nav_pt"
android:icon="#android:drawable/stat_notify_error"
android:title="#string/przegl_d_techniczny" />
</group>
</menu>
<?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/mobile_navigation"
app:startDestination="#+id/nav_home">
<fragment
android:id="#+id/nav_home"
android:name="com.example.carplanner.ui.home.HomeFragment"
android:label="Strona Główna"
tools:layout="#layout/fragment_home" />
<fragment
android:id="#+id/nav_paliwo"
android:name="com.example.carplanner.ui.paliwo.PaliwoFragment"
android:label="Paliwo"
tools:layout="#layout/fragment_paliwo" />
<fragment
android:id="#+id/nav_naprawa"
android:name="com.example.carplanner.ui.naprawa.NaprawaFragment"
android:label="Naprawy"
tools:layout="#layout/fragment_naprawa" />
<fragment
android:id="#+id/nav_wydatki"
android:name="com.example.carplanner.ui.wydatki.WydatkiFragment"
android:label="Wydatki"
tools:layout="#layout/fragment_wydatki" />
<fragment
android:id="#+id/nav_oc"
android:name="com.example.carplanner.ui.oc.OcFragment"
android:label="Ubezpieczenia"
tools:layout="#layout/fragment_oc" />
<fragment
android:id="#+id/nav_pt"
android:name="com.example.carplanner.ui.pt.PtFragment"
android:label="Przegląd techniczny"
tools:layout="#layout/fragment_pt" />
<fragment
android:id="#+id/nav_setting"
android:name="com.example.carplanner.SettingsActivity$SettingsFragment"
tools:layout="#layout/settings_activity" />
</navigation>
and the NaprawaFragment code:
package com.example.carplanner.ui.naprawa
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.example.carplanner.R
class NaprawaFragment : Fragment() {
private lateinit var naprawaViewModel: NaprawaViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
naprawaViewModel =
ViewModelProvider(this).get(naprawaViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_naprawa, container, false)
val textView: TextView = root.findViewById(R.id.text_naprawa)
naprawaViewModel.text.observe(viewLifecycleOwner, Observer {
textView.text = it
})
return root
}
}
And HomeFragment which is working properly
package com.example.carplanner.ui.home
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.example.carplanner.R
class HomeFragment : Fragment() {
private lateinit var homeViewModel: HomeViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
homeViewModel =
ViewModelProvider(this).get(HomeViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_home, container, false)
val textView: TextView = root.findViewById(R.id.text_home)
homeViewModel.text.observe(viewLifecycleOwner, Observer {
textView.text = it
})
return root
}
}
java.lang.IllegalStateException: ProfileFragmentBinding.bind(view) must not be null
at com.xx.profile.ProfileFragment.onViewCreated(ProfileFragment.kt:39)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:332)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1997)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1953)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:198)
at android.app.ActivityThread.main(ActivityThread.java:7055)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:523)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:836)
From the last few days i am getting a very weird exception and the crash is happening mainly because of DataBindingComponent, as it is returning null, with dataBinding
It's working good with ViewBinding but with databinding it's crashing
Note(Coincidently): I have 21 modules in my project including this, i got this exception at runtime for every databinding module, and if i remove any other module and make it to 20, the code excecute fine for both databinding as well as for viewbinding.
But i need this as Module, It will be great, if u guys could assist me. Thanks in advance.
I am using Navigation-Architecture component with BottomNavigationView.
My Code is as Follows,
package com.xx.profile
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.observe
import com.xx.core.dagger.ViewModelFactory
import com.xx.core.dagger.coreComponent
import com.xx.core.util.LogoutInterface
import com.xx.core.util.context.launchUrl
import com.xx.core.util.event.EventObserver
import com.xx.profile.databinding.ProfileFragmentBinding
import com.xx.profile.di.DaggerProfileComponent
import javax.inject.Inject
class ProfileFragment(private val logoutInterface: LogoutInterface) : Fragment(R.layout.profile_fragment) {
private lateinit var binding: ProfileFragmentBinding
#Inject
lateinit var viewModelFactory: ViewModelFactory
private val viewModel: ProfileViewModal by lazy {
ViewModelProvider(viewModelStore, viewModelFactory).get(ProfileViewModal::class.java)
}
override fun onAttach(context: Context) {
super.onAttach(context)
DaggerProfileComponent.factory().create(context.coreComponent()).inject(this)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = ProfileFragmentBinding.bind(view)
}
}
My xml is as follows,
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto">
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
tools:context=".ProfileFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white"
android:orientation="vertical"
android:padding="16dp"
tools:ignore="ExtraText">
</LinearLayout>
</ScrollView>
</layout>
I'm trying to set navController to bottomNavigation, but it's requires activity, the problem is my borromNavigation hosted in fragment, so i don't have activity instance.
I've tried
bottom_nav_view.setupWithNavController(findNavController())
and:
val host = Navigation.findNavController(this.activity!!.parent, R.id.my_nav_host_fragment)
bottom_nav_view.setupWithNavController(host)
home_fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".ui.fragments.home.HomeFragment">
<fragment
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="#+id/my_nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="#navigation/main_navigation"
app:defaultNavHost="true"
/>
<com.google.android.material.bottomnavigation.BottomNavigationView
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:id="#+id/bottom_nav_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="#menu/bottom_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
So, I need somehow take my_nav_host_fragment from my home_fragment.xml in HomeFragment.kt
HomeFragment.kt
package andy.schedulekpi.ui.fragments.home
import androidx.lifecycle.ViewModelProviders
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.navigation.NavController
import androidx.navigation.Navigation
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import androidx.navigation.ui.NavigationUI
import androidx.navigation.ui.setupWithNavController
import andy.schedulekpi.R
import andy.schedulekpi.ui.fragments.start.StartFragmentDirections
import kotlinx.android.synthetic.main.home_fragment.*
class HomeFragment : Fragment() {
companion object {
fun newInstance() = HomeFragment()
}
private lateinit var viewModel: HomeViewModel
private lateinit var host : NavController
val safeArgs : HomeFragmentArgs by navArgs()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.home_fragment, container, false)
//host = Navigation.findNavController(this.activity!!.parent, R.id.my_nav_host_fragment)
return view
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProviders.of(this).get(HomeViewModel::class.java)
// TODO: Use the ViewModel
Toast.makeText(this.context, safeArgs.currentWeek.toString(), Toast.LENGTH_SHORT).show()
//val navController = Navigation.findNavController(activity!!.parent, R.id.my_nav_host_fragment) - don't work
//val host = Navigation.findNavController() -ERROR
// bottom_nav_view.setupWithNavController(findNavController()) -ERROR
}
}
bottom_menu.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:icon="#drawable/ic_schedule"
android:id="#+id/scheduleFragment"
android:title="Schedule"/>
<item
android:icon="#drawable/ic_database"
android:id="#+id/archiveFragment"
android:title="Database"/>
<item
android:id="#+id/teachersFragment"
android:icon="#drawable/ic_teachers"
android:title="Teachers"/>
<item
android:id="#+id/settingsFragment"
android:icon="#drawable/ic_settings_"
android:title="Settings"/>
</menu>
main_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/main_navigation"
app:startDestination="#id/scheduleFragment">
<fragment
android:id="#+id/scheduleFragment"
android:name="andy.schedulekpi.ui.fragments.schedule.ScheduleFragment"
android:label="schedule_fragment"
tools:layout="#layout/schedule_fragment"/>
<fragment
android:id="#+id/archiveFragment"
android:name="andy.schedulekpi.ui.fragments.archive.ArchiveFragment"
android:label="archive_fragment"
tools:layout="#layout/archive_fragment"/>
<fragment
android:id="#+id/teachersFragment"
android:name="andy.schedulekpi.ui.fragments.teachers.TeachersFragment"
android:label="teachers_fragment"
tools:layout="#layout/teachers_fragment"/>
<fragment
android:id="#+id/settingsFragment"
android:name="andy.schedulekpi.ui.fragments.settings.SettingsFragment"
android:label="settings_fragment"
tools:layout="#layout/settings_fragment"/>
</navigation>
I expected to handle bottomNavigation from fragment, but now i clicked on menu items and nothing happend or error.
In HomeFragment to set navController on BottomNavigationView:
import androidx.navigation.findNavController
Navigation.setViewNavController(bottom_nav_view, activity!!.findNavController(R.id.my_nav_host_fragment))
then when u want get navController from bottom_nav_view:
bottom_nav_view.findNavController()
As said Artur Gniewowski, in HomeFragment in onActivityCreated I need just add
bottom_nav_view.setupWithNavController(activity!!.findNavController(R.id.my_nav_host_fragment))
So, now in HomeFragment i have:
package andy.schedulekpi.ui.fragments.home
import androidx.lifecycle.ViewModelProviders
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.navigation.Navigation
import androidx.navigation.findNavController
import androidx.navigation.fragment.navArgs
import androidx.navigation.ui.setupWithNavController
import andy.schedulekpi.R
import kotlinx.android.synthetic.main.home_fragment.*
import kotlinx.android.synthetic.main.home_fragment.view.*
class HomeFragment : Fragment() {
companion object {
fun newInstance() = HomeFragment()
}
private lateinit var viewModel: HomeViewModel
val safeArgs : HomeFragmentArgs by navArgs()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.home_fragment, container, false)
return view
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProviders.of(this).get(HomeViewModel::class.java)
// TODO: Use the ViewModel
//Navigation.setViewNavController(bottom_nav_view, activity!!.findNavController(R.id.my_nav_host_fragment))
bottom_nav_view.setupWithNavController(activity!!.findNavController(R.id.my_nav_host_fragment))
Toast.makeText(this.context, safeArgs.currentWeek.toString(), Toast.LENGTH_SHORT).show()
}
}
Thanks to Artur Gniewowski.