diff --git a/build.gradle b/build.gradle index 5392617..001b252 100644 --- a/build.gradle +++ b/build.gradle @@ -1,14 +1,13 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. - buildscript { - ext.kotlin_version = '1.5.31' + ext.kotlin_version = '1.7.10' repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.0.3' + classpath 'com.android.tools.build:gradle:7.3.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "com.vanniktech:gradle-maven-publish-plugin:0.17.0" } diff --git a/customAdapterRecycleView/build.gradle b/customAdapterRecycleView/build.gradle index cd4afa3..1423ad0 100644 --- a/customAdapterRecycleView/build.gradle +++ b/customAdapterRecycleView/build.gradle @@ -4,11 +4,11 @@ apply plugin: 'maven-publish' apply plugin: 'com.vanniktech.maven.publish' android { - compileSdkVersion 30 + compileSdkVersion 33 defaultConfig { minSdkVersion 14 - targetSdkVersion 30 + targetSdkVersion 33 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -20,6 +20,14 @@ android { } } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + buildFeatures { + viewBinding = true + } + } publishing { @@ -37,8 +45,8 @@ publishing { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') - implementation 'androidx.appcompat:appcompat:1.3.1' + implementation 'androidx.core:core-ktx:1.9.0' + implementation 'androidx.appcompat:appcompat:1.5.1' implementation 'androidx.recyclerview:recyclerview:1.2.1' - implementation "androidx.core:core-ktx:1.6.0" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" } diff --git a/customAdapterRecycleView/src/main/java/io/github/farshidroohi/AdapterRecyclerView.kt b/customAdapterRecycleView/src/main/java/io/github/farshidroohi/AdapterRecyclerView.kt index 2561d8b..db79b9f 100644 --- a/customAdapterRecycleView/src/main/java/io/github/farshidroohi/AdapterRecyclerView.kt +++ b/customAdapterRecycleView/src/main/java/io/github/farshidroohi/AdapterRecyclerView.kt @@ -1,5 +1,6 @@ package io.github.farshidroohi +import android.annotation.SuppressLint import android.content.Context import android.view.LayoutInflater import android.view.View @@ -23,10 +24,11 @@ abstract class AdapterRecyclerView( @IdRes val retryButtonId: Int ) : RecyclerView.Adapter() { + companion object { - private const val ITEM_VIEW = 0 - private const val ITEM_LOADING = 1 - private const val ITEM_FAILED = 2 + const val ITEM_VIEW = 0 + const val ITEM_LOADING = 1 + const val ITEM_FAILED = 2 } val items: MutableList = arrayListOf() @@ -39,18 +41,26 @@ abstract class AdapterRecyclerView( abstract fun onBindView( - viewHolder: ItemViewHolder, + viewHolder: RecyclerView.ViewHolder, position: Int, context: Context, element: T? ) + open fun onCreateViewHolder( + layoutInflater: LayoutInflater, + viewGroup: ViewGroup, + viewType: Int + ): RecyclerView.ViewHolder? { + return null + } override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val inflater = LayoutInflater.from(viewGroup.context) return when (viewType) { + ITEM_VIEW -> { val view = inflater.inflate(itemViewLayout, viewGroup, false) ItemViewHolder(view) @@ -65,11 +75,7 @@ abstract class AdapterRecyclerView( val view = inflater.inflate(itemFailedLayout, viewGroup, false) FailedViewHolder(view) } - - else -> { - val view = inflater.inflate(itemViewLayout, viewGroup, false) - ItemViewHolder(view) - } + else -> onCreateViewHolder(inflater, viewGroup, viewType)!! } } @@ -78,10 +84,6 @@ abstract class AdapterRecyclerView( when (viewHolder) { - is ItemViewHolder -> { - onBindView(viewHolder, position, viewHolder.itemView.context, getItem(position)) - } - is FailedViewHolder -> { handleSingleRow(viewHolder, position) @@ -90,12 +92,14 @@ abstract class AdapterRecyclerView( view?.setOnClickListener { onRetryClicked() } - } is LoadingViewHolder -> { handleSingleRow(viewHolder, position) } + else -> { + onBindView(viewHolder, position, viewHolder.itemView.context, getItem(position)) + } } @@ -125,6 +129,7 @@ abstract class AdapterRecyclerView( } + @SuppressLint("NotifyDataSetChanged") fun removeAll() { if (items.isEmpty()) { return @@ -142,11 +147,12 @@ abstract class AdapterRecyclerView( notifyItemRangeChanged(position, itemCount) } + @SuppressLint("NotifyDataSetChanged") fun remove(vararg item: T) { if (this.items.isEmpty()) { return } - this.items.removeAll(item) + this.items.removeAll(item.toSet()) notifyDataSetChanged() } @@ -155,6 +161,7 @@ abstract class AdapterRecyclerView( } + @SuppressLint("NotifyDataSetChanged") fun loadedState(newItems: List?) { if (newItems == null) { @@ -264,5 +271,4 @@ abstract class AdapterRecyclerView( class LoadingViewHolder(view: View) : RecyclerView.ViewHolder(view) class FailedViewHolder(view: View) : RecyclerView.ViewHolder(view) - } \ No newline at end of file diff --git a/customAdapterRecycleView/src/main/java/io/github/farshidroohi/DiffUtilAdapterRecyclerView.kt b/customAdapterRecycleView/src/main/java/io/github/farshidroohi/DiffUtilAdapterRecyclerView.kt new file mode 100644 index 0000000..5bd1fe9 --- /dev/null +++ b/customAdapterRecycleView/src/main/java/io/github/farshidroohi/DiffUtilAdapterRecyclerView.kt @@ -0,0 +1,54 @@ +package io.github.farshidroohi + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.viewbinding.ViewBinding +import io.github.farshidroohi.vh.BaseViewHolder + + +/** + * Created by Farshid Roohi. + * CustomAdapterRecyclerview | Copyrights 10/8/22. + */ + +abstract class DiffUtilAdapterRecyclerView( + diffCallback: DiffUtil.ItemCallback +) : ListAdapter>(diffCallback) { + + abstract fun initViewBinding(parent: ViewGroup): ViewBindingType + abstract fun bind(binding: ViewBindingType, position: Int, item: T, payloads: MutableList?) + + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int + ): BaseViewHolder { + val binding = initViewBinding(parent) + return BaseViewHolder(binding) + } + + override fun onBindViewHolder( + holder: BaseViewHolder, + position: Int, + payloads: MutableList + ) { + bind(holder.binding, position, currentList[position], payloads) + } + + override fun onBindViewHolder(holder: BaseViewHolder, position: Int) { + bind(holder.binding, position, currentList[position], null) + } + + override fun getItemCount(): Int = currentList.size + + fun changeItem(items: ArrayList, element: T, newElement: T) { + val index = items.indexOf(element) + items[index] = newElement + submitList(items.toMutableList()) + } + + fun clear() { + submitList(emptyList()) + } + +} \ No newline at end of file diff --git a/customAdapterRecycleView/src/main/java/io/github/farshidroohi/extensions/RecyclerViewExtensions.kt b/customAdapterRecycleView/src/main/java/io/github/farshidroohi/extensions/RecyclerViewExtensions.kt index b42e897..fab3986 100644 --- a/customAdapterRecycleView/src/main/java/io/github/farshidroohi/extensions/RecyclerViewExtensions.kt +++ b/customAdapterRecycleView/src/main/java/io/github/farshidroohi/extensions/RecyclerViewExtensions.kt @@ -34,10 +34,10 @@ fun RecyclerView.onLoadMoreListener(extraCount: Int = 0, onLoadMore: () -> Unit) is StaggeredGridLayoutManager -> { val staggeredGridLayoutManager = - layoutManager as StaggeredGridLayoutManager + layoutManager as StaggeredGridLayoutManager val spanCount = staggeredGridLayoutManager.spanCount val lastPositions = - staggeredGridLayoutManager.findFirstVisibleItemPositions(IntArray(spanCount)) + staggeredGridLayoutManager.findFirstVisibleItemPositions(IntArray(spanCount)) min(lastPositions[0], lastPositions[1]) } @@ -61,16 +61,29 @@ fun RecyclerView.onLoadMoreListener(extraCount: Int = 0, onLoadMore: () -> Unit) } -fun RecyclerView.onItemClickListener(onClickItem: (position: Int) -> Unit, onLongClickItem: (position: Int) -> Unit) { +fun RecyclerView.onItemClickListener( + onClickItem: (position: Int) -> Unit, + onLongClickItem: ((position: Int) -> Unit)? = null +) { + + this.addOnItemTouchListener( + RecyclerTouchListener( + context, + this, + object : OnItemListenerRecyclerViewListener { + override fun onClick(position: Int) { + if (position != (adapter?.itemCount ?: 0) - 1) { + onClickItem(position) + } + } - this.addOnItemTouchListener(RecyclerTouchListener(context, this, object : OnItemListenerRecyclerViewListener { - override fun onClick(position: Int) { - onClickItem(position) - } + override fun onLongClick(position: Int) { + if (position != (adapter?.itemCount ?: 0) - 1) { + onLongClickItem?.invoke(position) + } - override fun onLongClick(position: Int) { - onLongClickItem(position) - } - })) + } + }) + ) } \ No newline at end of file diff --git a/customAdapterRecycleView/src/main/java/io/github/farshidroohi/listener/RecyclerTouchListener.kt b/customAdapterRecycleView/src/main/java/io/github/farshidroohi/listener/RecyclerTouchListener.kt index 7091dbf..6a7c0f9 100644 --- a/customAdapterRecycleView/src/main/java/io/github/farshidroohi/listener/RecyclerTouchListener.kt +++ b/customAdapterRecycleView/src/main/java/io/github/farshidroohi/listener/RecyclerTouchListener.kt @@ -25,7 +25,7 @@ class RecyclerTouchListener(context: Context?, recyclerView: RecyclerView, priva override fun onLongPress(e: MotionEvent) { val child = recyclerView.findChildViewUnder(e.x, e.y) if (child != null && clickListener != null) { - clickListener.onLongClick(recyclerView.getChildPosition(child)) + clickListener.onLongClick(recyclerView.getChildAdapterPosition(child)) } } }) @@ -35,7 +35,7 @@ class RecyclerTouchListener(context: Context?, recyclerView: RecyclerView, priva override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean { val child = rv.findChildViewUnder(e.x, e.y) if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) { - clickListener.onClick(rv.getChildPosition(child)) + clickListener.onClick(rv.getChildAdapterPosition(child)) } return false } diff --git a/customAdapterRecycleView/src/main/java/io/github/farshidroohi/vh/BaseViewHolder.kt b/customAdapterRecycleView/src/main/java/io/github/farshidroohi/vh/BaseViewHolder.kt new file mode 100644 index 0000000..a75f946 --- /dev/null +++ b/customAdapterRecycleView/src/main/java/io/github/farshidroohi/vh/BaseViewHolder.kt @@ -0,0 +1,13 @@ +package io.github.farshidroohi.vh + +import androidx.recyclerview.widget.RecyclerView +import androidx.viewbinding.ViewBinding + +/** + * Created by Farshid Roohi. + * CustomAdapterRecyclerview | Copyrights 10/8/22. + */ + +class BaseViewHolder(val binding: ViewBindingType) : + RecyclerView.ViewHolder(binding.root) { +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 56e978b..9b6a242 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ org.gradle.jvmargs=-Xmx1536m GROUP=io.github.farshidroohi POM_ARTIFACT_ID=customAdapterRecycleView -VERSION_NAME=2.0.3 +VERSION_NAME=2.1.2 POM_NAME=CustomAdapterRecycleView POM_DESCRIPTION=Very easy endless scrolled, onClick item and simple use recyclerView adapter @@ -19,5 +19,4 @@ POM_LICENCE_URL=https://www.apache.org/licenses/LICENSE-2.0.txt POM_LICENCE_DIST=repo POM_DEVELOPER_ID=farshidroohi -POM_DEVELOPER_NAME=Farshid Roohi - +POM_DEVELOPER_NAME=Farshid Roohi \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 67d4c2e..8d2a3af 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip diff --git a/sample/build.gradle b/sample/build.gradle index ebbff72..95550b1 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -3,10 +3,10 @@ apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-android' android { - compileSdkVersion 30 + compileSdkVersion 33 defaultConfig { minSdkVersion 14 - targetSdkVersion 30 + targetSdkVersion 33 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles 'consumer-rules.pro' @@ -19,14 +19,23 @@ android { } } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + buildFeatures { + viewBinding = true + } + } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'androidx.appcompat:appcompat:1.3.1' - implementation 'androidx.constraintlayout:constraintlayout:2.1.0' + implementation 'androidx.appcompat:appcompat:1.5.1' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'androidx.recyclerview:recyclerview:1.2.1' - implementation "androidx.core:core-ktx:1.6.0" + implementation 'androidx.core:core-ktx:1.9.0' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation project(":customAdapterRecycleView") diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index 15f7d78..fa37012 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ + package="ir.farshid_roohi.customadapterrecyclerview"> - + - + - + + + + + \ No newline at end of file diff --git a/sample/src/main/java/io/github/customadapterrecyclerview/MainActivity.kt b/sample/src/main/java/io/github/customadapterrecyclerview/MainActivity.kt index 3b91f2c..ff4d6d6 100644 --- a/sample/src/main/java/io/github/customadapterrecyclerview/MainActivity.kt +++ b/sample/src/main/java/io/github/customadapterrecyclerview/MainActivity.kt @@ -1,14 +1,12 @@ package io.github.customadapterrecyclerview +import android.content.Intent import android.os.Bundle -import android.widget.Toast +import android.widget.Button import androidx.appcompat.app.AppCompatActivity -import androidx.recyclerview.widget.GridLayoutManager -import io.github.farshidroohi.extensions.onItemClickListener -import io.github.farshidroohi.extensions.onLoadMoreListener +import io.github.customadapterrecyclerview.multiViewType.MultiViewTypeActivity +import io.github.customadapterrecyclerview.singleViewType.SingleViewTypeActivity import ir.farshid_roohi.customadapterrecyclerview.R -import kotlinx.android.synthetic.main.activity_main.* -import java.util.* class MainActivity : AppCompatActivity() { @@ -16,58 +14,12 @@ class MainActivity : AppCompatActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - val myAdapter = MyAdapter() - - // onClick Error Button - myAdapter.onRetryClicked = { - myAdapter.loadingState() - // fake request or load other items... - recyclerView.postDelayed({ - myAdapter.loadedState(tempItems) - }, 2000) + findViewById