skydoves / PowerSpinner

🌀 A lightweight dropdown popup spinner, fully customizable with an arrow and animations for Android.
Apache License 2.0
1.22k stars 116 forks source link

getting null error on passing object list to spinner #42

Closed Miteshmakwana73 closed 4 years ago

Miteshmakwana73 commented 4 years ago

error

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.gueyedeapp, PID: 13713
    java.lang.ClassCastException: c.c.a.g.e.a.a$a cannot be cast to java.lang.CharSequence
        at c.g.a.b.z(:43)
        at c.g.a.b.m(:26)
        at androidx.recyclerview.widget.RecyclerView$g.n(:7065)
        at androidx.recyclerview.widget.RecyclerView$g.d(:7107)
        at androidx.recyclerview.widget.RecyclerView$u.F(:6012)
        at androidx.recyclerview.widget.RecyclerView$u.G(:6279)
        at androidx.recyclerview.widget.RecyclerView$u.p(:6118)
        at androidx.recyclerview.widget.RecyclerView$u.o(:6114)
        at androidx.recyclerview.widget.LinearLayoutManager$c.d(:2303)
        at androidx.recyclerview.widget.LinearLayoutManager.r2(:1627)
        at androidx.recyclerview.widget.LinearLayoutManager.U1(:1587)
        at androidx.recyclerview.widget.LinearLayoutManager.X0(:665)
        at androidx.recyclerview.widget.RecyclerView.D(:4134)
        at androidx.recyclerview.widget.RecyclerView.onMeasure(:3540)
        at android.view.View.measure(View.java:17765)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5620)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:454)
        at android.view.View.measure(View.java:17765)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2349)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1373)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1597)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1251)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6438)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:795)
        at android.view.Choreographer.doCallbacks(Choreographer.java:598)
        at android.view.Choreographer.doFrame(Choreographer.java:567)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:781)
        at android.os.Handler.handleCallback(Handler.java:810)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:189)
        at android.app.ActivityThread.main(ActivityThread.java:5532)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:950)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:745)

this what i done so far

xml

<com.skydoves.powerspinner.PowerSpinnerView
                    android:id="@+id/spinnerCategory"
                    style="@style/fontRegular"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center_vertical"
                    android:layout_marginStart="@dimen/_10sdp"
                    android:layout_marginTop="@dimen/_20sdp"
                    android:layout_marginEnd="@dimen/_10sdp"
                    android:background="@drawable/background_button_white_20dp"
                    android:drawableEnd="@drawable/ic_search_gray"
                    android:drawablePadding="@dimen/_7sdp"
                    android:elevation="1dp"
                    android:hint="@string/category"
                    android:padding="@dimen/_9sdp"
                    android:textColor="@color/black"
                    android:textSize="@dimen/_12ssp"
                    app:spinner_arrow_gravity="end"
                    app:spinner_arrow_padding="8dp"
                    app:spinner_divider_color="@color/black"
                    app:spinner_divider_show="true"
                    app:spinner_divider_size="0.4dp"
                    app:spinner_popup_animation="dropdown"
                    app:spinner_popup_elevation="14dp" />

java

override fun setCategoryList(response: CategoryListModel) {
        activity?.hideKeybord()
        hideProgressBar()
        mList.clear()
        mList.addAll(response.data)
        binding.spinnerCategory.apply {
            setItems(mList)
            setOnSpinnerItemSelectedListener<CategoryListModel.CategoryListData> { _, item ->
                binding.spinnerCategory.hint = item.categoryName
                Toast.makeText(context, item.categoryName, Toast.LENGTH_SHORT).show()
            }
            lifecycleOwner = this@SearchFragment
            preferenceName = getString(R.string.category)
        }
}

I am setting spinner when I get a response from API

this is my model class


import com.google.gson.annotations.SerializedName

data class CategoryListModel(
    @SerializedName("data")
    val `data`: List<CategoryListData> = listOf(),
    @SerializedName("FLAG")
    val fLAG: Boolean = false,
    @SerializedName("IS_ACTIVE")
    val iSACTIVE: Int = 0,
    @SerializedName("MESSAGE")
    val mESSAGE: String = ""
) {
    data class CategoryListData(
        @SerializedName("category_name")
        val categoryName: String = "",
        @SerializedName("created_by")
        val createdBy: String = "",
        @SerializedName("created_date")
        val createdDate: String = "",
        @SerializedName("id")
        val id: String = "",
        @SerializedName("modified_by")
        val modifiedBy: String = "",
        @SerializedName("modified_date")
        val modifiedDate: String = "",
        @SerializedName("status")
        val status: String = ""
    )
}

please suggest me why I am getting an error

skydoves commented 4 years ago

Hi, It seems to use a default adapter. The default adapter can be set only Charsequence type items. So If you want to use your custom model as a data list, create a new custom adapter.

Miteshmakwana73 commented 4 years ago

can you provide a full custom adapter class so everyone understands better and proper or any example?

skydoves commented 4 years ago

This is an example. The customized adapter is not much different from the RecyclerView.Adapter because a customized adapter must extend it. The main difference is implementing the PowerSpinnerInterface interface. You can reference this example codes.

Miteshmakwana73 commented 4 years ago

thank you it's working now this is my code of the custom adapter so anyone can take reference from it.

bind spinner

binding.spinnerCategory.apply {
            setSpinnerAdapter(MySpinnerAdapter(this))
            setItems(mList)
            setOnSpinnerItemSelectedListener<CategoryListModel.CategoryListData> { _, item ->
                binding.spinnerCategory.hint = item.categoryName
                Toast.makeText(context, item.categoryName, Toast.LENGTH_SHORT).show()
            }
            lifecycleOwner = this@SearchFragment
            preferenceName = getString(R.string.category)
        }

adapter

inner class MySpinnerAdapter(
        powerSpinnerView: PowerSpinnerView
    ) : RecyclerView.Adapter<MySpinnerAdapter.ViewHolder>(),
        PowerSpinnerInterface<CategoryListModel.CategoryListData> {

        override val spinnerView: PowerSpinnerView = powerSpinnerView
        override var onSpinnerItemSelectedListener: OnSpinnerItemSelectedListener<CategoryListModel.CategoryListData>? =
            null
        private val spinnerItems: MutableList<CategoryListModel.CategoryListData> = arrayListOf()

        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            val model = spinnerItems[holder.adapterPosition]
            holder.itemView.tvItem.setText(model.categoryName)
            holder.itemView.setOnClickListener {
                notifyItemSelected(position)
            }
        }

        // we must call the spinnerView.notifyItemSelected method to let PowerSpinnerView know about changed information.
        override fun notifyItemSelected(index: Int) {
            this.spinnerView.notifyItemSelected(index, spinnerItems[index].categoryName)
            this.onSpinnerItemSelectedListener?.onItemSelected(index, spinnerItems[index])
        }

        override fun onCreateViewHolder(
            parent: ViewGroup,
            viewType: Int
        ): ViewHolder {
            var mInflater: LayoutInflater = context!!.getSystemService(Activity.LAYOUT_INFLATER_SERVICE) as LayoutInflater

            val v =
                mInflater.inflate(R.layout.raw_category_list, parent, false)
            return ViewHolder(
                v
            )
        }

        override fun getItemCount(): Int {
            return this.spinnerItems.size
        }

        override fun setItems(itemList: List<CategoryListModel.CategoryListData>) {
            this.spinnerItems.clear()
            this.spinnerItems.addAll(itemList)
            notifyDataSetChanged()
        }

        inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
    }

@skydoves please correct me if anything is wrong