I am using fragments in my android application, when I run the program, the percentage name is displayed incorrectly, but after I switch to another fragment and perform some actions, everything becomes as it should be.
I set the title for the fragment on this line:
(activity as AppCompatActivity).supportActionBar?.title = "Soccer Quiz"
but it only applies when moving to another fragment.
My kotlin code:
package com.example.soccerquiz
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.navigation.Navigation
import com.example.soccerquiz.databinding.FragmentWelcomeScreenBinding
/**
* A simple [Fragment] subclass.
*/
class WelcomeScreenFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val binding: FragmentWelcomeScreenBinding =
DataBindingUtil.inflate(
inflater, R.layout.fragment_welcome_screen, container, false
)
binding.letsPlayButton.setOnClickListener { view: View ->
Navigation.findNavController(view)
.navigate(R.id.action_welcomeScreenFragment_to_quizFragment)
}
(activity as AppCompatActivity).supportActionBar?.title = "Soccer Quiz"
return binding.root
}
}
https://i.stack.imgur.com/LzNLk.png
https://i.stack.imgur.com/66NXk.png
Please help me with my problem.
It was necessary to change the title of fragment in navigation graph.
No need to install manually, because when you start the program it does not always work, you have to switch between fragments.
Related
I've been doing this Android Studio course and I've stumbled upon a problem with this particular method. For whatever reason, I can use it in every fragment except one, in which apparently can't be imported.
Here is the fragment: (StartFragment)
package com.example.cupcake
import android.app.Fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
import com.example.cupcake.databinding.FragmentStartBinding
/**
* This is the first screen of the Cupcake app. The user can choose how many cupcakes to order.
*/
class StartFragment : Fragment() {
// Binding object instance corresponding to the fragment_start.xml layout
// This property is non-null between the onCreateView() and onDestroyView() lifecycle callbacks,
// when the view hierarchy is attached to the fragment.
private var binding: FragmentStartBinding? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val fragmentBinding = FragmentStartBinding.inflate(inflater, container, false)
binding = fragmentBinding
return fragmentBinding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding?.apply {
// Set up the button click listeners
orderOneCupcake.setOnClickListener { orderCupcake(1) }
orderSixCupcakes.setOnClickListener { orderCupcake(6) }
orderTwelveCupcakes.setOnClickListener { orderCupcake(12) }
}
}
/**
* Start an order with the desired quantity of cupcakes and navigate to the next screen.
*/
fun orderCupcake(quantity: Int) {
findNavController().navigate(R.id.action_startFragment_to_flavorFragment) //here is the error
}
/**
* This fragment lifecycle method is called when the view hierarchy associated with the fragment
* is being removed. As a result, clear out the binding object.
*/
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
}
The whole code is in the code link, thanks
Your fragment extends android.app.Fragment - that's the deprecated, should never be used framework fragment. You need to replace your import android.app.Fragment with import androidx.fragment.app.Fragment to actually extend the AndroidX Fragment you need to use with Navigation.
I'm trying change some text after load a fragment. It will be location tracker in future. So I'm testing change of the text.
build.gradle module:
android {
buildFeatures{
dataBinding = true
viewBinding = true
}
}
start.xml:
<TextView
android:id="#+id/location"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:text="Current GPS Location"
android:textColor="#FF0000"
android:textSize="30sp"
android:textStyle="bold" />
Start.kt:
import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.databinding.DataBindingUtil.setContentView
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.example.basic.databinding.StartBinding
import android.util.Log
class Start : Fragment() {
private lateinit var binding: StartBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = StartBinding.inflate(layoutInflater)
binding.location.setText("Hello World")
}
}
Application runs without problem but setText Not works. Do you know why?
You are initializing your binding but not adding it to the view
onCreateView(inflater... container...) {
binding = StartBinding.inflate(layoutInflater, container, false)
return binding.root
}
then following the life cycle usage previous to binding, you have to make the change after the view is created
onViewCreated(...) {
binding.location.setText("Hello World")
}
A small comment, your naming doesn't follow conventions:
StartFragment
fragment_start
You should do the binding in onCreateView instead of onCreate as in onCreate() the fragment view is not created yet.
So transfer below in onCreateView
binding = StartBinding.inflate(layoutInflater)
binding.location.setText("Hello World")
For more info check fragment lifecycle
Thanks for answers!
Solution is very simple.
Here is solution for people who will find this question:
class Start : Fragment() {
lateinit var binding : StartBinding //this must be at the begin of your class
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = StartBinding.inflate(layoutInflater,container,false) //this must be here in onCreateView
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.textView.setText("Hello World") // and now setText works in onViewCreated
}
}
So I'm trying to create a tabbed app in Kotlin and I have chosen the default one they made for you to practice but I can't figure out how to get the buttons working `
package com.example.android_app.ui.home
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import com.example.android_app.R
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.fragment_home.*
class HomeFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//Program Buttons
logout.setOnClickListener{
val intent = Intent(this, sign_in::class.java)
startActivity(intent)
}
}
private lateinit var homeViewModel: HomeViewModel
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
homeViewModel =
ViewModelProviders.of(this).get(HomeViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_home, container, false)
homeViewModel.text.observe(viewLifecycleOwner, Observer {
})
return root
}
}
`
As far as I know this should work. The problem is not in the button but in Intent. My button is already defined and has no errors but there is a red line under Intent even though it's imported. The error message is below.
public constructor Intent(p0: Context!, p1: Class<*>!) defined in android.content.Intent
public constructor Intent(p0: String!, p1: Uri!) defined in android.content.Intent
You need to pass context into the constructor of Intent instead of this.
val intent = Intent(context, sign_in::class.java)
I have three tabs (fragments) in my app, one of which should be a settings tab. I would like to use the AndroidX preference library for this settings tab.
I can open the settings tab and change settings, however once I have opened the settings tab once, the bottom navigation bar does not work anymore. When I close and restart the app the preferences have been saved. I think this is because .replace(android.R.id.content, SettingsFragmentCompat()) replaces the entire activity including the bottom navigation bar.
How can I correctly load the preference fragment into the tab fragment?
SettingsFragment.kt (tab fragment)
package net.htlgrieskirchen.jheschl17.hypernote.ui.settings
import android.app.Activity
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 net.htlgrieskirchen.jheschl17.hypernote.R
class SettingsFragment : Fragment() {
private lateinit var view1: View
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
view1 = inflater.inflate(R.layout.fragment_settings, container, false)
requireActivity().supportFragmentManager
.beginTransaction()
.replace(android.R.id.content, SettingsFragmentCompat())
.commit()
return view1
}
}
SettingsFragmentCompat.kt (android boilerplate)
package net.htlgrieskirchen.jheschl17.hypernote.ui.settings
import android.os.Bundle
import androidx.preference.PreferenceFragmentCompat
import net.htlgrieskirchen.jheschl17.hypernote.R
class SettingsFragmentCompat : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences, rootKey)
}
}
I solved the issue by changing the root element of the layout file corresponding to SettingsFragment to androidx.drawerlayout.widget.DrawerLayout with id view_settings and changing .replace(android.R.id.content, SettingsFragmentCompat()) to .replace(R.id.view_settings, SettingsFragmentCompat()).
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.drawerlayout.widget.DrawerLayout
import com.example.tender.R
import com.example.tender.databinding.FragmentAvailableTenderBinding
import com.example.tender.databinding.FragmentLoginBinding
import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.NavigationUI
/**
* A simple [Fragment] subclass.
*/
class AvailableTenderFragment : Fragment() {
private lateinit var drawerLayout: DrawerLayout
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val binding = FragmentAvailableTenderBinding.inflate(inflater)
drawerLayout = binding.drawerLayout
**val navController = this.findNavController(R.id.nav_host_fragment)**
**NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout)**
NavigationUI.setupWithNavController(binding.navView, navController)
binding.root
}
}
"To many arguments for public fun Fragment.findNavController():NAvcontroller defined in androidx.navigation.fragment" is showing when i hover on findnavcontroller.I am unable to resolve the error on the above bold lines.In this case what should I do?
As per the Navigate to a destination documentation, the androidx.navigation.fragment.findNavController you've imported takes no parameters (it finds the parent NavHostFragment of the current Fragment and doesn't need the ID of the NavHostFragment).
The lines you've written, namely findNavController(R.id.nav_host_fragment) and setupActionBarWithNavController() are methods you'd call in an Activity, not in a Fragment.