Android extended Spinner is not responding to tap

2019-08-17 11:17发布

I want to use a centered spinner where the width of the spinner is only as wide as the selected item text. From my research it seems that this is not natively supported out of the box with an attribute so I found another StackOverflow question/answer and tried implementing that but ran into some issues with it.

So I took option 1 from this SO response and implemented it in Kotlin and It's not working for me

class DynamicWidthSpinner @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : AppCompatSpinner(context, attrs, defStyleAttr) {

    override fun setAdapter(adapter: SpinnerAdapter?) {
        super.setAdapter(if (adapter != null) WrapperSpinnerAdapter(adapter) else null)
    }

    inner class WrapperSpinnerAdapter(val baseAdapter: SpinnerAdapter) : SpinnerAdapter {

        override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
            return baseAdapter.getView(selectedItemPosition, convertView, parent)
        }

        override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
            return baseAdapter.getDropDownView(position, convertView, parent)
        }

        override fun getCount(): Int = baseAdapter.count
        override fun getItem(position: Int): Any = baseAdapter.getItem(position)
        override fun getItemId(position: Int): Long = baseAdapter.getItemId(position)
        override fun getItemViewType(position: Int): Int = baseAdapter.getItemViewType(position)
        override fun getViewTypeCount(): Int = baseAdapter.viewTypeCount
        override fun hasStableIds(): Boolean =  baseAdapter.hasStableIds()
        override fun isEmpty(): Boolean = baseAdapter.isEmpty

        override fun registerDataSetObserver(observer: DataSetObserver) {
            baseAdapter.registerDataSetObserver(observer)
        }

        override fun unregisterDataSetObserver(observer: DataSetObserver) {
            baseAdapter.unregisterDataSetObserver(observer)
        }
    }
}

and in my MainActivity I'm doing this from onCreate

        val spinner: DynamicWidthSpinner = findViewById(R.id.global_toolbar_location_spinner)

        val tempLocationList = ArrayList<String>()
        tempLocationList.add("Test1")
        tempLocationList.add("Much longer test string 2")

        spinner.adapter = ArrayAdapter(
            this,
            R.layout.global_toolbar_spinner_item,
            tempLocationList
        )

        spinner.onItemSelectedListener = object : OnItemSelectedListener {
            override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, arg3: Long) {
                // TODO: do stuff on selection here
            }

            override fun onNothingSelected(arg0: AdapterView<*>) {
                // TODO: do nothing... yet
            }
        }

        spinner.setSelection(0)

and I am using my custom Spinner in the layout xml (ommitting everything else that is not necessary because I am able to get it work just fine using the native <Spinner> or androidx compat Spinner

<com.blablabla.app.ui.DynamicWidthSpinner
        android:id="@+id/global_toolbar_location_spinner"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:spinnerMode="dialog"
        />

What I see is just the first item "Test1" and nothing happens when I tap on it and arrow seems to have disappeared now as well

1条回答
三岁会撩人
2楼-- · 2019-08-17 11:51

I figured out the issue. Turns out that this is one of those cases where the @JvmOverloads doesn't work. Once I converted it to the multiple constructor kotlin syntax it worked without a problem


class DynamicWidthSpinner : AppCompatSpinner {

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    ...
}


查看更多
登录 后发表回答