androidkotlinspinneradaptergetview

Kotlin: Spinner won't show


I'm migrating my app to Kotlin and a spinner which was previously working fine (while in Java) stopped working in Kotlin.

This is my CustomShareSpinnerAdapter class:

class CustomShareSpinnerAdapter(
    applicationContext: Context?,
    private val shareOptions: Array<String>
) : BaseAdapter() {
    private val inflter: LayoutInflater
    override fun getCount(): Int {
        return shareOptions.size
    }

    override fun getItem(i: Int): Any? {
        return null
    }

    override fun getItemId(i: Int): Long {
        return 0
    }

    @SuppressLint("InflateParams")
    override fun getDropDownView(position: Int, _convertView: View?, parent: ViewGroup): View {
        var convertView = _convertView
        if (convertView == null) {
            val vi =
                parent.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            convertView = vi.inflate(R.layout.share_spinner_row, null)
        }
        val llLayout = super.getDropDownView(position, convertView, parent)
        if (parent.parent!=null)
            roundCorners(parent)
        return llLayout
    }

    private fun roundCorners(parent: ViewGroup) {
        val container2Round = parent.parent as View
        val gd = GradientDrawable(
            GradientDrawable.Orientation.TOP_BOTTOM, intArrayOf(Color.WHITE, Color.WHITE)
        )
        val radius = AWScreen.dp2px(10)
        gd.cornerRadius = radius.toFloat()
        container2Round.background = gd
    }

    override fun getView(i: Int, _view: View?, viewGroup: ViewGroup): View {

        val view = _view ?:
        inflter.inflate(R.layout.share_spinner_row, viewGroup, false)

        val tvShare = view.findViewById<TextView>(R.id.share)
        tvShare.text = shareOptions[i]
        if (shareOptions[i] == "") tvShare.visibility = View.GONE
        setListItemRoundedCorners(tvShare, i)
        if (i == shareOptions.size - 1) {
            val padding = AWScreen.sp2px(10f, view.context)
            tvShare.setPadding(padding, padding, padding, padding)
        }
        return view
    }

    private fun setListItemRoundedCorners(tvShare: TextView, i: Int) {
        if (i == 1) {
            tvShare.setBackgroundResource(R.drawable.rounded_border_top)
        } else {
            if (i == 2) {
                tvShare.setBackgroundResource(R.drawable.rounded_border_bottom)
            }
        }
    }

    init {
        inflter = LayoutInflater.from(applicationContext)
    }
}

share_spinner_row.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/shareLayout"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:orientation="horizontal">

    <TextView
        android:id="@+id/share"
        android:textSize="20sp"
        android:textColor="#000"
        android:paddingTop="10dp"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:paddingBottom="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</LinearLayout>

This is where I set ShareSpinner:

private fun setShareSpinner() {
    val shareOptions = arrayOf(
        "",
        getStringResourceByName("displaythoughtactivity_sharespinner_text0"),
        getStringResourceByName("displaythoughtactivity_sharespinner_text1"),
        getStringResourceByName("displaythoughtactivity_sharespinner_text2")
    )
    val customAdapter = CustomShareSpinnerAdapter(this, shareOptions)
    binding!!.shareSpinner.adapter = customAdapter
    binding!!.shareSpinner.onItemSelectedListener = this
}

onItemSelected:

override fun onItemSelected(arg0: AdapterView<*>, arg1: View, position: Int, id: Long) {
    val shareSpinnerId = R.id.shareSpinner
    val saveSpinnerId = R.id.saveSpinner
    when (arg0.id) {
        shareSpinnerId -> {
            onShareSpinnerItemSelected(position)
            binding!!.shareSpinner.setSelection(0)
        }
        saveSpinnerId -> {
            onSaveSpinnerItemSelected(position)
            binding!!.saveSpinner.setSelection(0)
        }
        else -> loadAnimSpinnerItem(position)
    }
}

The spinner is just not displaying when you click on the share icon.

No exceptions, no crash, no error on Logcat, it just won't show.

I'm quite sure it'll ended being something stupid, but not being able to figure it out.

Edit 1:

On the other hand, even I'm not an expert on the spinner lifecycle, I don't understand why it's passing through getView twice (and not only once) during spinner set and like 20 times from getDropDownView on icon touch when I have only 4 items in my spinner.


Solution

  • Ok, this is how I made it to work:

    getDropDownView:

    @SuppressLint("InflateParams")
    override fun getDropDownView(position: Int, _convertView: View?, parent: ViewGroup): View? {
        val viewHolder = if (_convertView==null) ViewHolder1() else _convertView.tag as ViewHolder1
    
        var view = _convertView
        if (view==null){
            view = inflater.inflate(R.layout.share_spinner_row, parent, false)
            viewHolder.spinnerRow = view.findViewById(R.id.share)
            view!!.tag = viewHolder
        }
    
        val llLayout = super.getDropDownView(position, _convertView, parent)
    
        if (parent.parent!=null)
            roundCorners(parent)
    
        return llLayout
    }
    

    getView:

    override fun getView(i: Int, _view: View?, viewGroup: ViewGroup): View { 
        val viewHolder = if (_view==null) ViewHolder1() else _view.tag as ViewHolder1
    
        var view = _view
        if (view==null){
            view = inflater.inflate(R.layout.share_spinner_row, viewGroup, false)
            viewHolder.spinnerRow = view.findViewById(R.id.share)
            view!!.tag = viewHolder
        }
    
        val tvShare = viewHolder.spinnerRow
        tvShare!!.text = shareOptions[i]
    
        if (shareOptions[i] == "") tvShare.visibility = View.GONE else tvShare.visibility = View.VISIBLE
    
        setListItemRoundedCorners(tvShare, i)
        if (i == shareOptions.size - 1) {
            val padding = AWScreen.sp2px(10f, view.context)
            tvShare.setPadding(padding, padding, padding, padding)
        }
    
        return view
    }
    

    class ViewHolder1:

    class ViewHolder1 {
        var spinnerRow: TextView? = null
    }
    

    Now it shows correctly and with rounded corners as expected.