Automated Java to Kotlin conversion: unresolved reference to 'ARG_LAYOUT_RES_ID' - android

I'm using AppIntro in my Kotlin app, and need to customize its layout. The tutorial tells us to use this code as starting point. Because that's written in Java, I converted it to Kotlin (not 100% automated though, because Kotlin doesn't support 'static' keyword):
import android.support.v4.app.Fragment
import android.os.Bundle
import android.support.annotation.Nullable
import android.view.ViewGroup
import android.view.LayoutInflater
import android.view.View
class IntroFragment: Fragment() {
private val ARG_LAYOUT_RES_ID = "layoutResId"
private var layoutResId: Int = 0
companion object {
fun newInstance(layoutResId: Int): IntroFragment{
val args: Bundle = Bundle()
args.putSerializable(ARG_LAYOUT_RES_ID, layoutResId)
val fragment = IntroFragment()
fragment.arguments = args
return fragment
}
}
override fun onCreate(#Nullable savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (arguments != null && arguments!!.containsKey(ARG_LAYOUT_RES_ID)) {
layoutResId = arguments!!.getInt(ARG_LAYOUT_RES_ID)
}
}
#Nullable
override fun onCreateView(inflater: LayoutInflater, #Nullable container: ViewGroup?,
#Nullable savedInstanceState: Bundle?): View? {
return inflater.inflate(layoutResId, container, false)
}
}
At this part:
args.putSerializable(ARG_LAYOUT_RES_ID, layoutResId)
Android Studio complains:
Unresolved reference: ARG_LAYOUT_RES_ID
How to solve this?

It is because ARG_LAYOUT_RES_ID is an instance variable while your newInstance method is a class (static) method.
If you move ARG_LAYOUT_RES_ID into the companion object, it will work. Like this:
import android.support.v4.app.Fragment
import android.os.Bundle
import android.support.annotation.Nullable
import android.view.ViewGroup
import android.view.LayoutInflater
import android.view.View
class IntroFragment: Fragment() {
private var layoutResId: Int = 0
companion object {
private const val ARG_LAYOUT_RES_ID = "layoutResId"
fun newInstance(layoutResId: Int): IntroFragment {
val args: Bundle = Bundle()
args.putSerializable(ARG_LAYOUT_RES_ID, layoutResId)
val fragment = IntroFragment()
fragment.arguments = args
return fragment
}
}
override fun onCreate(#Nullable savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (arguments != null && arguments!!.containsKey(ARG_LAYOUT_RES_ID)) {
layoutResId = arguments!!.getInt(ARG_LAYOUT_RES_ID)
}
}
#Nullable
override fun onCreateView(inflater: LayoutInflater,
#Nullable container: ViewGroup?,
#Nullable savedInstanceState: Bundle?): View? {
return inflater.inflate(layoutResId, container, false)
}
}
You could also make ARG_LAYOUT_RES_ID a const like i've shown above.

Move the field to your companion object:
companion object {
private val ARG_LAYOUT_RES_ID = "layoutResId"
fun newInstance(layoutResId: Int): IntroFragment{
val args: Bundle = Bundle()
args.putSerializable(ARG_LAYOUT_RES_ID, layoutResId)
val fragment = IntroFragment()
fragment.arguments = args
return fragment
}
}

The variables and functions inside the companion object block are basically static (if you were to draw parallels from Java).
The ARG_LAYOUT_RES_ID variable is not inside the companion object scope, so it can't be accessed statically.
Move the ARG_LAYOUT_RES_ID variable inside the companion object scope, and all will be good again.

Related

setOnClickListener in Fragment with Kotlin

I am working on a sample code and I want a Button showing a message but it didn't work. App will open but buttonn didn't work
This app should show a Toast but it does not. I tried lateinit var firstComend : Button but didn't work too
I should sat will converting Activity to Fragment
Please help me
package com.mysfk.android.frogments
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.mysfk.android.R
import android.graphics.Color
import android.telephony.SmsManager
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
class OrderFragment : Fragment() {
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val let = arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
var firstComend = view?.findViewById<Button>(R.id.firstButton)
firstComend?.setOnClickListener {
Toast.makeText(context, "ارسال شد", Toast.LENGTH_SHORT).show()
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_order, container, false)
}
companion object {
#JvmStatic
fun newInstance(param1: String, param2: String) =
MessageFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
}
Try to set your click listener inside the onCreateView, like this:
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_order, container, false)
var firstComend = view?.findViewById<Button>(R.id.firstButton)
firstComend?.setOnClickListener {
Toast.makeText(context, "Test", Toast.LENGTH_SHORT).show()
}
}
All view related decision must be done in onCreateView or onViewCreated
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_order, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?){
var firstComend = view?.findViewById<Button>(R.id.firstButton)
firstComend?.setOnClickListener {
Toast.makeText(context, "Test", Toast.LENGTH_SHORT).show()
}
}

Why am I getting " kotlin.UninitializedPropertyAccessException: lateinit property binding has not been initialized " when binding is initialized?

I'm new to kotlin and android development.
I'm currently learning fragment and how to create it, receive data from one fragment and display it on another through the activity that connects them.
What I have done:
I created two fragment
I called them in the main activity dynamically
I used viewBinding
I created an interface called fragmentAactionListener in the SendingTextFragment and it has a method that will be defined in the main activity but called from the SendingTextFragment
What I was hoping to achieve:
When someone type a name in the editView and click the send button, it will call the method defined in the main activity and it will pass it to the DisplayFragment.
But when I type a name and click the button but the application class and say kotlin.UninitializedPropertyAccessException: lateinit property binding has not been initialized but initialized it.
The error message:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.fragmenttest, PID: 5187
kotlin.UninitializedPropertyAccessException: lateinit property binding has not been initialized
at com.example.fragmenttest.DisplayFragment.recieveName(DisplayFragment.kt:31)
at com.example.fragmenttest.MainActivity.onButtonClick(MainActivity.kt:37)
at com.example.fragmenttest.SendingTestFragment.onButtonClicked(SendingTestFragment.kt:52)
at com.example.fragmenttest.SendingTestFragment.onViewCreated$lambda-0(SendingTestFragment.kt:46)
at com.example.fragmenttest.SendingTestFragment.lambda$g_0sTs_brBZ0HIBdlZHmgd8vecI(Unknown Source:0)
at com.example.fragmenttest.-$$Lambda$SendingTestFragment$g_0sTs_brBZ0HIBdlZHmgd8vecI.onClick(Unknown Source:2)
at android.view.View.performClick(View.java:7448)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access$3600(View.java:810)
at android.view.View$PerformClick.run(View.java:28305)
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)
My code:
The MainActivity
package com.example.fragmenttest
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.example.fragmenttest.databinding.ActivityMainBinding
class MainActivity : FragmentActivity(), SendingTextFragment.FragmentActionListener {
private lateinit var binding : ActivityMainBinding
private var displayFragment : DisplayFragment? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
var sendingTestFragment = SendingTextFragment()
displayFragment = DisplayFragment()
addFragment(sendingTestFragment)
}
// add fragment
fun addFragment(fragment: Fragment){
// get the fragment manager and start fragment transaction
var fTransaction = supportFragmentManager.beginTransaction()
fTransaction.replace(R.id.FLFragment, fragment)
fTransaction.addToBackStack(null)
fTransaction.commit()
}
override fun onButtonClick(name: String) {
displayFragment!!.recieveName(name)
addFragment(displayFragment!!)
}
}
The SendingFragment
package com.example.fragmenttest
import android.content.Context
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.fragmenttest.databinding.FragmentSendingTestBinding
import java.text.SimpleDateFormat
class SendingTextFragment : Fragment() {
private lateinit var binding : FragmentSendingTestBinding
private var activityContext : SendingTextFragment.FragmentActionListener? = null
private var simpleDateFormat: SimpleDateFormat? = null
interface FragmentActionListener{
fun onButtonClick(name : String)
}
override fun onAttach(context: Context) {
super.onAttach(context)
activityContext = context as FragmentActionListener
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding = FragmentSendingTestBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
simpleDateFormat = SimpleDateFormat("HH:mm:ss")
binding.time.text = simpleDateFormat?.format(System.currentTimeMillis())
binding.button.setOnClickListener {
onButtonClicked(it)
}
}
private fun onButtonClicked(view: View){
if (activityContext != null){
activityContext?.onButtonClick(binding.name.text.toString())
}
}
}
The Display
package com.example.fragmenttest
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.example.fragmenttest.databinding.FragmentDisplayBinding
class DisplayFragment : Fragment() {
private lateinit var binding : FragmentDisplayBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding = FragmentDisplayBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
fun recieveName(name : String){
binding.name.text = name
}
}

How can I change different URL or view in tabbed activity?

I'm new in Android kotlin development. I would like to create a tabbed activity in my app to show different static HTML page.
I able to set 1 URL in my app now. But when I change or tap to another tab, it will show similar view or URL.
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.support.v4.app.Fragment
import android.arch.lifecycle.Observer
import android.arch.lifecycle.ViewModelProviders
import android.webkit.WebView
import xxx.abcabc.xxx.R
import android.util.Log
class PlaceholderFragment : Fragment() {
private lateinit var pageViewModel: PageViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
pageViewModel = ViewModelProviders.of(this).get(PageViewModel::class.java).apply {
setIndex(arguments?.getInt(ARG_SECTION_NUMBER) ?: 1)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_left_menu_policies, container, false)
var webTnc: WebView = root.findViewById(R.id.myWebView)
webTnc.loadUrl("https://www.abcxyz.com/abcxyz/abcxyz_webpage/tnc.html")
return root
}
companion object {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private const val ARG_SECTION_NUMBER = "section_number"
/**
* Returns a new instance of this fragment for the given section
* number.
*/
#JvmStatic
fun newInstance(sectionNumber: Int): PlaceholderFragment {
return PlaceholderFragment().apply {
arguments = Bundle().apply {
putInt(ARG_SECTION_NUMBER, sectionNumber)
}
}
}
}
}
How can I detect sectionNumber something like
if(sectionNumber == 0)
{
var webTnc: WebView = root.findViewById(R.id.myWebView)
webTnc.loadUrl("https://www.abcxyz.com/abcxyz/abcxyz_webpage/tnc.html")
}
else
{
var webTnc: WebView = root.findViewById(R.id.myWebView)
webTnc.loadUrl("https://www.URL2.com/URL2.html")
}
Please help. Thank you.
Edited
I see that you're putting sectionNumber in bundle arguments in fragment. So you can use that arguments to get the data back.
Try this:
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_left_menu_policies, container, false)
val sectionNumber = arguments?.getInt(ARG_SECTION_NUMBER) ?: 1
if (sectionNumber == 1) {
var webTnc: WebView = root.findViewById(R.id.myWebView)
webTnc.loadUrl("https://www.abcxyz.com/abcxyz/abcxyz_webpage/tnc.html")
} else {
var webTnc: WebView = root.findViewById(R.id.myWebView)
webTnc.loadUrl("https://www.URL2.com/URL2.html")
}
return root
}

Using safeargs I get "required Bundle found Bundle?"

I am passing arguments using safeargs. In the reciving fragment I am getting a compile error: 'Required Bundle Found Bundle?'. Cannot see where the error has crept in.
Googled around, checked text and udacity tutorial
Where error appears (at 'arguments')
package com.example.android.naveditoryoutube
import android.arch.lifecycle.ViewModelProviders
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.fragment_two_fragment.*
class FragmentTwo : Fragment() {
companion object {
fun newInstance() = FragmentTwo()
}
private lateinit var viewModel: FragmentTwoViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_two_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProviders.of(this).get(FragmentTwoViewModel::class.java)
}
override fun onStart() {
super.onStart()
var args = FragmentTwoArgs.fromBundle(arguments)
argText.text = args.calculated_Number
}
}
Sending code:
package com.example.android.naveditoryoutube
import android.arch.lifecycle.ViewModelProviders
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.navigation.Navigation
import kotlinx.android.synthetic.main.fragment_one_fragment.*
class FragmentOne : Fragment() {
companion object {
fun newInstance() = FragmentOne()
}
private lateinit var viewModel: FragmentOneViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_one_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
viewModel = ViewModelProviders.of(this).get(FragmentOneViewModel::class.java)
var calculated_Number : String = viewModel.sendNewNumber().toString()
button_calculate.setOnClickListener{view: View ->
if (number_box.text.isNotEmpty()){
var number_entered: String = number_box.text.toString()
viewModel.findNewNumber((number_entered))
calculated_Number = viewModel.sendNewNumber()
Navigation.findNavController(view).navigate(FragmentOneDirections.actionFragmentOneToFragmentTwo(calculated_Number))
}
}
}
}
Error appears here
var args = FragmentTwoArgs.fromBundle(arguments)
arguments is expected to be Bundle but is Bundle?
I had to change it to use !!
var args = FragmentTwoArgs.fromBundle(arguments!!)
use requireArguments() instead of arguments!!
try using requireArguments() instead of arguments
var args = FragmentTwoArgs.fromBundle(requireArguments())
You shouldn't use FragmentTwoArgs.fromBundle(arguments)
just use:
val args: FragmentTwoArgsby navArgs()
And in your method call:
val amount = args.amount
It's work for me, see official guide:
https://developer.android.com/topic/libraries/architecture/navigation/navigation-pass-data
Instead of
var args = FragmentTwoArgs.fromBundle(arguments)
argText.text = args.calculated_Number
you can use
arguments?.let {
val args = FragmentTwoArgs.fromBundle(it)
argText.text = args.calculated_Number
}

Type mismatch: inferred type is FragmentActivity? but Context was expected

i want to insert menu gridview in tablayout with kotlin. i have been searching for many references in google but it wont help, still getting 1 error in adapter = FoodAdapter(this, foodsList). it says "Type missmatch : inferred type as fragmentHome but Context was expected". this is my code for fragmentHome.kt
package com.example.ako.nextbrilliantgeneration
import android.os.Bundle
import android.support.v4.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.content.Context
import android.support.v4.app.FragmentActivity
import kotlinx.android.synthetic.main.fragment_fragment_home.*
import kotlinx.android.synthetic.main.menu_entry.view.*
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
class fragmentHome : Fragment() {
var adapter: FoodAdapter? = null
var foodsList = ArrayList<Menu>()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_fragment_home, container, false)
foodsList.add(Menu("Coffee", R.drawable.profile))
foodsList.add(Menu("Espersso", R.drawable.profile))
foodsList.add(Menu("French Fires", R.drawable.profile))
foodsList.add(Menu("Honey",R.drawable.profile))
foodsList.add(Menu("Strawberry", R.drawable.profile))
foodsList.add(Menu("Sugar cubes", R.drawable.profile))
adapter = FoodAdapter(this, foodsList)
gvFoods.adapter = adapter
}
class FoodAdapter : BaseAdapter {
var foodsList = ArrayList<Menu>()
var context: Context? = null
constructor(context: Context, foodsList: ArrayList<Menu>) : super() {
this.context = context
this.foodsList = foodsList
}
override fun getCount(): Int {
return foodsList.size
}
override fun getItem(position: Int): Any {
return foodsList[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val food = this.foodsList[position]
var inflator = context!!.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
var foodView = inflator.inflate(R.layout.menu_entry, null)
foodView.imgFood.setImageResource(food.image!!)
foodView.tvName.text = food.name!!
return foodView
}
}
}
is there any solution?
thanks
Your adapter takes in a non-null Context, but you're passing in a Fragment. You could try passing in your activity from your fragment, either:
adapter = FoodAdapter(activity!!, foodsList)
Or if you have the latest support library:
adapter = FoodAdapter(requireActivity(), foodsList)
You're getting unreachable error because you return from the method too early, simply move it to the bottom:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
foodsList.add(Menu("Coffee", R.drawable.profile))
foodsList.add(Menu("Espersso", R.drawable.profile))
foodsList.add(Menu("French Fires", R.drawable.profile))
foodsList.add(Menu("Honey",R.drawable.profile))
foodsList.add(Menu("Strawberry", R.drawable.profile))
foodsList.add(Menu("Sugar cubes", R.drawable.profile))
adapter = FoodAdapter(this, foodsList)
gvFoods.adapter = adapter
// move this line to last
return inflater.inflate(R.layout.fragment_fragment_home, container, false)
}
The error is clear enough you try to pass this which refer to Fragment object but your adapter needs Context then try to pass Activity that extends from Context.
Replace this line
adapter = FoodAdapter(this, foodsList)
With
adapter = FoodAdapter(getActivity(), foodsList)
Update
calls to Java get and set methods that can be replaced with the use of Kotlin synthetic properties.
getActivity() --> activity
This is a great update to help developers who are writing in Kotlin. The getActivity method has been annotated with #Nullable to better support Kotlin null-safety. Before, this method could return null and would therefore cause an IllegalStateException in Kotlin code because a null object would be used where a non-null type was expected.
To best handle these cases for methods that have been annotated with #Nullable, use the let operator to unwrap the nullable into a non-null object.
getActivity()?.let { adapter = FoodAdapter(it, foodList) }
DO NOT use requireActivity() to "ensure" a non-null activity because this method will throw an exception if your activity does happen to be null.
In Fragment class you should use following way:
mFargmentSettingBinding.txtAppVersionCode.setText(Static.getAppVersion(activity!!))

Categories

Resources