@ -15,67 +15,67 @@ import java.util.*
*
*
* 通用的adapter 可添加header , footer , 以及不同类型item
* 通用的adapter 可添加header , footer , 以及不同类型item
* /
* /
abstract class CommonRecyclerAdapter < ITEM > ( protected val context : Context ) :
abstract class CommonRecyclerAdapter < ITEM > ( protected val context : Context ) :
RecyclerView . Adapter < ItemViewHolder > ( ) {
RecyclerView . Adapter < ItemViewHolder > ( ) {
constructor ( context : Context , vararg delegates : ItemViewDelegate < ITEM > ) : this ( context ) {
constructor ( context : Context , vararg delegates : ItemViewDelegate < ITEM > ) : this ( context ) {
addItemViewDelegates ( * delegates )
addItemViewDelegates ( * delegates )
}
}
constructor (
constructor (
context : Context ,
context : Context ,
vararg delegates : Pair < Int , ItemViewDelegate < ITEM > >
vararg delegates : Pair < Int , ItemViewDelegate < ITEM > >
) : this ( context ) {
) : this ( context ) {
addItemViewDelegates ( * delegates )
addItemViewDelegates ( * delegates )
}
}
private val inflater : LayoutInflater = LayoutInflater . from ( context )
private val inflater : LayoutInflater = LayoutInflater . from ( context )
private var headerItems : SparseArray < View > ? = null
private var headerItems : SparseArray < View > ? = null
private var footerItems : SparseArray < View > ? = null
private var footerItems : SparseArray < View > ? = null
private val itemDelegates : HashMap < Int , ItemViewDelegate < ITEM > > = hashMapOf ( )
private val itemDelegates : HashMap < Int , ItemViewDelegate < ITEM > > = hashMapOf ( )
private val items : MutableList < ITEM > = mutableListOf ( )
private val items : MutableList < ITEM > = mutableListOf ( )
private val lock = Object ( )
private val lock = Object ( )
private var itemClickListener : ( ( holder : ItemViewHolder , item : ITEM ) -> Unit ) ? = null
private var itemClickListener : ( ( holder : ItemViewHolder , item : ITEM ) -> Unit ) ? = null
private var itemLongClickListener : ( ( holder : ItemViewHolder , item : ITEM ) -> Boolean ) ? = null
private var itemLongClickListener : ( ( holder : ItemViewHolder , item : ITEM ) -> Boolean ) ? = null
// 这个用Kotlin的setter就行了, 不需要手动开一个函数进行设置
// 这个用Kotlin的setter就行了, 不需要手动开一个函数进行设置
var itemAnimation : ItemAnimation ? = null
var itemAnimation : ItemAnimation ? = null
fun setOnItemClickListener ( listener : ( holder : ItemViewHolder , item : ITEM ) -> Unit ) {
fun setOnItemClickListener ( listener : ( holder : ItemViewHolder , item : ITEM ) -> Unit ) {
itemClickListener = listener
itemClickListener = listener
}
}
fun setOnItemLongClickListener ( listener : ( holder : ItemViewHolder , item : ITEM ) -> Boolean ) {
fun setOnItemLongClickListener ( listener : ( holder : ItemViewHolder , item : ITEM ) -> Boolean ) {
itemLongClickListener = listener
itemLongClickListener = listener
}
}
fun bindToRecyclerView ( recyclerView : RecyclerView ) {
fun bindToRecyclerView ( recyclerView : RecyclerView ) {
recyclerView . adapter = this
recyclerView . adapter = this
}
}
fun < DELEGATE : ItemViewDelegate < ITEM > > addItemViewDelegate ( viewType : Int , delegate : DELEGATE ) {
fun < DELEGATE : ItemViewDelegate < ITEM > > addItemViewDelegate ( viewType : Int , delegate : DELEGATE ) {
itemDelegates [ viewType ] = delegate
itemDelegates [ viewType ] = delegate
}
}
fun < DELEGATE : ItemViewDelegate < ITEM > > addItemViewDelegate ( delegate : DELEGATE ) {
fun < DELEGATE : ItemViewDelegate < ITEM > > addItemViewDelegate ( delegate : DELEGATE ) {
itemDelegates [ itemDelegates . size ] = delegate
itemDelegates [ itemDelegates . size ] = delegate
}
}
fun < DELEGATE : ItemViewDelegate < ITEM > > addItemViewDelegates ( vararg delegates : DELEGATE ) {
fun < DELEGATE : ItemViewDelegate < ITEM > > addItemViewDelegates ( vararg delegates : DELEGATE ) {
delegates . forEach {
delegates . forEach {
addItemViewDelegate ( it )
addItemViewDelegate ( it )
}
}
}
}
fun addItemViewDelegates ( vararg delegates : Pair < Int , ItemViewDelegate < ITEM > > ) =
fun addItemViewDelegates ( vararg delegates : Pair < Int , ItemViewDelegate < ITEM > > ) =
delegates . forEach {
delegates . forEach {
addItemViewDelegate ( it . first , it . second )
addItemViewDelegate ( it . first , it . second )
}
}
fun addHeaderView ( header : View ) {
fun addHeaderView ( header : View ) {
synchronized ( lock ) {
synchronized ( lock ) {
if ( headerItems == null ) {
if ( headerItems == null ) {
@ -88,7 +88,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
}
}
}
}
}
}
fun addFooterView ( footer : View ) =
fun addFooterView ( footer : View ) =
synchronized ( lock ) {
synchronized ( lock ) {
if ( footerItems == null ) {
if ( footerItems == null ) {
@ -100,8 +100,8 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
notifyItemInserted ( index )
notifyItemInserted ( index )
}
}
}
}
fun removeHeaderView ( header : View ) =
fun removeHeaderView ( header : View ) =
synchronized ( lock ) {
synchronized ( lock ) {
headerItems ?. let {
headerItems ?. let {
@ -112,7 +112,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
}
}
}
}
}
}
fun removeFooterView ( footer : View ) =
fun removeFooterView ( footer : View ) =
synchronized ( lock ) {
synchronized ( lock ) {
footerItems ?. let {
footerItems ?. let {
@ -123,7 +123,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
}
}
}
}
}
}
fun setItems ( items : List < ITEM > ? ) {
fun setItems ( items : List < ITEM > ? ) {
synchronized ( lock ) {
synchronized ( lock ) {
if ( this . items . isNotEmpty ( ) ) {
if ( this . items . isNotEmpty ( ) ) {
@ -135,7 +135,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
notifyDataSetChanged ( )
notifyDataSetChanged ( )
}
}
}
}
fun setItems ( items : List < ITEM > ? , diffResult : DiffUtil . DiffResult ) {
fun setItems ( items : List < ITEM > ? , diffResult : DiffUtil . DiffResult ) {
synchronized ( lock ) {
synchronized ( lock ) {
if ( this . items . isNotEmpty ( ) ) {
if ( this . items . isNotEmpty ( ) ) {
@ -147,7 +147,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
diffResult . dispatchUpdatesTo ( this )
diffResult . dispatchUpdatesTo ( this )
}
}
}
}
fun setItem ( position : Int , item : ITEM ) {
fun setItem ( position : Int , item : ITEM ) {
synchronized ( lock ) {
synchronized ( lock ) {
val oldSize = getActualItemCount ( )
val oldSize = getActualItemCount ( )
@ -157,7 +157,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
}
}
}
}
}
}
fun addItem ( item : ITEM ) {
fun addItem ( item : ITEM ) {
synchronized ( lock ) {
synchronized ( lock ) {
val oldSize = getActualItemCount ( )
val oldSize = getActualItemCount ( )
@ -166,7 +166,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
}
}
}
}
}
}
fun addItems ( position : Int , newItems : List < ITEM > ) {
fun addItems ( position : Int , newItems : List < ITEM > ) {
synchronized ( lock ) {
synchronized ( lock ) {
if ( this . items . addAll ( position , newItems ) ) {
if ( this . items . addAll ( position , newItems ) ) {
@ -174,7 +174,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
}
}
}
}
}
}
fun addItems ( newItems : List < ITEM > ) {
fun addItems ( newItems : List < ITEM > ) {
synchronized ( lock ) {
synchronized ( lock ) {
val oldSize = getActualItemCount ( )
val oldSize = getActualItemCount ( )
@ -187,7 +187,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
}
}
}
}
}
}
fun removeItem ( position : Int ) {
fun removeItem ( position : Int ) {
synchronized ( lock ) {
synchronized ( lock ) {
if ( this . items . removeAt ( position ) != null ) {
if ( this . items . removeAt ( position ) != null ) {
@ -195,7 +195,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
}
}
}
}
}
}
fun removeItem ( item : ITEM ) {
fun removeItem ( item : ITEM ) {
synchronized ( lock ) {
synchronized ( lock ) {
if ( this . items . remove ( item ) ) {
if ( this . items . remove ( item ) ) {
@ -203,7 +203,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
}
}
}
}
}
}
fun removeItems ( items : List < ITEM > ) {
fun removeItems ( items : List < ITEM > ) {
synchronized ( lock ) {
synchronized ( lock ) {
if ( this . items . removeAll ( items ) ) {
if ( this . items . removeAll ( items ) ) {
@ -211,7 +211,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
}
}
}
}
}
}
fun swapItem ( oldPosition : Int , newPosition : Int ) {
fun swapItem ( oldPosition : Int , newPosition : Int ) {
synchronized ( lock ) {
synchronized ( lock ) {
val size = getActualItemCount ( )
val size = getActualItemCount ( )
@ -224,7 +224,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
}
}
}
}
}
}
fun updateItem ( item : ITEM ) =
fun updateItem ( item : ITEM ) =
synchronized ( lock ) {
synchronized ( lock ) {
val index = this . items . indexOf ( item )
val index = this . items . indexOf ( item )
@ -233,7 +233,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
notifyItemChanged ( index )
notifyItemChanged ( index )
}
}
}
}
fun updateItem ( position : Int , payload : Any ) =
fun updateItem ( position : Int , payload : Any ) =
synchronized ( lock ) {
synchronized ( lock ) {
val size = getActualItemCount ( )
val size = getActualItemCount ( )
@ -241,7 +241,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
notifyItemChanged ( position + getHeaderCount ( ) , payload )
notifyItemChanged ( position + getHeaderCount ( ) , payload )
}
}
}
}
fun updateItems ( fromPosition : Int , toPosition : Int , payloads : Any ) =
fun updateItems ( fromPosition : Int , toPosition : Int , payloads : Any ) =
synchronized ( lock ) {
synchronized ( lock ) {
val size = getActualItemCount ( )
val size = getActualItemCount ( )
@ -253,43 +253,43 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
)
)
}
}
}
}
fun clearItems ( ) =
fun clearItems ( ) =
synchronized ( lock ) {
synchronized ( lock ) {
this . items . clear ( )
this . items . clear ( )
notifyDataSetChanged ( )
notifyDataSetChanged ( )
}
}
fun isEmpty ( ) = items . isEmpty ( )
fun isEmpty ( ) = items . isEmpty ( )
fun isNotEmpty ( ) = items . isNotEmpty ( )
fun isNotEmpty ( ) = items . isNotEmpty ( )
/ * *
/ * *
* 除去header和footer
* 除去header和footer
* /
* /
fun getActualItemCount ( ) = items . size
fun getActualItemCount ( ) = items . size
fun getHeaderCount ( ) = headerItems ?. size ( ) ?: 0
fun getHeaderCount ( ) = headerItems ?. size ( ) ?: 0
fun getFooterCount ( ) = footerItems ?. size ( ) ?: 0
fun getFooterCount ( ) = footerItems ?. size ( ) ?: 0
fun getItem ( position : Int ) : ITEM ? = items . getOrNull ( position )
fun getItem ( position : Int ) : ITEM ? = items . getOrNull ( position )
fun getItemByLayoutPosition ( position : Int ) = items . getOrNull ( position - getHeaderCount ( ) )
fun getItemByLayoutPosition ( position : Int ) = items . getOrNull ( position - getHeaderCount ( ) )
fun getItems ( ) : List < ITEM > = items
fun getItems ( ) : List < ITEM > = items
protected open fun getItemViewType ( item : ITEM , position : Int ) = 0
protected open fun getItemViewType ( item : ITEM , position : Int ) = 0
/ * *
/ * *
* grid 模式下使用
* grid 模式下使用
* /
* /
protected open fun getSpanSize ( item : ITEM , viewType : Int , position : Int ) = 1
protected open fun getSpanSize ( item : ITEM , viewType : Int , position : Int ) = 1
final override fun getItemCount ( ) = getActualItemCount ( ) + getHeaderCount ( ) + getFooterCount ( )
final override fun getItemCount ( ) = getActualItemCount ( ) + getHeaderCount ( ) + getFooterCount ( )
final override fun getItemViewType ( position : Int ) = when {
final override fun getItemViewType ( position : Int ) = when {
isHeader ( position ) -> TYPE _HEADER _VIEW + position
isHeader ( position ) -> TYPE _HEADER _VIEW + position
isFooter ( position ) -> TYPE _FOOTER _VIEW + position - getActualItemCount ( ) - getHeaderCount ( )
isFooter ( position ) -> TYPE _FOOTER _VIEW + position - getActualItemCount ( ) - getHeaderCount ( )
@ -297,16 +297,16 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
getItemViewType ( it , getActualPosition ( position ) )
getItemViewType ( it , getActualPosition ( position ) )
} ?: 0
} ?: 0
}
}
override fun onCreateViewHolder ( parent : ViewGroup , viewType : Int ) = when {
override fun onCreateViewHolder ( parent : ViewGroup , viewType : Int ) = when {
viewType < TYPE _HEADER _VIEW + getHeaderCount ( ) -> {
viewType < TYPE _HEADER _VIEW + getHeaderCount ( ) -> {
ItemViewHolder ( headerItems !! . get ( viewType ) )
ItemViewHolder ( headerItems !! . get ( viewType ) )
}
}
viewType >= TYPE _FOOTER _VIEW -> {
viewType >= TYPE _FOOTER _VIEW -> {
ItemViewHolder ( footerItems !! . get ( viewType ) )
ItemViewHolder ( footerItems !! . get ( viewType ) )
}
}
else -> {
else -> {
val holder = ItemViewHolder (
val holder = ItemViewHolder (
inflater . inflate (
inflater . inflate (
@ -315,10 +315,10 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
false
false
)
)
)
)
itemDelegates . getValue ( viewType )
itemDelegates . getValue ( viewType )
. registerListener ( holder )
. registerListener ( holder )
if ( itemClickListener != null ) {
if ( itemClickListener != null ) {
holder . itemView . setOnClickListener {
holder . itemView . setOnClickListener {
getItem ( holder . layoutPosition ) ?. let {
getItem ( holder . layoutPosition ) ?. let {
@ -326,7 +326,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
}
}
}
}
}
}
if ( itemLongClickListener != null ) {
if ( itemLongClickListener != null ) {
holder . itemView . setOnLongClickListener {
holder . itemView . setOnLongClickListener {
getItem ( holder . layoutPosition ) ?. let {
getItem ( holder . layoutPosition ) ?. let {
@ -334,13 +334,13 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
} ?: true
} ?: true
}
}
}
}
holder
holder
}
}
}
}
final override fun onBindViewHolder ( holder : ItemViewHolder , position : Int ) { }
final override fun onBindViewHolder ( holder : ItemViewHolder , position : Int ) { }
final override fun onBindViewHolder (
final override fun onBindViewHolder (
holder : ItemViewHolder ,
holder : ItemViewHolder ,
position : Int ,
position : Int ,
@ -353,19 +353,19 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
}
}
}
}
}
}
override fun onViewAttachedToWindow ( holder : ItemViewHolder ) {
override fun onViewAttachedToWindow ( holder : ItemViewHolder ) {
super . onViewAttachedToWindow ( holder )
super . onViewAttachedToWindow ( holder )
if ( !is Header ( holder . layoutPosition ) && !is Footer ( holder . layoutPosition ) ) {
if ( !is Header ( holder . layoutPosition ) && !is Footer ( holder . layoutPosition ) ) {
addAnimation ( holder )
addAnimation ( holder )
}
}
}
}
override fun onAttachedToRecyclerView ( recyclerView : RecyclerView ) {
override fun onAttachedToRecyclerView ( recyclerView : RecyclerView ) {
super . onAttachedToRecyclerView ( recyclerView )
super . onAttachedToRecyclerView ( recyclerView )
val manager = recyclerView . layoutManager
val manager = recyclerView . layoutManager
if ( manager is GridLayoutManager ) {
if ( manager is GridLayoutManager ) {
manager . spanSizeLookup = object : GridLayoutManager . SpanSizeLookup ( ) {
manager . spanSizeLookup = object : GridLayoutManager . SpanSizeLookup ( ) {
override fun getSpanSize ( position : Int ) : Int {
override fun getSpanSize ( position : Int ) : Int {
return getItem ( position ) ?. let {
return getItem ( position ) ?. let {
if ( isHeader ( position ) || isFooter ( position ) ) manager . spanCount else getSpanSize (
if ( isHeader ( position ) || isFooter ( position ) ) manager . spanCount else getSpanSize (
@ -376,13 +376,13 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
}
}
}
}
}
}
private fun isHeader ( position : Int ) = position < getHeaderCount ( )
private fun isHeader ( position : Int ) = position < getHeaderCount ( )
private fun isFooter ( position : Int ) = position >= getActualItemCount ( ) + getHeaderCount ( )
private fun isFooter ( position : Int ) = position >= getActualItemCount ( ) + getHeaderCount ( )
private fun getActualPosition ( position : Int ) = position - getHeaderCount ( )
private fun getActualPosition ( position : Int ) = position - getHeaderCount ( )
private fun addAnimation ( holder : ItemViewHolder ) {
private fun addAnimation ( holder : ItemViewHolder ) {
itemAnimation ?. let {
itemAnimation ?. let {
if ( it . itemAnimEnabled ) {
if ( it . itemAnimEnabled ) {
@ -393,7 +393,7 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
}
}
}
}
}
}
protected open fun startAnimation ( holder : ItemViewHolder , item : ItemAnimation ) {
protected open fun startAnimation ( holder : ItemViewHolder , item : ItemAnimation ) {
item . itemAnimation ?. let {
item . itemAnimation ?. let {
for ( anim in it . getAnimators ( holder . itemView ) ) {
for ( anim in it . getAnimators ( holder . itemView ) ) {
@ -402,12 +402,12 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context):
}
}
}
}
}
}
companion object {
companion object {
private const val TYPE _HEADER _VIEW = Int . MIN _VALUE
private const val TYPE _HEADER _VIEW = Int . MIN _VALUE
private const val TYPE _FOOTER _VIEW = Int . MAX _VALUE - 999
private const val TYPE _FOOTER _VIEW = Int . MAX _VALUE - 999
}
}
}
}