Android Kotlin pass spinner values to mutable list - android

I have an application with a spinner that contains several items.
I created it and all that
Could anyone give me an example of how I can pass these values to a list I have? Using a mutableList?
Cheers
class NewKitListActivity : AppCompatActivity() {
var spinnerArray = arrayOf("Dumbell", "Punching Bag", "Yoga Ball", "Skipping Rope")
val kitMutableList = mutableListOf(spinnerArray)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_new_kit_list)
val spinner = newKitItemSpinner
val spinnerArrayAdapter = ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, spinnerArray)
//selected item will look like a spinner set from XML
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
spinner.adapter = spinnerArrayAdapter
spinner.onItemSelectedListener = object : OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
val selectedItem = parent.getItemAtPosition(position).toString()
if (selectedItem == "Dumbell") {
// mutableListAdapter.toMutableList()
//mutableList.adapter = mutableListAdapter
}
} // to close the onItemSelected
override fun onNothingSelected(parent: AdapterView<*>) {
}
}

I believe you can do like this.
1. Make custom adapter or adapters
2. Make first list which hold string values
3. Make mutable list which holds selected values
4. when spinner loaded first time it load values from first adapter and list
5. when user select item it clear first adapter then notify changes then set new adapter load values from mutable list ( I am not sure last will require to notify changes to adapter)
//Mutable List for storing selected items
val selectedItems: MutableList<String>? = null
//Listen On select for spinner
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
//Performing action onItemSelected and onNothing selected
override fun onItemSelected(arg0: AdapterView<*>, arg1: View, position: Int, id: Long) {
// Add selected item in Mutable List
selectedItems.add(spinnerArray[position])
// Clear Adapter
spinner.adapter = null
// Notify data set changed
spinnerArrayAdapter.notifyDataSetChanged()
// Set New Data adapter
spinner.adapter = ArrayAdapter(this, android.R.layout.simple_spinner_dropdown_item, selectedItems)
}
override fun onNothingSelected(arg0: AdapterView<*>) {
// TODO: Auto-generated method stub
}
}

Create a list to store your selectedItems:
val selectedItems = mutableListOf<String>()
then add items when they are selected:
override fun onItemSelected(arg0: AdapterView<*>, arg1: View, position: Int, id: Long) {
selectedItems.add(spinnerArray[position])
}

Related

How to retrieve the String of a selected item in spinner outside of onItemSelected method?

I need to retrieve the selected string in a spinner outside of the .onItemSelectedListener.
The dropdown menu contains "Each week, each month, each year" strings and I need to retrieve that selected item String in order use them in if conditionals outside of the function.
I've only seen people making Toasts in the onItemSelected function but this doesn't solve my problem.
This is my code:
val spinner = binding.tvAutoComplete
val powtarzanie = resources.getStringArray(R.array.powtarzanie)
val arrayAdapter = ArrayAdapter(requireContext(),
R.layout.dropdown_powtarzaj_item,
powtarzanie)
spinner.setAdapter(arrayAdapter)
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long
) {
val itemText: String = parent?.getItemAtPosition(position).toString()
}
override fun onNothingSelected(parent: AdapterView<*>?) {
TODO("Not yet implemented")
}
}
One way and probably the most simple way to go about this is to define a global variable:
private var spinnerSelection: String? = null
and just change it in your onItemSelected implementation:
spinnerSelection = parent?.getItemAtPosition(pos).toString()
Example code showing the whole flow:
class MainActivity : AppCompatActivity(), AdapterView.OnItemSelectedListener {
private var spinnerSelection: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val spinner: Spinner = findViewById(R.id.spinner)
spinner.onItemSelectedListener = this
ArrayAdapter.createFromResource(
this,
R.array.numbers_array,
android.R.layout.simple_spinner_item
).also { adapter ->
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
spinner.adapter = adapter
}
val button: Button = findViewById(R.id.button)
button.setOnClickListener {
Log.d("MainActivity", "Currently selected item: $spinnerSelection")
}
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, pos: Int, id: Long) {
spinnerSelection = parent?.getItemAtPosition(pos).toString()
}
override fun onNothingSelected(parent: AdapterView<*>?) {
//TODO("Not yet implemented")
}
}

Kotlin: function setSelection() doesn't work outside onItemSelected() function

I have a spinner and when I select something from the list some action happens:
val arrayAdapter =
ArrayAdapter(requireContext(), R.layout.dropdown_item, carBrandList)
binding.spinner.adapter = arrayAdapter
binding.spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
adapterView: AdapterView<*>?,
view: View?,
position: Int,
id: Long,
) {
refuelList.clear()
realTimeUpdates(carIdList[position])
saveData(requireContext(), carIdList[position])
saveSpinnerPosition(requireContext(), position)
}
override fun onNothingSelected(parent: AdapterView<*>?) {
}
}
I want to store spinner position in Shared Preferences and it works.
I want to retrieve spinner position if an user opens particular fragment.
How can I use function setSelection() outside this code? setSelection() only works for me if it is in onItemSelected() function
It should work outside the onItemSelected(), just be sure that you saved the correct spinner position in Shared Preferences.

Android Kotlin does spinner_listener run through during initialize?

I write a kotlin app and wonder, why the code runs through the listener during initializing it. I try to explain the question with my code:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
findpath()
//check, if Dateien existieren, sonst create in function
checkOrCreateFiles()
binding = ActivityMainBinding.inflate(layoutInflater)
var view = binding.root
setContentView(view) //R.layout.activity_main)
val cadapterk: ArrayAdapter<String> = ArrayAdapter<String>(
this,
android.R.layout.simple_spinner_item, myvokdirs
)
binding.spinnerKasten.adapter = cadapterk
//binding.spinnerKasten.setSelection(0)
binding.spinnerKasten.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>,
view: View,
position: Int,
id: Long
) {
kastenselected = myvokdirs[position].toString()
setnewpath(kastenselected)
}
override fun onNothingSelected(parent: AdapterView<*>) {
kastenselected = myvokdirs[0]
}
}
binding.AuswahlContainer.isEnabled = false
fileAktuell = boxes[0] //dateiAkt
checkAktuell = gut[0] // gutAkt
readDatei(fileAktuell)
binding.spinnerKasten.isEnabled = false
// some addional code
}
The situation / problem
In principle, the code works. Binding is o.k. The spinner "binding.spinnerkasten" is o.k. The associated adapter "cadapterk" is ok and shows data of my list "myvokdirs". BUT:
during initializing the spinner the code runs through "setnewpath". But "setnewpath" should be used only after selecting an item in the spinner.
How can I avoid, that "setnewpath" is fired during init? It seems, that the app runs through the listener during onCreate-function.
What is wrong or what is my misunderstanding, that the code fires "setnewpath" already in init instead of only after selecting an item?
do I habe to combine it with an onCLickListener?
(All other things are correct. The spinner appears on the right place, the spinner shows the correct data
onItemSelected is always called upon loading if you dont want something to run on initial load then surround with a boolean
var firstLoad = true
override fun onItemSelected(
parent: AdapterView<*>,
view: View,
position: Int,
id: Long
) {
if(!firstLoad){
kastenselected = myvokdirs[position].toString()
setnewpath(kastenselected)
}else{
firstLoad = false
}
}

How to initialise spinner using data binding

I am using data binding to bind my spinner
Everything works well except, the first time when I load data from server, I initialize the spinner and I set a selected value from my viewModel, but it doesn't work
If I close and reopen the page, I find the value selected in the spinner
Here is my spinner xml:
<Spinner
android:id="#+id/construction_site"
android:layout_width="match_parent"
android:layout_height="40dp"
android:prompt="#string/select_existing_construction_site"
app:entries="#{viewModel.constructionSiteAdapter}"
app:selectedValue="#{viewModel.constructionSite}"
style="#style/Widget.AppCompat.DropDownItem.Spinner">
</Spinner>
In the viewModel, I initialize the spinner in this way :
class RightDrawerViewModel : ViewModel(){
val constructionSiteAdapter: ArrayAdapter<ConstructionSite> by lazy {
ConstructionSiteAdapter(
App.context,
R.layout.cell_construction_site_list_item,
ArrayList()
)
}
fun bind(constructionSite: ConstructionSite) {
constructionSiteAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
constructionSiteAdapter.clear()
this.constructionSite.value = constructionSite // here I set the selected site to the spinner using data binding
setConstructionSites(constructionSite)
loadConstructionSites() // this method, load all sites from server and add them to the spinner
}
}
Here is my binding adapter:
#BindingAdapter(value = ["selectedValue", "selectedValueAttrChanged", "entries"], requireAll = false)
fun setEntries(view: Spinner, newSelectedValue: ConstructionSite?, bindingListener: InverseBindingListener?, adapter: ArrayAdapter<*>) {
view.adapter = adapter
view.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
bindingListener?.onChange()
}
override fun onNothingSelected(parent: AdapterView<*>) {}
}
if (newSelectedValue != null) {
val pos = (view.adapter as? ArrayAdapter<ConstructionSite>)?.getPosition(newSelectedValue)
if (pos != null) view.setSelection(pos, true)
}
}
#InverseBindingAdapter(attribute = "selectedValue", event = "selectedValueAttrChanged")
fun getSelectedValue(view: Spinner): ConstructionSite {
return view.selectedItem as ConstructionSite
}
So the problem is this.constructionSite.value = constructionSite doesn't work and for the first load, the spinner doesn't have a selected value

How to Set Multiple Click Listener to AutoCompleteTextView in Android?

I have an AutoCompleteTextView that will show a list of Hints when type in few keyword that match with its ArrayAdapter Data.
Currently, I have set an AdapterView.OnItemClickListener so when user click on the Hint, the soft keyboard on screen will be close.
What I trying to achieve :
I would like to add a functionality that allow user to Delete the Data of the Hint from the Database, so I was thinking to add another ClickListener for the AdapterView such as LongClickListener, so when user LongClick on the Hint, it will trigger a Dialog Pop Out and prompt the Delete Confirmation from the User.
I been search for how to set LongClickListener on Autocomplete, however I could not find any solution on the net.
I believe it is important to ensure the Click Listen able to obtain the position(in Int) or text data(in String) of the Hint as I would need to determine what are the Data that being selected and I can tell the Database to delete it.
My Questions:
How can I set a Long Click Listener for the AutoCompleteTextView that will also obtain the selected Hint position?
Any other solution that could help to resolve what I trying to achieve is welcome, thank you.
Note: I would like to keep the functionality of the hide soft keyboard when Hint is selected. I accept Answer In Java Language as well.
What I have done so far :
// Get an ArrayList<String> from database and declare to remarkList
val remarkList: ArrayList<String> = getDataFromDatabase()
// Set remarkList Data into ArrayAdapter
val adapter = ArrayAdapter(context!!, android.R.layout.simple_list_item_1, remarkList)
// Set ArrayAdapter to AutoCompleteTextView
autoComplete_remarks.setAdapter<ArrayAdapter<String>>(adapter)
// When click the hint selection, will trigger close keyboard function
autoComplete_remarks.onItemClickListener =
AdapterView.OnItemClickListener { _: AdapterView<*>, _: View, position: Int, _: Long ->
hideKeyboard(activity!!)
}
In order to have multiple click listeners, you should build a custom Adapter with custom item layout.
class CustomAdapter(context: Context?, resource: Int) : ArrayAdapter<Data>(context, resource) {
private var mListener : IOnItemListener? = null
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View? {
var convertView = convertView
// Inflate layout
// Listeners
val textViewItem = convertView!!.findViewById(R.id.textViewItem) as TextView
textViewItem.setOnClickListener(View.OnClickListener {
mListener?.onClick(...)
})
textViewItem.setOnLongClickListener(View.OnLongClickListener {
mListener?.onLongClick(...)
})
return convertView;
}
fun setListener(listener: IOnItemListener) {
mListener = listener
}
interface IOnItemListener {
fun onClick(...)
fun onLongClick(...)
}
}
Then somewhere else, call
val adapter : CustomAdapter = CustomAdapter(context, R.layout...)
adapter.setListener(object: IOnItemListener())
Have created the Custom Adapter Class for the AutoCompleteTextView, Basically This Custom Adapter, in the getView function will create an Unique Individual Listener for each TextView that will be pop out by the AutoCompleteTextView.
Note: The TextView results that pop out by the AutoCompleteTextView is Customizable through inner class ListFilter: Filter() and override fun publishResults(constraint: CharSequence?, results: FilterResults) function
Custom Adapter Class
class AutoCompleteTextViewCustomAdapter(context: Context, resource: Int, data: ArrayList<String>): ArrayAdapter<String>(context, resource) {
private var mListener: IOnItemListener? = null
private var dataList: List <String>? = data
private val listFilter = ListFilter()
private var dataListAllItems: List<String>? = null
override fun getView(position: Int, view: View? , parent: ViewGroup): View {
var adapterView = view
// using Custom XML View
if (adapterView == null) {
adapterView = LayoutInflater.from(parent.context)
.inflate(R.layout.list_row_text, parent, false)
}
val textView = adapterView!!.findViewById(R.id.textView) as TextView
textView.text = getItem(position)
// Custom OnClickListener Setup
textView.setOnLongClickListener {
mListener?.onLongClick("Pass Data")
true
}
// Custom OnClickListener Setup
textView.setOnClickListener {
mListener?.onSingleClick("Pass Data")
}
return adapterView
}
// Custom OnClickListener Setup
fun setListener(listener : IOnItemListener) {
mListener = listener
}
// Custom OnClickListener Setup that will be Called from the Activity/Fragment
interface IOnItemListener {
fun onLongClick(dataToBePass : String)
fun onSingleClick(dataToBePass : String)
}
// Custom Adapter Setup for AutoCompleteTextView
override fun getCount(): Int {
return dataList!!.size
}
override fun getItem(position: Int): String ? {
return dataList!![position]
}
override fun getFilter() : Filter {
return listFilter
}
inner class ListFilter: Filter() {
..// Filtering Logic
return results
}
override fun publishResults(constraint: CharSequence?, results: FilterResults) {
..// Filtering Logic
}
}
So, when each TextView that pop out by the AutoCompleteTextView being onClick or onLongClick, the override method in AutoCompleteTextViewCustomAdapter.IOnItemListener will be called to perform logic function that you desire.
Activity/Fragment
val adapter = AutoCompleteTextViewCustomAdapter(context!!, R.layout.list_row_text, dataList).also {
//Setup the OnClickListener what to perform when the TextView of the Adapter if being onClick
it.setListener(object : AutoCompleteTextViewCustomAdapter.IOnItemListener {
override fun onLongClick(dataReceived: String) {
// DO SOMETHING
}
override fun onSingleClick(dataReceived: String) {
// DO SOMETHING
}
})
}
// Set the adapter to the AutoCompleteTextView View that define in your XML File
autoCompleteTextView.setAdapter(adapter)
So far this solution work for my Scenario, in short, to having a Multiple Click Listener to AutoCompleteTextView, we cannot use the Default Adapter as they only support Single onClickListener, so we have to Create Custom Adapter to customize and setup ALL the ClickListener to support multiple onClick Listener.

Categories

Resources