Skip to content

Instantly share code, notes, and snippets.

@baruckis
Last active July 18, 2019 11:41
Show Gist options
  • Save baruckis/2ee9911c0b6a14bc7fdc5b8744d02c3c to your computer and use it in GitHub Desktop.
Save baruckis/2ee9911c0b6a14bc7fdc5b8744d02c3c to your computer and use it in GitHub Desktop.
Custom Spinner to differentiate between user selected and programmatically selected item in Kotlin for Android.
/*
* Copyright 2018 Andrius Baruckis www.baruckis.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.Spinner
import android.widget.AdapterView
/**
* Custom Spinner to differentiate between user selected and programmatically selected item.
*
* Call [CustomSpinner.programmaticallySetPosition] to set it programmatically.
* Call [CustomSpinner.setSelection] to set it user selected.
*/
class CustomSpinner : Spinner, AdapterView.OnItemSelectedListener {
private var mListener: OnItemSelectedListener? = null
/**
* Used to ascertain whether the user selected an item on spinner (and not programmatically).
*/
private var mUserActionOnSpinner = true
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
if (mListener != null) {
mListener!!.onItemSelected(parent, view, position, id, mUserActionOnSpinner)
}
// Reset variable, so that it will always be true unless tampered with.
mUserActionOnSpinner = true
}
override fun onNothingSelected(parent: AdapterView<*>) {
if (mListener != null)
mListener!!.onNothingSelected(parent)
}
interface OnItemSelectedListener {
/**
*
* Callback method to be invoked when an item in this view has been
* selected. This callback is invoked only when the newly selected
* position is different from the previously selected position or if
* there was no selected item.
*
* Impelmenters can call getItemAtPosition(position) if they need to access the
* data associated with the selected item.
*
* @param parent The AdapterView where the selection happened.
* @param view The view within the AdapterView that was clicked.
* @param position The position of the view in the adapter.
* @param id The row id of the item that is selected.
*/
fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long, userSelected: Boolean)
/**
* Callback method to be invoked when the selection disappears from this
* view. The selection can disappear for instance when touch is activated
* or when the adapter becomes empty.
*
* @param parent The AdapterView that now contains no selected item.
*/
fun onNothingSelected(parent: AdapterView<*>)
}
fun programmaticallySetPosition(pos: Int, animate: Boolean = true) {
mUserActionOnSpinner = false
setSelection(pos, animate)
}
fun setCustomOnItemSelectedListener(listener: OnItemSelectedListener) {
mListener = listener
}
constructor(context: Context) : super(context) {
super.setOnItemSelectedListener(this)
}
constructor(context: Context, mode: Int) : super(context, mode) {
super.setOnItemSelectedListener(this)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
super.setOnItemSelectedListener(this)
}
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
super.setOnItemSelectedListener(this)
}
constructor(context: Context, attrs: AttributeSet, defStyle: Int, mode: Int) : super(context, attrs, defStyle, mode) {
super.setOnItemSelectedListener(this)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment