Long story short. I want my spinner to always show same first item "Add". When item selected from the list it should be gone from the list and the specific action happen. The text "Add" should still appear on spinner. So my question is how to make that spinner always show first item on his dataList? PS. I made that first item in the list don't show when drop down is open.
My layout:
<Spinner
android:id="#+id/spinner_add"
style="#style/Widget.AppCompat.Spinner.Underlined"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:backgroundTint="#color/colorButton" />
Method to set spinner adapter with data list:
private fun fillAddSpinner() {
val spinner: Spinner = findViewById(R.id.spinner_add)
val titles: MutableList<String> = ArrayList()
titles.add(resources.getString(R.string.add_advanced_filter))
for (filter in tableAdvancedFilters) {
titles.add(filter.title)
}
val dataAdapter = object : ArrayAdapter<String?>(this, R.layout.spinner_item,
titles as List<String?>
) {
override fun getDropDownView(
position: Int,
convertView: View?,
parent: ViewGroup
): View {
var v: View? = null
// If this is the initial dummy entry, make it hidden
if (position == 0) {
val tv = TextView(context)
tv.height = 0
tv.visibility = View.GONE
v = tv
} else { // Pass convertView as null to prevent reuse of special case views
v = super.getDropDownView(position, null, parent)
}
// Hide scroll bar because it appears sometimes unnecessarily, this does not prevent scrolling
parent.isVerticalScrollBarEnabled = false
return v!!
}
}
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
spinner.adapter = dataAdapter
}
I want it stay the same like it is now:
After user selects one item from spinner I will render specific filter choices.
If you want to programmatically set spinner selected item use the following: spinnerObject.setSelection(INDEX_OF_ITEM)
Related
I'm trying to set a Background color for alternate items in my ListView. I'm doing the following in my Custom ArrayAdapter class:
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val currentExpense:Expense? = getItem(position)
itemExpenseListBinding = ExpensesRowDesignBinding.inflate(
LayoutInflater.from(context),
parent,
false)
val itemView = itemExpenseListBinding.root
// if(itemView == null){
// itemView = convertView as LinearLayout
// }
for ((index, item) in dataSource.withIndex()){
if (index%2 == 0){
itemExpenseListBinding.linearExpensesRow.setBackgroundColor(Color.parseColor("#FEF8DD")
)
}
}
However, I'm getting end up with Background color being set on all my rows. I would like to have it set on just the even number rows in my ListView.
Update: Fixed this doing the following:
if (position%2 == 0){
itemExpenseListBinding.linearExpensesRow.setBackgroundColor(Color.parseColor("#FEF8DD"))
}
Can't believe I missed the position parameter lol.
I'm using AndroidStudio 4.1.1 and kotlin
I'm having issues trying to get the value of a selected item in a spinner view/item. My first attempt, and many threads say to do it this way, is:
val spinner = findViewById<Spinner>(R.id.wMuscleGroup) as Spinner
val selectedText = spinner.getSelectedItem().toString()
This does not work for me. selectedText shows nothing in a Toast or a println
I also tried this, which I also found many threads for:
val spinner = findViewById<Spinner>(R.id.wMuscleGroup) as Spinner
if (spinner != null) {
val adapter = ArrayAdapter( this, android.R.layout.simple_spinner_item, muscleGroups )
spinner.adapter = adapter
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
val selectedText = muscleGroups[position]
println("Muscle Group selected is $selectedText") // <-- this works
}
override fun onNothingSelected(parent: AdapterView<*>) {
// write code to perform some action
}
}
}
// selectedText is not seen here:
println("Muscle Group selected is $selectedText")
This works and I can see selectedString in my println, in the onItemSelected function inside the block. But, how do I get this value to be seen outside of this block of code? I need to use this value in a class object and a database write. I've tried declaring selectedString outside/above the if (spinner != null), but that does not seem to work either.
Thanks for any help.
Your Spinner does not have a value selected by default. Hence calling spinner.getSelectedItem() returns null and null.toString() returns an empty String.
Your code will work only if the user has selected an option from the Spinner first. You can set a initial value by using spinner.setSelection(position).
If you want to use the selected value outside the selection, you can use a global variable as follows:
val spinner = findViewById<Spinner>(R.id.wMuscleGroup) as Spinner
var selectedText = muscleGroups.first() // as default
if (spinner != null) {
val adapter = ArrayAdapter( this, android.R.layout.simple_spinner_item, muscleGroups )
spinner.adapter = adapter
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
selectedText = muscleGroups[position]
}
override fun onNothingSelected(parent: AdapterView<*>) {
}
}
}
If you want to try something with selectedText, you should use it inside onItemSelected function.
I have 10 items like this in recyclerview. My problem is when I click one item I change the background color but for some reason another item changes its background color too. I don't know why this is happening.
For example, if I click the first item and change the color, the item in position 8 also changes its color. I only want the item that I click on to change its color.
This is my code:
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val titulo = holder.itemView.findViewById(R.id.txt_categoria) as TextView
titulo.text = categories[position].name_category!!
holder.itemView.setOnClickListener{
when{
textView == null ->{
textView = holder.itemView.txt_categoria
textView!!.setBackgroundResource(R.drawable.design_categories_project)
textView!!.setTextColor(Color.WHITE)
fragmentProyectos.filterProjects(categories[position].id_categorie!!,
categories[position].name_category!!)
}
posClicked != position ->{
holder.itemView.txt_categoria.setBackgroundResource(R.drawable.design_categories_project)
holder.itemView.txt_categoria.setTextColor(Color.WHITE)
textView!!.setBackgroundResource(R.drawable.design_categories_project_white)
textView!!.setTextColor((Color.parseColor("#343434")))
textView = holder.itemView.txt_categoria
fragmentProyectos.filterProjects(categories[position].id_categorie!!,
categories[position].name_category!!)
}
else ->{
textView!!.setBackgroundResource(R.drawable.design_categories_project_white)
textView!!.setTextColor((Color.parseColor("#343434")))
textView = null
fragmentProyectos.getData()
}
}
posClicked = position
}
}
Try setting the color like this:
titulo.setTextColor((Color.parseColor("#343434")))
Android Spinner is not working, the API is working and the Spinner's list of items is working. However, the item selection is not working.
class PlayerSignup2Activity : AppCompatActivity() {
private lateinit var positions : List<Position>
val positionSpinner = positionsSpinner
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(com.example.app.R.layout.activity_user_signup2)
//Positions from API
positions = APIService.getPositions(this)
val spinnerAdapter = ArrayAdapter(this, R.layout.spinner_item, positions)
spinnerAdapter.setDropDownViewResource(R.layout.spinner_item)
positionSpinner.adapter = spinnerAdapter
}
Spinner list
After selecting any item
Any idea on how to fix this?!
Try with this
<Spinner
android:id="#+id/spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
In Kotlin
class MainActivity : /** Other Classes, */AdapterView.OnItemSelectedListener {
var list_of_items = arrayOf("Item 1", "Item 2", "Item 3")
override fun onCreate(savedInstanceState: Bundle?) {
spinner!!.setOnItemSelectedListener(this)
// Create an ArrayAdapter using a simple spinner layout and languages array
val aa = ArrayAdapter(this, android.R.layout.simple_spinner_item, list_of_items)
// Set layout to use when the list of choices appear
aa.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
// Set Adapter to Spinner
spinner!!.setAdapter(aa)
}
override fun onItemSelected(arg0: AdapterView<*>, arg1: View, position: Int, id:Long{
// use position to know the selected item
//here you will get the answwer
}
override fun onNothingSelected(arg0: AdapterView<*>) {
}
}
try using prompt for adding title in .XML file
<Spinner
android:id="#+id/spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:prompt="#string/spinner_title"/>
or try adding 1 more item that contains whatever title you want like "select position" on index 0.
positions.add("select position");
positions.add("value 1");
after adding values to list set spinner value to index 0 by default using below code.
mSpinner.setSelection(0) .
and on Item Selected check if index 0 or value is "select position" then ignore selection else perform action you want.
private lateinit var positions : List<Position>
//add dummy data first
positions.add(Position("select position"));
//Positions from API
positions.addAll(APIService.getPositions(this));
I know there have been several questions that dealt with the problem how to add the "Select one..." hint for the Spinner before the first selection is made. But that's not my case.
What I need is to display the hint only when the SpinnerAdapter is empty. By default in such case, nothing happens on click (but that is not the major problem), and most of all, the spinner doesn't display any text, so it looks like this, which obviously doesn't feel right:
Any idea how to simply handle this problem? I've come up with 2 possible solutions, but I don't like any of them very much:
If the SpinnerAdapter is empty, hide the Spinner from the layout and display a TextView with the same background as the Spinner instead.
Implement a custom SpinnerAdapter whose getCount() returns 1 instead of 0 if the internal list is empty, and at the same time, have its getView() return a TextView with the required "Empty" message, possibly grey-coloured. But that would require specific checking if the selected item is not the "Empty" one.
You can use this SpinnerWithHintAdapter class below
class SpinnerWithHintAdapter(context: Context, resource: Int = android.R.layout.simple_spinner_dropdown_item) :
ArrayAdapter<Any>(context, resource) {
override fun isEnabled(position: Int): Boolean {
return position != 0
}
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
return (super.getDropDownView(position, convertView, parent) as TextView).apply {
if (position == 0) {
// Set the hint text color gray
setTextColor(Color.GRAY)
} else {
setTextColor(Color.BLACK)
}
}
}
fun attachTo(spinner: Spinner, itemSelectedCallback: ((Any?) -> Unit)? = null) {
spinner.apply {
adapter = this#SpinnerWithHintAdapter
itemSelectedCallback?.let {
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) {}
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long
) {
val selectedItem = parent?.getItemAtPosition(position)
// If user change the default selection
// First item is disable and it is used for hint
if (position > 0) {
it(selectedItem)
}
}
}
}
}
}
}
How to use? Let's assume I have data class called City
data class City(
val id: Int,
val cityName: String,
val provinceId: Int
) {
/**
* By overriding toString function, you will show the dropdown text correctly
*/
override fun toString(): String {
return cityName
}
}
In the activity, initiate the adapter, add hint(first item), add main items, and finally attach it to your spinner.
SpinnerWithHintAdapter(this#MyActivity)
.apply {
// add hint
add("City")
// add your main items
for (city in cityList) add(city)
// attach this adapter to your spinner
attachTo(yourSpinner) { selectedItem -> // optional item selected listener
selectedItem?.apply {
if (selectedItem is City) {
// do what you want with the selected item
}
}
}
}