diff --git a/build.gradle b/build.gradle index e6b5d46..d47006e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,11 +1,10 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.4.32' + ext.kotlin_version = '1.5.0' repositories { google() - jcenter() - + mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:4.2.0' @@ -18,8 +17,7 @@ buildscript { allprojects { repositories { google() - jcenter() - + mavenCentral() } } diff --git a/sample/build.gradle b/sample/build.gradle index cd54e56..9006a26 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -45,7 +45,7 @@ dependencies { androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.constraintlayout:constraintlayout:2.0.4' @@ -66,5 +66,5 @@ dependencies { kapt 'com.github.bumptech.glide:compiler:4.12.0' // debugImplementation because LeakCanary should only run in debug builds. - debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4' + debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7' } diff --git a/sample/src/main/java/org/imaginativeworld/whynotimagecarousel/sample/JavaActivity.java b/sample/src/main/java/org/imaginativeworld/whynotimagecarousel/sample/JavaActivity.java index 1da9e72..2cd2969 100644 --- a/sample/src/main/java/org/imaginativeworld/whynotimagecarousel/sample/JavaActivity.java +++ b/sample/src/main/java/org/imaginativeworld/whynotimagecarousel/sample/JavaActivity.java @@ -26,7 +26,9 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import me.relex.circleindicator.CircleIndicator2; @@ -120,6 +122,16 @@ public ViewBinding onCreateViewHolder(@NotNull LayoutInflater layoutInflater, @N // ... return null; } + + @Override + public void onLongClick(int position, @NotNull CarouselItem dataObject) { + // ... + } + + @Override + public void onClick(int position, @NotNull CarouselItem carouselItem) { + // ... + } }); CircleIndicator2 indicator = findViewById(R.id.custom_indicator); @@ -133,12 +145,17 @@ public ViewBinding onCreateViewHolder(@NotNull LayoutInflater layoutInflater, @N List list = new ArrayList<>(); + // Dummy header + Map headers = new HashMap<>(); + headers.put("header_key", "header_value"); + int index = 1; for (String item : DataSet.INSTANCE.getOne()) { list.add( new CarouselItem( item, - "Image " + index++ + " of " + DataSet.INSTANCE.getOne().size() + "Image " + index++ + " of " + DataSet.INSTANCE.getOne().size(), + headers ) ); } diff --git a/sample/src/main/java/org/imaginativeworld/whynotimagecarousel/sample/KotlinActivity.kt b/sample/src/main/java/org/imaginativeworld/whynotimagecarousel/sample/KotlinActivity.kt index f0f7750..39a6538 100644 --- a/sample/src/main/java/org/imaginativeworld/whynotimagecarousel/sample/KotlinActivity.kt +++ b/sample/src/main/java/org/imaginativeworld/whynotimagecarousel/sample/KotlinActivity.kt @@ -8,6 +8,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.ViewGroup import android.widget.ImageView +import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.core.content.res.ResourcesCompat @@ -99,34 +100,34 @@ class KotlinActivity : AppCompatActivity() { infiniteCarousel = true touchToPause = true - onScrollListener = object : CarouselOnScrollListener { - override fun onScrollStateChanged( - recyclerView: RecyclerView, - newState: Int, - position: Int, - carouselItem: CarouselItem? - ) { - // ... + carouselListener = object : CarouselListener { + override fun onClick(position: Int, carouselItem: CarouselItem) { + Toast.makeText(this@KotlinActivity, "You clicked it.", Toast.LENGTH_SHORT) + .show() } - override fun onScrolled( - recyclerView: RecyclerView, - dx: Int, - dy: Int, - position: Int, - carouselItem: CarouselItem? - ) { - // ... + override fun onLongClick(position: Int, dataObject: CarouselItem) { + Toast.makeText( + this@KotlinActivity, + "You long clicked it.", + Toast.LENGTH_SHORT + ) + .show() } } + // Dummy header + val headers = mutableMapOf() + headers["header_key"] = "header_value" + val listOne = mutableListOf() for ((index, item) in DataSet.one.withIndex()) { listOne.add( CarouselItem( imageUrl = item, - caption = "Image ${index + 1} of ${DataSet.one.size}" + caption = "Image ${index + 1} of ${DataSet.one.size}", + headers = headers ) ) } diff --git a/whynotimagecarousel/build.gradle b/whynotimagecarousel/build.gradle index 46b95cc..97cd581 100644 --- a/whynotimagecarousel/build.gradle +++ b/whynotimagecarousel/build.gradle @@ -1,6 +1,5 @@ buildscript { repositories { - jcenter() mavenCentral() } dependencies { diff --git a/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/ImageCarousel.kt b/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/ImageCarousel.kt index d4e8cad..e5389cb 100644 --- a/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/ImageCarousel.kt +++ b/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/ImageCarousel.kt @@ -1,6 +1,5 @@ package org.imaginativeworld.whynotimagecarousel -import android.annotation.SuppressLint import android.content.Context import android.graphics.Color import android.graphics.drawable.ColorDrawable @@ -478,25 +477,21 @@ class ImageCarousel( initAdapter() initListeners() initAutoPlay() - initTouchListener() } - @SuppressLint("ClickableViewAccessibility") - private fun initTouchListener() { - recyclerView.setOnTouchListener { _, event -> - if (touchToPause) { - when (event?.action) { - MotionEvent.ACTION_UP -> { - resumeAutoPlay() - } - MotionEvent.ACTION_DOWN -> { - pauseAutoPlay() - } + override fun onInterceptTouchEvent(event: MotionEvent?): Boolean { + if (touchToPause) { + when (event?.action) { + MotionEvent.ACTION_UP -> { + resumeAutoPlay() + } + MotionEvent.ACTION_DOWN -> { + pauseAutoPlay() } } - - false } + + return super.onInterceptTouchEvent(event) } @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) diff --git a/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/adapter/FiniteCarouselAdapter.kt b/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/adapter/FiniteCarouselAdapter.kt index 37da3fe..95e07b1 100644 --- a/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/adapter/FiniteCarouselAdapter.kt +++ b/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/adapter/FiniteCarouselAdapter.kt @@ -51,14 +51,13 @@ open class FiniteCarouselAdapter( } override fun onBindViewHolder(holder: MyViewHolder, position: Int) { - val item = getItem(position) ?: return - - /** - * If the sum of consecutive two items of a [RecyclerView] is not greater than - * the [ImageCarousel] view width, then the [scrollToPosition] method will not work - * as expected. So we will check the width of the element and increase the minimum width - * for fixing the problem if [autoWidthFixing] is true. - */ + val realItemPosition = getRealDataPosition(position) + val item = getItem(realItemPosition) ?: return + + // If the sum of consecutive two items of a RecyclerView is not greater than + // the ImageCarousel view width, then the scrollToPosition() method will not work + // as expected. So we will check the width of the element and increase the minimum width + // for fixing the problem if autoWidthFixing is true. if (autoWidthFixing && carouselType == CarouselType.SHOWCASE) { val containerWidth = recyclerView.width if (holder.itemView.layoutParams.width >= 0 && @@ -73,6 +72,18 @@ open class FiniteCarouselAdapter( holder.binding.img.scaleType = imageScaleType holder.binding.img.setImage(item, imagePlaceholder) + + listener?.apply { + holder.itemView.setOnClickListener { + this.onClick(realItemPosition, item) + } + + holder.itemView.setOnLongClickListener { + this.onLongClick(realItemPosition, item) + + true + } + } } // Init listeners @@ -80,7 +91,7 @@ open class FiniteCarouselAdapter( holder.binding, imageScaleType, item, - getRealDataPosition(position) + realItemPosition ) // Init start and end offsets diff --git a/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/indicator/BaseCircleIndicator.kt b/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/indicator/BaseCircleIndicator.kt deleted file mode 100644 index 6dac4aa..0000000 --- a/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/indicator/BaseCircleIndicator.kt +++ /dev/null @@ -1,3 +0,0 @@ -package org.imaginativeworld.whynotimagecarousel.indicator - -class BaseCircleIndicator diff --git a/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/indicator/CarouselIndicator.kt b/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/indicator/CarouselIndicator.kt deleted file mode 100644 index 7236798..0000000 --- a/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/indicator/CarouselIndicator.kt +++ /dev/null @@ -1,3 +0,0 @@ -package org.imaginativeworld.whynotimagecarousel.indicator - -class CarouselIndicator diff --git a/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/listener/CarouselListener.kt b/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/listener/CarouselListener.kt index ea7789f..d8d822f 100644 --- a/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/listener/CarouselListener.kt +++ b/whynotimagecarousel/src/main/java/org/imaginativeworld/whynotimagecarousel/listener/CarouselListener.kt @@ -7,12 +7,50 @@ import androidx.viewbinding.ViewBinding import org.imaginativeworld.whynotimagecarousel.model.CarouselItem interface CarouselListener { - fun onCreateViewHolder(layoutInflater: LayoutInflater, parent: ViewGroup): ViewBinding? + /** + * Inflate custom view here using view binding. + * It's mapped with RecyclerView.Adapter#onCreateViewHolder. + * + * @param layoutInflater for inflating layout. + * @param parent the parent of the generated hierarchy. + * @return ViewBinding of the custom view. + */ + fun onCreateViewHolder(layoutInflater: LayoutInflater, parent: ViewGroup): ViewBinding? = null + /** + * Bind view with data. + * It's mapped with RecyclerView.Adapter#onBindViewHolder. + * + * @param binding The ViewBinding returned in onCreateViewHolder. + * @param imageScaleType selected ImageView.ScaleType provided in imageScaleType attribute. + * @param item current CarouselItem item for bind. + * @param position current data position. + */ fun onBindViewHolder( binding: ViewBinding, imageScaleType: ImageView.ScaleType, item: CarouselItem, position: Int - ) + ) { + } + + /** + * When an item view is clicked it will be invoked. + * + * Note: It will not work for the custom layout. + * + * @param position Data item position. + * @param carouselItem Data item of the clicked view. + */ + fun onClick(position: Int, carouselItem: CarouselItem) {} + + /** + * When an item view is long clicked it will be invoked. + * + * Note: It will not work for the custom layout. + * + * @param position Data item position. + * @param carouselItem Data item of the long clicked view. + */ + fun onLongClick(position: Int, dataObject: CarouselItem) {} }