I am working on the codelab:
https://codelabs.developers.google.com/codelabs/kotlin-android-training-add-navigation/index.html?index=..%2F..android-kotlin-fundamentals#0
I have the following function in the GameFragment.kt
private fun setTitle() {
(activity as AppCompatActivity).supportActionBar?.title = getString(R.string.title_android_trivia_question, questionIndex + 1, numQuestions)
}
strings.xml contains this line:
<string name="title_android_trivia_question" formatted="false">Android Trivia (%d/%d)</string>
I call this function in the onCreateView like this:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
binding = DataBindingUtil.inflate<FragmentGameBinding>(
inflater, R.layout.fragment_game, container, false)
// Shuffles the questions and sets the question index to the first question.
randomizeQuestions()
setTitle()
...
This displays the title properly. But before showing this the default title "GameFragment" is shown for a fraction of second. How to avoid that?
Related
I'm trying to use Bottom Navigation in my app. Most explanations online are about using Bottom Navigation to navigate a fragment container from WITHIN the MainActivity. However, I am trying to use the Bottom Navigation from within a fragment and not an activity. Can anybody help me? This is the code I have thus far, the line in bold represents the problem saying:
"Too many arguments for public fun Fragment.findNavController(): NavController defined in androidx.navigation.fragment"
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentHomePageBinding.inflate(inflater, container, false)
val bottomNavigationView = binding.bottomNavigation
val navController = findNavController(**R.id.homeScreenFragment**)
bottomNavigationView.setupWithNavController(navController)
return binding.root
}
}
I wish to generate a column of buttons inside a fragment in Kotlin from a database. For now I tried with just one button, but I cannot seem to do it without hardcoding it in the XML file. Here is my code so far:
class NotesFragment() : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view: View = inflater!!.inflate(R.layout.fragment_notes, container, false)
//val root : ViewGroup = inflater.inflate(R.layout.fragment_notes, null) as ViewGroup
val button_Id: Int = 1111
val button = Button((activity as MainActivity?)!!)
button.setText("Button 4 added dynamically")
button.setLayoutParams(ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT))
button.setId(button_Id)
button.x = 250f
button.y = 500f
button.setOnClickListener(this)
view.add(button)
return view
}
}
I know I should probably look for the layout somewhere in this and do an addView with it... What is the next step?
I did it like this
view.rootView.findViewById<RelativeLayout>(R.id.button_container).addView(button)
I am using this instruction: https://developer.android.com/training/graphics/opengl/environment.
But I have to work with fragment instead of activity. Also I have some picture on main fragment and using OpenGl I have to draw some shapes. But, when I start app in becomes just empty dark screen.
Somewhere I found that I can write something like this for fragment, but If I remove this line of code my xml layout become on app, but I need to mix fragment and draw shapes over this fragment.
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
lifecycle.addObserver(viewModel)
val rootView = inflater.inflate(R.layout.main_fragment, container, false)
val fL = rootView.findViewById<ConstraintLayout>(R.id.main)
customGLSurfaceView = CustomGLSurfaceView(requireContext())
fL.addView(customGLSurfaceView) // this line
return rootView
}
I'm using the jetpack navigation component here, not the Compose Navigation Component since there are some areas in my app I cannot convert yet.
The issue I'm running into is:
Fragment A starts and contains a ComposeView in it's xml. Fragment A opens Fragment B. But, when you return to Fragment A, the ComposeView is empty and doesn't show anything.
Is this a bug? Is this known? Am I just doing something wrong? I looked into setting the view composition strategy and tried each option and none of them worked.
I found the answer. I had a BaseFragment:
abstract class BaseFragment : Fragment() {
private var hasInitializedRootView = false
private var rootView: View? = null
protected abstract val layoutId: Int
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return getPersistentView(inflater, container, savedInstanceState, layoutId)
}
private fun getPersistentView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?, layout: Int): View? {
if (rootView == null) {
// Inflate the layout for this fragment
rootView = inflater?.inflate(layout, container, false)
} else {
// Do not inflate the layout again.
// The returned View of onCreateView will be added into the fragment.
// However it is not allowed to be added twice even if the parent is same.
// So we must remove rootView from the existing parent view group
// (it will be added back).
(rootView?.parent as? ViewGroup)?.removeView(rootView)
}
return rootView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (!hasInitializedRootView) {
hasInitializedRootView = true
viewCreated(view, savedInstanceState)
}
}
abstract fun viewCreated(view: View, savedInstanceState: Bundle?)
}
What would happen is that onCreateView wouldn't be called as wanted and the composition wouldn't restart. Changing to using a normal Fragment fixed this perfectly.
class DashBoardFragment : Fragment() {
private var recyclerView : RecyclerView?=null
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
var view = inflater!!.inflate(R.layout.fragment_dash_board, container, false)
initComponents(view )
return view
}
private fun initComponents(View view) {
var textView : TextView = view?.findViewById(R.id.recyclerView) as TextView
textView.setText("hello world")
}
when changing into recycler its showing same problem appreciate if you help to me
Well, how about adding more details. Like, what are you trying to accomplish, how are you doing it, what difficulties you have found with the approach, another approaches you have tried, etc. In summary, without code isn't a good question neither is with just code. Search for the balance!
Try moving the code in the initComponents function to the onCreateView function. The error might occur because recyclerView id is not ready until the View is created.
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
var view = inflater!!.inflate(R.layout.fragment_dash_board, container, false)
var textView : TextView = view?.findViewById(R.id.recyclerView) as TextView
textView.setText("hello world")
return view
}