I have set an ItemClickLister for my RecyclerView like this:
ItemClickSupport.addTo(recyclerView!!).setOnItemClickListener(
object : ItemClickSupport.OnItemClickListener {
override fun onItemClicked(recyclerView: RecyclerView?, position: Int, v: View?) {
val row = recyclerView!!.getChildAt(position)
val el = row.findViewById(R.id.active_expandablelayout) as ExpandableLayout
if (el.isExpanded) {
el.collapse()
} else {
el.expand()
}
}
}
)
using the ItemClickSupport library which I translated into Kotlin.
I get an error on object
(line 2) that says:
object must be declared abstract or implement abstract member.
I'm really new to Kotlin and I couldn't find any solution here on SO either.
Any help is greatly appreciated.
Edit:
Here is my ItemClickSupport.kt
:
class ItemClickSupport private constructor(private val mRecyclerView: RecyclerView) {
private var mOnItemClickListener: OnItemClickListener? = null
private var mOnItemLongClickListener: OnItemLongClickListener? = null
private val mOnClickListener = View.OnClickListener { v ->
if (mOnItemClickListener != null) {
val holder = mRecyclerView.getChildViewHolder(v)
mOnItemClickListener!!.onItemClicked(mRecyclerView, holder.adapterPosition, v)
}
}
private val mOnLongClickListener = View.OnLongClickListener { v ->
if (mOnItemLongClickListener != null) {
val holder = mRecyclerView.getChildViewHolder(v)
return@OnLongClickListener mOnItemLongClickListener!!.onItemLongClicked(mRecyclerView, holder.adapterPosition, v)
}
false
}
private val mAttachListener = object : RecyclerView.OnChildAttachStateChangeListener {
override fun onChildViewAttachedToWindow(view: View) {
if (mOnItemClickListener != null) {
view.setOnClickListener(mOnClickListener)
}
if (mOnItemLongClickListener != null) {
view.setOnLongClickListener(mOnLongClickListener)
}
}
override fun onChildViewDetachedFromWindow(view: View) {
}
}
init {
mRecyclerView.setTag(R.id.item_click_support, this)
mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener)
}
fun setOnItemClickListener(listener: OnItemClickListener): ItemClickSupport {
mOnItemClickListener = listener
return this
}
fun setOnItemLongClickListener(listener: OnItemLongClickListener): ItemClickSupport {
mOnItemLongClickListener = listener
return this
}
private fun detach(view: RecyclerView) {
view.removeOnChildAttachStateChangeListener(mAttachListener)
view.setTag(R.id.item_click_support, null)
}
interface OnItemClickListener {
fun onItemClicked(recyclerView: RecyclerView, position: Int, v: View)
}
interface OnItemLongClickListener {
fun onItemLongClicked(recyclerView: RecyclerView, position: Int, v: View): Boolean
}
companion object {
fun addTo(view: RecyclerView): ItemClickSupport {
var support: ItemClickSupport? = view.getTag(R.id.item_click_support) as ItemClickSupport
if (support == null) {
support = ItemClickSupport(view)
}
return support
}
fun removeFrom(view: RecyclerView): ItemClickSupport {
val support = view.getTag(R.id.item_click_support) as ItemClickSupport
support?.detach(view)
return support
}
}
}
This is a screenshot with the whole error and where it happens:
In Kotlin, we cannot create an instance of an abstract class. Abstract classes can only be implemented by another class which should be abstract in nature. In order to use an abstract class, we need to create another class and inherit the abstract class.
A Kotlin abstract class is similar to Java abstract class which can not be instantiated. This means we cannot create objects of an abstract class. However, we can inherit subclasses from a Kotlin abstract class. A Kotlin abstract class is declared using the abstract keyword in front of class name.
Interfaces in Kotlin can contain declarations of abstract methods, as well as method implementations. What makes them different from abstract classes is that interfaces cannot store state. They can have properties, but these need to be abstract or provide accessor implementations.
Object expressions Object expressions create objects of anonymous classes, that is, classes that aren't explicitly declared with the class declaration. Such classes are useful for one-time use. You can define them from scratch, inherit from existing classes, or implement interfaces.
Your interface and method signatures do not match. Your interface is declaring one function as:
fun onItemClicked(recyclerView: RecyclerView, position: Int, v: View)
And you override it as:
fun onItemClicked(recyclerView: RecyclerView?, position: Int, v: View?)
Those are not the same method signatures.
If this was a Java interface, you can override while changing nullability because it isn't clear what the nullability is (given no annotations in the Java code). But since you ported it to a Kotlin interface you must override using the same exact signature. You instead made both RecyclerView?
and View?
nullable which results in a mismatch to the original signature. Change your overridden function to be:
override fun onItemClicked(recyclerView: RecyclerView, position: Int, v: View)
Since this is a Kotin interface, you cannot use the SAM conversion to a Lambda so that is why the other answer previously provided does not work. If this was a Java interface, you could do that. You can track SAM conversions for Kotlin interfaces in KT-7770.
If you wanted this code to be more idiomatic Kotlin you would want function references or lambdas instead of interfaces, and you should just do that instead of relying on SAM conversion. You can read more about that in Higher-Order Functions and Lambdas. This is outside the scope of your question to go into more detail.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With