I'm trying to implement the new Android Navigation Component in an existing app.
I have 2 fragments that are identical except for their name. When I set the startDestination to fragment2, the fragment seems to be shown correctly. When the startDestination is set to fragment1, I don't see the inflated view but I do see the "Fragment 1 created" toast.
What am I doing incorrectly?
class Fragment1 : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
Toast.makeText(context, "Fragment 1 created", Toast.LENGTH_LONG).show()
return inflater.inflate(R.layout.fragment1, container, false)
}
}
class Fragment2 : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
Toast.makeText(context, "Fragment 2 created", Toast.LENGTH_LONG).show()
return inflater.inflate(R.layout.fragment2, container, false)
}
}
nav_graph.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/nav_graph"
app:startDestination="#id/fragment1">
<fragment
android:id="#+id/fragment1"
android:name="com.package.anotherpackage.ui.Fragment1"
android:label="fragment1"
tools:layout="#layout/fragment1"/>
<fragment
android:id="#+id/fragment2"
android:name="com.package.anotherpackage.ui.Fragment2"
android:label="fragment2"
tools:layout="#layout/fragment2"/>
</navigation>
MainActivity layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/background_light"
tools:context=".MainActivity">
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="#navigation/nav_graph"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</FrameLayout>
Fragment1 Layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
tools:context=".ui.Fragment1"
>
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="fragment 1"
/>
</FrameLayout>
Dependencies:
//Navigation
def nav_version = "1.0.0-alpha05"
implementation "android.arch.navigation:navigation-fragment-ktx:$nav_version"
implementation "android.arch.navigation:navigation-ui-ktx:$nav_version"
// optional - Test helpers
androidTestImplementation "android.arch.navigation:navigation-testing-ktx:$nav_version"
I had a layout in another library in my project with the name "fragment1.xml".
It must have been conflicting with the other layout I was trying to inflate in Fragment1. Renaming the Fragment1 layout fixed the issue.
Related
I have an app using Android Navigation (single activity many fragments).
When launched, the app displays a loading screen, an optional "news"-type screen which returns the user to the home screen when they're done, then a home screen.
However, I'm having trouble getting accessibility to pick up the home screen. When the news screen isn't shown, it'll get focused fine, but when it is included, the home screen will not receive focus, which seems to remain on the loading screen.
I've been able to reproduce this in a minimal example, with screens "Loading", "A", and "B". The app behaviour here is:
Launch on Main Fragment
wait 5 seconds, navigate to fragment A
user presses "continue"
return to Main Fragment
Wait 5 seconds, navigate to fragment B
After each navigation, I'd expect the text element to be focused, and read out. However, for fragment B, it isn't.
Things I've tried:
Using <requestFocus /> in fragment B
Requesting focus in code
Setting the importantForAccessibility state of the "Loading" fragment just before navigating away
If I change the loading fragment to use buttons for navigation, instead of the automatic behaviour, the focus does pass correctly, but obviously doesn't provide the right experience.
class LoadingFragment : Fragment() {
private lateinit var rootView: View
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = inflater.inflate(R.layout.fragment_main, container, false).also {
rootView = it
}
private var beenHereBefore = false
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Mimic a delayed loading process
Handler(Looper.getMainLooper()).postDelayed({
// Navigate to the correct screen, based on state
findNavController().navigate(
if (beenHereBefore) {
R.id.action_mainFragment_to_fragmentB
} else {
beenHereBefore = true
R.id.action_mainFragment_to_fragmentA
}
)
}, 5000)
}
}
fragment_main.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:id="#+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.LoadingFragment">
<TextView
android:id="#+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MainFragment"
android:textColor="#color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
class FragmentA : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = inflater.inflate(R.layout.fragment_a, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.findViewById<Button>(R.id.button).setOnClickListener {
findNavController().popBackStack()
}
}
}
fragment_a.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">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fragment A"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="308dp"
android:text="Continue"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout>
class FragmentB : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = inflater.inflate(R.layout.fragment_b, container, false)
}
fragment_b.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">
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fragment B"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
main_graph.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_graph"
app:startDestination="#id/mainFragment">
<fragment
android:id="#+id/mainFragment"
android:name="com.example.navigationtestapp.ui.main.LoadingFragment"
android:label="fragment_main"
tools:layout="#layout/fragment_main" >
<action
android:id="#+id/action_mainFragment_to_fragmentA"
app:destination="#id/fragmentA" />
<action
android:id="#+id/action_mainFragment_to_fragmentB"
app:destination="#id/fragmentB" />
</fragment>
<fragment
android:id="#+id/fragmentA"
android:name="com.example.navigationtestapp.ui.main.FragmentA"
android:label="FragmentA" />
<fragment
android:id="#+id/fragmentB"
android:name="com.example.navigationtestapp.ui.main.FragmentB"
android:label="FragmentB" />
</navigation>
If I were you will try to handle the accessibility focus using the accessibility API and not the requestFocus. You've mentioned that the the focus seems to be held by the loading screen, so this should work due that the a11y focus will follow it, but I will try to handle that using the sendAccessibilityEvent method
https://developer.android.com/reference/android/view/accessibility/AccessibilityEventSource#sendAccessibilityEvent(int)
// Moving a11y focus from btn1 to btn 2
btn1 = (Button) findViewById(R.id.screen3_btn1);
btn2 = (Button) findViewById(R.id.screen3_btn2);
btn1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
btn2.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
});
Excellent answer about this: Android - Set TalkBack accessibility focus to a specific view
Hope this helps
While creating bottom navigation with the jetpack navigation component the code below would work for an activity
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHostFragment.navController
findViewById<BottomNavigationView>(R.id.bottom_nav).setupWithNavController(navController)
with that, while working inside with fragments you need to call .setupWithNavController and pass in the navController and all should be fine.
But in my case with a navgraph inside the fragments XML and bottom navigation specified the app build but its only stuck in the home screen.
MainFragment.kt
class MainFragment : Fragment() {
private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentMainBinding.inflate(inflater, container, false)
NavigationUI.setupWithNavController(binding.bottomNav,findNavController())
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
fragment_main.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.MainFragment">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_nav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/bottom_navigation_menu" />
<fragment
android:id="#+id/main_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
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/main_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
main_graph.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_gragh"
app:startDestination="#id/homeFragment">
<fragment
android:id="#+id/homeFragment"
android:name="io.github.jerrymatera.medstab.ui.home.HomeFragment"
android:label="fragment_home"
tools:layout="#layout/fragment_home" />
<fragment
android:id="#+id/appointmentFragment"
android:name="io.github.jerrymatera.medstab.ui.appointment.AppointmentFragment"
android:label="appointment_fragment"
tools:layout="#layout/appointment_fragment" />
<fragment
android:id="#+id/chatFragment"
android:name="io.github.jerrymatera.medstab.ui.chat.ChatFragment"
android:label="chat_fragment"
tools:layout="#layout/chat_fragment" />
<fragment
android:id="#+id/profileFragment"
android:name="io.github.jerrymatera.medstab.ui.profile.ProfileFragment"
android:label="profile_fragment"
tools:layout="#layout/profile_fragment" />
</navigation>
menu/bottom_navigation_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/mainFragment"
android:icon="#drawable/ic_home_24"
android:title="#string/home" />
<item
android:id="#+id/appointmentFragment"
android:enabled="true"
android:icon="#drawable/ic_date_range_24"
android:title="#string/appointments" />
<item
android:id="#+id/chatFragment"
android:enabled="true"
android:icon="#drawable/ic_chat_24"
android:title="#string/chat" />
<item
android:id="#+id/profileFragment"
android:enabled="true"
android:icon="#drawable/ic_account_box_24"
android:title="#string/profile" />
</menu>
In menu resource of NavigationView (menu/bottom_navigation_menu.xml) each item ID must be matching with fragment ID in navigation graph(main_graph.xml). By this NavigationUI will figure out mapping between item and destination and it will perform fragment transaction on item selection.
change
android:id="#+id/mainFragment"
to
android:id="#+id/homeFragment"
in menu/bottom_navigation_menu.xml
Maybe the problem is in MainFragment.kt but I don't know the exact reason
NavigationUI.setupWithNavController(binding.bottomNav,findNavController())
require BottomNavigationView and NavController
I have an activity with BottomNavigationView. On navigation I show/hide two fragments one of which is empty fragment, another contains collapsing toolbar which has set android:fitsSystemWindows="true" .
The problem is - when I open collapsing fragment tab and navigate back to empty fragment, the bottom navigation view moving down (out of device screen).
The problem doesn't appear, when I don't set fitSystemWindows true or when I create a new fragment every time user changes tab. But I need to keep both.
Is there a solution to escape this?
Here is the sample code, which behaves so
Activity
class BottomNavigationActivity : AppCompatActivity() {
private var currentFragment: Fragment? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_bottom_navigation)
val bottomNavigationView = findViewById(R.id.activity_navigation__bottom_bar) as BottomNavigationView
bottomNavigationView.setOnNavigationItemSelectedListener {
when (it.itemId) {
R.id.action_blank -> openFragment(findFragment("blank")?:BlankFragment(), "blank")
R.id.action_collapsed -> openFragment(findFragment("collapsing")?:CollapsingFragment(), "collapsing")
}
return#setOnNavigationItemSelectedListener true
}
}
private fun openFragment(fragment: Fragment, tag: String) {
val fragmentTransaction = supportFragmentManager.beginTransaction()
currentFragment?.let {
fragmentTransaction.hide(it)
}
if (!fragment.isAdded) {
fragmentTransaction.add(R.id.container, fragment, tag);
}
if (!fragment.isVisible) {
fragmentTransaction.show(fragment)
}
currentFragment = fragment
fragmentTransaction.commitAllowingStateLoss()
}
private fun findFragment(tag: String): Fragment? {
return supportFragmentManager.findFragmentByTag(tag)
}
}
Activity layout xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignBottom="#id/activity_navigation__bottom_bar"/>
<android.support.design.widget.BottomNavigationView
android:id="#+id/activity_navigation__bottom_bar"
android:background="#color/colorPrimary"
android:layout_width="match_parent"
app:menu="#menu/menu"
android:layout_height="56dp"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
the empty Fragment
class BlankFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_blank, container, false)
}
}
empty fragment layout xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
tools:context=".BlankFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="blank fragment"/>
</FrameLayout>
the collapsing Fragment
class CollapsingFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_collapsing, container, false)
}
}
collapsing fragment layout xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="#+id/fragment_collapsing_toolbar__appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/fragment_collapsing_toolbar__container"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="?android:attr/windowBackground"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
android:fitsSystemWindows="true">
<android.support.v7.widget.Toolbar
android:id="#+id/fragment_collapsing_toolbar__toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="collapsing fragment"
app:titleMarginStart="72dp"
app:titleMarginEnd="72dp"
app:layout_collapseMode="pin"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/fragment_collapsing_toolbar__content"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.design.widget.CoordinatorLayout>
here is the menu
<?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/action_blank"
android:enabled="true"
android:title="blank"
app:showAsAction="ifRoom" />
<item
android:id="#+id/action_collapsed"
android:enabled="true"
android:title="collapsing"
app:showAsAction="ifRoom" />
</menu>
Thanks.
I am applying navigation library to my project.
And I get this error:
android.view.InflateException: Binary XML file line #23: Binary XML file line #23: Error inflating class fragment
This is MainActivity.kt:
val fragmentManager = supportFragmentManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if(savedInstanceState == null){
fragmentManager.beginTransaction().add(R.id.nav_host_fragment, InitFragment()).commit()
}else{
}
}
This is activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000"
android:tint="#555"
tools:context="com.example.view.main.MainActivity">
<ImageView
android:id="#+id/iv_flame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" />
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph"/>
</RelativeLayout>
</layout>
This is InitFragment.kt
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
var binding = DataBindingUtil.inflate<FragmentInitBinding>(inflater, R.layout.fragment_init, container, false)
binding!!.initVm = InitViewModel(this#InitFragment)
var view = binding.root
return view
}
this is fragment_init.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:bind="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="initVm"
type="com.example.vm.InitViewModel" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/transparent"
tools:context=".view.main.fragment.LoginFragment">
</layout>
I don't see any problem with this code. Is there any extra job I have to implement for this? I am using Data Binding. But I don't think I need to it for MainActivity.kt.
MainActivity.kt contains all the fragments. And initFragment.kt will be the first navigation that has menu to navigate.
What should I do?
Edit: In case of JAVA and NOT KOTLIN
after setContentView()
add
Fragment fragment = findViewById(R.id.nav_host_fragment);
Basically an initialization error.
AccountActivity :
class AccountActivity : AppCompatActivity(){
private lateinit var activityAccountBinding: ActivityAccountBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ViewDataBinding>(this,
R.layout.activity_account)
setDataBinder(binding)
setup()
}
override fun setDataBinder(viewDataBinding: ViewDataBinding) {
activityAccountBinding = viewDataBinding as ActivityAccountBinding
// to getting events in this file(Click event)
activityAccountBinding.accountActivity = this
}
override fun setup() {
}
}
activity_account:-
<?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">
<data>
<variable
name="accountActivity"
type="com.app.presentation.myaccount.activity.AccountActivity"
/>
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/red_fd3d50">
<fragment
android:id="#+id/fragmentContainer"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
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/my_account_graph"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
my_account_graph:-
<?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/my_account_graph"
app:startDestination="#id/profileFragment">
<fragment
android:id="#+id/profileFragment"
android:name="com.app.presentation.myaccount.ProfileFragment"
android:label="ProfileFragment"
tools:layout="#layout/fragment_profile" />
</navigation>
I'm trying to add a fragment within a subclass of DialogFragment. I have a FrameLayout with an id pref_container that I want to replace with a fragment called settingsFragment.
The problem is that fragmentTransaction can't find R.id.pref_container, I don't know if this is because pref_container is only inflated in onCreateView rather than being part of the activity?
I am very new to Android programming, so thank you for your time.
class QuestionnaireDialog : DialogFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
this.setStyle(DialogFragment.STYLE_NORMAL, R.style.AppTheme)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.questionnaire_layout,container,true)
val settingsFragment = ExercisesOnlySettingsFragment()
val ft = fragmentManager?.beginTransaction()
/// **** Here fragmentTransaction can't find R.id.pref_container because it's inflated later and not loaded as part of the activity? ****
ft?.add(R.id.pref_container, settingsFragment)
ft?.commit()
return view
}
}
The runtime error I get is
No view found for id 0x7f09009c (com.lescadeaux.kegel:id/pref_container) for fragment ExercisesOnlySettingsFragment{4ba4b89 #1 id=0x7f09009c}
Here is relavent part of my XML for questionnaire_layout
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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"
android:id="#+id/questionnaireLayout"
android:background="#android:color/background_light">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/scrollView"
app:layout_constraintTop_toBottomOf="#+id/textView5"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="#+id/button"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginEnd="8dp"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<!-- RELAVENT PART -->
<FrameLayout
android:layout_width="300dp"
android:layout_height="match_parent"
android:id="#+id/pref_container">
</FrameLayout>
<!-- RELAVENT PART -->
</LinearLayout>
</HorizontalScrollView>
</android.support.constraint.ConstraintLayout>
Please try to use getChildFragmentManager() (or its kotlin equivalent) instead of getFragmentManager() you are using - it will work.