Home > front end >  androidx.recyclerview.widget.RecyclerView cannot be cast to androidx.cardview.widget.CardView - Drag
androidx.recyclerview.widget.RecyclerView cannot be cast to androidx.cardview.widget.CardView - Drag

Time:06-24

I am trying to build a drag and drop activity, where user can drag an item from Recyclerview to a card view, i am following android's drag and drop documentation,

the dragging is working fine, have shadows, but when i drop the item to one of the cardviews, it throwing the error,androidx.recyclerview.widget.RecyclerView cannot be cast to androidx.cardview.widget.CardView i have worked it in the past, but it was dragging item from textView to ConstraintLayout.

The error is in TrueOrFalseActivity

enter image description here

Adapterclass

class StatementAdapter(
    private val context: Context,
    private val statementList: ArrayList<Statement>
) :
    RecyclerView.Adapter<StatementAdapter.StatementViewHolder>() {

    private var mListener: OnItemLongClickListener? = null

    interface OnItemLongClickListener {
        fun onItemLongClick(view: View)

    }

    fun setOnItemLongClickListener(listener: OnItemLongClickListener) {
        mListener = listener
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StatementViewHolder {

        val layoutInflater = LayoutInflater.from(parent.context)
        val statementBinding: StatementBinding =
            DataBindingUtil.inflate(layoutInflater, R.layout.statement_list, parent, false)

        return StatementViewHolder(statementBinding, mListener)

    }


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

    override fun onBindViewHolder(holder: StatementViewHolder, position: Int) {
        val statementViewModel = statementList[position]
        holder.bind(statementViewModel)


    }

    class StatementViewHolder(
        private val statementBinding: StatementBinding,
        private val listener: OnItemLongClickListener?

    ) : RecyclerView.ViewHolder(statementBinding.root) {

        fun bind(statementViewModel: Statement) {
            this.statementBinding.statementModel = statementViewModel

            itemView.setOnLongClickListener {
                listener?.onItemLongClick(itemView)
                true
            }

            statementBinding.executePendingBindings()
        }
    }

}

Activity

class TrueOrFalseActivity : AppCompatActivity(), StatementAdapter.OnItemLongClickListener {
    private lateinit var trueOrFalseBinding: ActivityTrueOrFalseBinding
    private var rvStatement: RecyclerView? = null
    private var statementAdapter: StatementAdapter? = null

    private val dragMessage = "Added"
    private val inBucket = "in bucket"
    private val offBucket = "not in bucket"

    private lateinit var draggingItem : View

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        trueOrFalseBinding = ActivityTrueOrFalseBinding.inflate(layoutInflater)
        setContentView(trueOrFalseBinding.root)

        rvStatement = findViewById(R.id.rvStatement)
        val statementViewModel = ViewModelProvider(this).get(StatementViewModel::class.java)
        statementViewModel.generateStatement()

        statementViewModel.newMStatementList.observe(this) {
            statementAdapter = StatementAdapter(this@TrueOrFalseActivity, it)
            rvStatement!!.layoutManager = LinearLayoutManager(this@TrueOrFalseActivity)
            rvStatement!!.adapter = statementAdapter
            statementAdapter?.setOnItemLongClickListener(this)



        }

        // trueOrFalseBinding.cardTruthBox
        trueOrFalseBinding.cardTruthBox.setOnDragListener(statementDragListener)
//        trueOrFalseBinding.cardFalseBox.setOnDragListener(statementDragListener)
    }

    private val statementDragListener = View.OnDragListener { view, dragEvent ->

//        val draggableItem = dragEvent.localState as View

        val draggableItem = draggingItem

        when (dragEvent.action) {
            DragEvent.ACTION_DRAG_STARTED -> {
                true
            }
            DragEvent.ACTION_DRAG_ENTERED -> {
                trueOrFalseBinding.cardTruthBox.alpha = 0.3f
                true
            }
            DragEvent.ACTION_DRAG_LOCATION -> {
                true
            }
            DragEvent.ACTION_DRAG_EXITED -> {
                trueOrFalseBinding.cardTruthBox.alpha = 1.0f
                draggableItem.visibility = View.INVISIBLE
                view.invalidate()
                true
            }
            DragEvent.ACTION_DROP -> {
                trueOrFalseBinding.cardTruthBox.alpha = 1.0f

//                if (dragEvent.clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)){
//                    val draggedData = dragEvent.clipData.getItemAt(0).text
//                }
                //re-position the card in the updated x, y co-ordinates
                // with mask center position pointing to new x,y co-ordinates
                draggableItem.x = dragEvent.x - (draggableItem.width / 2)
                draggableItem.y = dragEvent.y - (draggableItem.height / 2)

                //on drop event remove the card from parent viewGroup
                val parent = draggableItem.parent as CardView
                parent.removeView(draggableItem)

                val dropArea = view as CardView
                dropArea.addView(draggableItem)

                checkIfCardIsOnBucket(dragEvent)

                true
            }
            DragEvent.ACTION_DRAG_ENDED -> {
                draggableItem.visibility = View.INVISIBLE
                view.invalidate()
//                statementAdapter?.notifyDataSetChanged()
                true
            }
            else -> {
                false
            }
        }
    }

    private fun checkIfCardIsOnBucket(dragEvent: DragEvent?) {

        val bucketXStart = trueOrFalseBinding.cardTruthBox.x
        val bucketYStart = trueOrFalseBinding.cardTruthBox.y

        val faceXEnd = bucketXStart   trueOrFalseBinding.cardTruthBox.width
        val faceYEnd = bucketYStart   trueOrFalseBinding.cardTruthBox.height

        val toastMsg =
            if (dragEvent!!.x in bucketXStart..faceXEnd && dragEvent.y in bucketYStart..faceYEnd) {
                inBucket
            } else {
                offBucket
            }
        //4
        Toast.makeText(this, toastMsg, Toast.LENGTH_SHORT).show()
    }

    override fun onItemLongClick(view: View) {
        //Toast.makeText(this@TrueOrFalseActivity, itemView.toString(), Toast.LENGTH_LONG).show()
        val item = ClipData.Item(dragMessage)
        val dragData = ClipData(
            dragMessage,
            arrayOf(ClipDescription.MIMETYPE_TEXT_PLAIN),
            item
        )
        val myShadow = MyDragShadowBuilder(view)
        view.startDragAndDrop(dragData, myShadow, null, 0)
        draggingItem = view
    }
}

private class MyDragShadowBuilder(v: View) : View.DragShadowBuilder(v) {
    private val shadow = ColorDrawable(Color.LTGRAY)

    override fun onProvideShadowMetrics(size: Point?, touch: Point?) {

        val width: Int = view.width
        val height: Int = view.height
        shadow.setBounds(0, 0, width, height)
        size?.set(width, height)
        touch?.set(width, height)
    }

    override fun onDrawShadow(canvas: Canvas?) {
        super.onDrawShadow(canvas)
    }
}

 java.lang.ClassCastException: androidx.recyclerview.widget.RecyclerView cannot be cast to androidx.cardview.widget.CardView
        at com.example.simmone.view.TrueOrFalseActivity.statementDragListener$lambda-1(TrueOrFalseActivity.kt:94)
        at com.example.simmone.view.TrueOrFalseActivity.$r8$lambda$Uf0--ln2uKD0LrTLx3eNYF0CoE8(Unknown Source:0)
        at com.example.simmone.view.TrueOrFalseActivity$$ExternalSyntheticLambda0.onDrag(Unknown Source:2)
        at android.view.View.callDragEventHandler(View.java:26592)
        at android.view.View.dispatchDragEvent(View.java:26583)
        at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1837)
        at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1819)
        at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1819)
        at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1819)
        at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1819)
        at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1819)
        at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1819)
        at android.view.ViewRootImpl.handleDragEvent(ViewRootImpl.java:7258)
        at android.view.ViewRootImpl.access$1200(ViewRootImpl.java:191)
        at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:5098)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

StackTrace

 java.lang.ClassCastException: androidx.recyclerview.widget.RecyclerView cannot be cast to androidx.cardview.widget.CardView
        at com.example.simmone.view.TrueOrFalseActivity.statementDragListener$lambda-1(TrueOrFalseActivity.kt:94)
        at com.example.simmone.view.TrueOrFalseActivity.$r8$lambda$Uf0--ln2uKD0LrTLx3eNYF0CoE8(Unknown Source:0)
        at com.example.simmone.view.TrueOrFalseActivity$$ExternalSyntheticLambda0.onDrag(Unknown Source:2)
        at android.view.View.callDragEventHandler(View.java:26592)
        at android.view.View.dispatchDragEvent(View.java:26583)
        at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1837)
        at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1819)
        at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1819)
        at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1819)
        at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1819)
        at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1819)
        at android.view.ViewGroup.dispatchDragEvent(ViewGroup.java:1819)
        at android.view.ViewRootImpl.handleDragEvent(ViewRootImpl.java:7258)
        at android.view.ViewRootImpl.access$1200(ViewRootImpl.java:191)
        at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:5098)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

Is this possible to achieve, or any other ways to do this?

CodePudding user response:

Try

val parent = draggableItem.parent as RecyclerView        
  • Related