I have followed various tutorials for creating a custom Spinner on Android. Unfortunately, I don't fully understand how what I'm doing works, so I would really appreciate it if you could give me a cable to finish understanding it.
Next, I leave the code that I have made following the tutorial.
package es.manuel.spinnerexample.ui.customSpinner
import android.content.Context
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.activity.viewModels
import es.manuel.spinnerexample.R
import es.manuel.spinnerexample.databinding.ActivityCustomSpinnerBinding
class CustomSpinnerActivity : AppCompatActivity() {
private val binding: ActivityCustomSpinnerBinding by lazy {
ActivityCustomSpinnerBinding.inflate(layoutInflater)
}
private val viewModel: CustomSpinnerViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
setupViews()
}
private fun setupViews() {
binding.spnCustomSpinnerPlanets.adapter =
PlanetSpinnerAdapter(this, viewModel.planets)
}
companion object {
fun newIntent(context: Context): Intent {
return Intent(context, CustomSpinnerActivity::class.java)
}
}
}
package es.manuel.spinnerexample.ui.customSpinner
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import es.manuel.spinnerexample.data.entity.Planet
import es.manuel.spinnerexample.databinding.SpinnerSelectedItemBinding
class PlanetSpinnerAdapter(
ctxt: Context,
private val planets: List<Planet>
) :
ArrayAdapter<Planet>(ctxt, 0, planets) {
// TODO HACER
private val layoutInflater = LayoutInflater.from(ctxt)
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
return initView(position, convertView, parent)
}
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
return initView(position, convertView, parent)
}
private fun initView(position: Int, convertView: View?, parent: ViewGroup): View {
val rowView = SpinnerSelectedItemBinding.inflate(layoutInflater, parent, false)
val planet = planets[position]
rowView.txtSpinnerSelectedItemKm.text = planet.order.toString()
rowView.txtSpinnerSelectedItemName.text = planet.name
return rowView.root
}
}
package es.manuel.spinnerexample.ui.customSpinner
import androidx.lifecycle.ViewModel
import es.manuel.spinnerexample.data.base.Database
class CustomSpinnerViewModel : ViewModel() {
val planets = Database.queryAllPlanets()
}
I understand that the main idea is to create a class that extends ArrayAdapter (which already has what it takes to create an adapter for the Spinner, right?), what I don't quite understand is what the overridden methods do or why they have the same code. The way I see it, I think one is for when only one item is displayed and the other is for when the list of items is displayed, how is it possible that it works having the same code?
Here I bring you a code made 100% by me, I am going to explain each step of how I create it, I originally created it to use it in a custom listView, but it also works in your case.
The truth is that I did not understand 100% your code written in Kotlin.
activity_main.xml
MainActivity.java
Here we must observe that we obtain the Spinner by its ID, then in my case I create an array that contains the internal path of the .json files which contains the information (image path, title and description), which would be the information that we will use to create the custom view.
Don't pay attention to the commented part, that was for the original listView, with the Spinner it will give you an error.
OptionAdapter.java
First of all, the constructor, we store everything in internal variables and we get the LayoutInflater with the context.
then as we can see, the most important method we have is getView(...)
What exactly is this method?
well my friend that method is the one with all the magic, it will return a "view" view that is basically where what we want comes in, it is the heart of the matter because that is the view that will be seen in the spinner, each one of the options of the spinner will be obtained from this method.
now is where LayoutInflater comes into play.. it will allow us to create a view from an existing .xml file.. then we will get its internal views and assign the data to it.. the other data that will help us obtain These data.
In my case I decided to do it that way of passing the path of the .json files and reading them, you can do something easier and that is to pass an array of a custom class that contains the title, image id, and description.
but something is missing, here is the .xml file that I use to inflate the view. Option.xml
this too but to be clear, the .xml files must be in res/layout
Edit I don't understand much of your code, I only program in java, above is how I would do it using java, but I don't see that you have an .xml file to inflate, the truth is I don't know what to do with your Layout Inflater , it may be that your problem