Error declaring an Intent in from a Fragment in Kotlin: - android

I am trying to create an intent that uses a button within a fragment in the main activity to open a new activity. The error pops up underlining the 'Intent' object with a red line. The error is:
None of the following functions can be called with the arguments supplied.
(Context!, Class<*>!) defined in android.content.Intent
(String!, Uri!) defined in android.content.Intent
I tried the following code
val fieldIntent = Intent(this#Fragment1, ProductsAndInputs::class.java )
instead of the initial
val fieldIntent = Intent(this, ProductsAndInputs::class.java )
Based on an answer provided on a different forum but it also didn't work
class Fragment1 : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view: View = inflater!!.inflate(R.layout.fragment_fragment1, container, false)
view.btn_field.setOnClickListener { view ->
val fieldIntent = Intent(this#Fragment1, ProductsAndInputs::class.java )
Log.i("Button clicked", "Field button")
}
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
}

the issue is that the Intent constructor wants a context, but you're passing it a Fragment. But you can get a context from the Fragment: try this:
val fieldIntent = Intent(this#Fragment1.context, Products...
Oh, and you do need to call startActivity too, as Ajay said.

You need to add this code
val fieldIntent = Intent(this#Fragment1, ProductsAndInputs::class.java )
startActivity(fieldIntent)

Related

Setting setOnClickListener using bindings android kotlin

I have been doing a tutorial that is a bit out of date and uses synthetics rather than bindings. I am trying to use bindins. I am trying to set up a listener in a fragment (AddEditFragment.kt). It's using a callback to MainActivity.onSaveClicked.
In AddEditFragment I use an import for the binding
import com.funkytwig.tasktimer.databinding.FragmentAddEditBinding
I have a lateinit on the first line of the class defenition
class AddEditFragment : Fragment() {
private lateinit var binding: FragmentAddEditBinding
I am initializing the bunding in onActivityCreated and setting up the listner. I can use findViewById to get the ID
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val addEditSave = view?.findViewById(R.id.addEditSave) as Button
addEditSave.setOnClickListener { listener?.onSaveClicked() }
}
And this works fine but if I try to use the binding
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
binding.addEditSave.setOnClickListener { listener?.onSaveClicked() }
}
The code does not show any errrors but it does not seem to create the listner. I have a Log.d in the onSaveClicked callback function and when I use the first (findViewById) version of the function it works (it calles onSaveClicked) but with the second version (using bindings) onSaveClicked does not get called when I click the Button.
I Cant figre out why the second version does not work, I thought the two versions of onActivityCreated should do the same thing.
The interface in AddEditFragment.kt is
interface OnSaveClicked {
fun onSaveClicked()
}
In fragment you should add your view in onCreateView or in OnViewCreated not in onActivityCreated
Please refer link for more details.
private var _binding: FragmentAddEditBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentAddEditBinding.inflate(inflater, container, false)
val view = binding.root
binding.addEditSave.setOnClickListener { listener?.onSaveClicked() }
return view
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
OK, thanks for all the help. turned out I was doing the inflate wrong.
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
Log.d(TAG, "onCreateView")
binding = FragmentAddEditBinding.inflate(layoutInflater, container, false)
return binding.root
}
I was doing
binding = FragmentAddEditBinding.inflate(layoutInflater)
I missed out on the last 2 args as I was taking the code from the inflate when I am in an Activity, not a Fragment. I think it is to do with the layout effecticly being in the parent.

Passing data from fragment to mainactivity with tablayout and adapater. Kotlin android app

i need help with the following situation.
I hava a fragment, adapter and mainactivity. i use fragment and adapter for tablayout.
Im trying to pass data from edittext in fragment to activity.
When i am using Intent to pass data from fragment to mainactivit , it crashes the app.
Is there a another posibility to pass data like via adapter to mainactivity?
class person : Fragment() {
lateinit var Sname : EditText
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_person, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Sname= view.findViewById(R.id.snamedittext)
senddata()
}
private fun senddata() {
var name = Sname.toString()
val intent = Intent(activity,personactivity::class.java)
intent.putExtra("name", name)
startActivity(intent)
}
}

How to get EditText value from xml in fragment?

What I've tried so far:
getString(R.id.editBrand) => this returns false (R.id.editBrand returns a long number)
view.findViewById(R.id.editBrand) => runs to nullreference
Any help would be vm appreciated, thank you!
My whole fragment:
class CreateFragment : Fragment() {
#SuppressLint("ResourceType")
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val binding = DataBindingUtil.inflate<FragmentCreateBinding>(inflater,
R.layout.fragment_create,container,false)
val application = requireNotNull(this.activity).application
val dataSource = CarDatabase.getInstance(application).carDatabaseDao
val viewModelFactory = CarViewModelFactory(dataSource, application)
val carViewmodel =
ViewModelProvider(
this, viewModelFactory).get(CarViewmodel::class.java)
val adapter = CarAdapter()
binding.submitButton.setOnClickListener { view : View ->
view.findNavController().navigate(R.id.action_createFragment_to_readFragment)
carViewmodel.onCreated(12, view.findViewById<EditText>(R.id.editBrand).editBrand.toString(), "blue")
}
binding.setLifecycleOwner(this)
return binding.root
}
}
Use
binding.editBrand.text.toString()
Since binding is the reference to your layout here.
If you use view.findViewById<EditText>, view refers to the submitButton and calling findViewById on it will look for child views.
getString() take a string resource as a parameter and not a view resource.

How can I call a context in a fragment for DrawableCompat.setTint with kotlin?

I want to change the color of a button in fragment by control of another button in mainActivity.
The code for the fragment is :
lass build_8p : Fragment() {
var brush_chosen = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val brush_color = arguments?.getString("brush")
ib0.setOnClickListener {
if (brush_chosen==1)
{
//val con = this.context
DrawableCompat.setTint(ib0.drawable, ContextCompat.getColor(this.context,R.color.rndcolor1))
}
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_build_8p, container, false)
}
The variable brush_chosen will be took from the mainActivity.
Here I want to know how to put a correct input for
DrawableCompat.setTint(ib0.drawable, ContextCompat.getColor(this.context,R.color.rndcolor1))
}
Since that line does not work.
Please tell me how and Thank you very much.
You can just use requireContext():
DrawableCompat.setTint(ib0.drawable, ContextCompat.getColor(requireContext(),R.color.rndcolor1))
To use fragment context :
DrawableCompat.setTint(ib0.drawable, ContextCompat.getColor(requireContext(),R.color.rndcolor1))
To use Activity context :
DrawableCompat.setTint(ib0.drawable, ContextCompat.getColor(requireActivity(),R.color.rndcolor1))
both should work in your case

How can I add a function extension for Fragment class in Kotlin?

At present, I use Code B to display a message in a Fragment class, it works well.
I hope to use Code A to do it, so I write Code C, but Code C is wrong, how can I fix Code C ? Thanks!
Code A
import org.jetbrains.anko.*
class UIFragmentCamera : Fragment() {
private fun updateCameraUi() {
toast("Hello")
}
}
Code B
import org.jetbrains.anko.*
class UIFragmentCamera : Fragment() {
private fun updateCameraUi() {
requireContext().toast("Hello")
}
}
Code C
fun Fragment.toast(info:String) {
requireActivity().toast(info)
}
Make sure you imported androidx.fragment.app.Fragment or android.app.Fragment in the extension function defined file
requireActivity returns FragmentActivity whereas requireContext returns Context. I believe your toast is another extension function which display message based on the type Context
Code C
fun Context.toast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show()
}
fun Fragment.toast(info: String) {
requireContext().toast(info)
}
Option - 1: If you want to create extension function of Fragment class you have to do it in this way
fun Fragment.toast(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}
And from inside fragment you can call this like below:
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
//Here it is
toast("Hello")
return super.onCreateView(inflater, container, savedInstanceState)
}
Option - 2: You can create extension function for Context class like this
fun Context.toast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
Then you can call this from Fragment like below:
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
//Here it is, both are valid
requireActivity().toast("Hello")
requireContext().toast("World")
return super.onCreateView(inflater, container, savedInstanceState)
}
You can also call this from Activity like below:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
toast("Hello World")
}
import android.widget.Toast
import androidx.fragment.app.Fragment
fun Fragment.toast(message :String ){
Toast.makeText(requireContext(),message,Toast.LENGTH_SHORT).show()
}

Categories

Resources