diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 84861e7..69403ed 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -46,5 +46,4 @@ dependencies { // Extra dependencies for the library implementation(libs.picasso) implementation(libs.androidx.multidex) - implementation(libs.carousels.kotlin) } \ No newline at end of file diff --git a/carousel/.gitignore b/carousel/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/carousel/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/carousel/build.gradle.kts b/carousel/build.gradle.kts new file mode 100644 index 0000000..d78c70d --- /dev/null +++ b/carousel/build.gradle.kts @@ -0,0 +1,51 @@ +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) +} + +android { + namespace = "com.example.carousel" + compileSdk = 35 + + defaultConfig { + applicationId = "com.example.carousel" + minSdk = 22 + targetSdk = 34 + versionCode = 1 + versionName = "1.0" + + multiDexEnabled = true + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = "11" + } +} + +dependencies { + + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.appcompat) + implementation(libs.material) + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) +// Dependencies for the library + api(libs.picasso) + implementation(libs.glide) + implementation(libs.androidx.multidex) +} \ No newline at end of file diff --git a/carousel/proguard-rules.pro b/carousel/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/carousel/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/carousel/src/androidTest/java/com/example/carousel/ExampleInstrumentedTest.kt b/carousel/src/androidTest/java/com/example/carousel/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..5dc5c4d --- /dev/null +++ b/carousel/src/androidTest/java/com/example/carousel/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.example.carousel + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.example.carousel", appContext.packageName) + } +} \ No newline at end of file diff --git a/carousel/src/main/AndroidManifest.xml b/carousel/src/main/AndroidManifest.xml new file mode 100644 index 0000000..9558c49 --- /dev/null +++ b/carousel/src/main/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/carousel/src/main/java/com/example/carousel/ImageSlider.kt b/carousel/src/main/java/com/example/carousel/ImageSlider.kt new file mode 100644 index 0000000..bc1dd9e --- /dev/null +++ b/carousel/src/main/java/com/example/carousel/ImageSlider.kt @@ -0,0 +1,148 @@ +package com.example.carousel + +import android.content.Context +import android.os.Handler +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.RelativeLayout +import androidx.core.content.ContextCompat +import androidx.viewpager.widget.ViewPager +import com.example.carousel.adapters.ViewPagerAdapter +import com.example.carousel.interfaces.ItemClickListener +import com.example.carousel.models.SlideModel +import java.util.* + +class ImageSlider @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : + RelativeLayout(context, attrs, defStyleAttr) { + + private var viewPager: ViewPager? = null + private var pagerDots: LinearLayout? = null + private var viewPagerAdapter: ViewPagerAdapter? = null + + private var dots: Array? = null + + private var currentPage = 0 + private var imageCount = 0 + + private var cornerRadius: Int = 0 + private var period: Long = 0 + private var delay: Long = 0 + private var autoCycle = false + + private var selectedDot = 0 + private var unselectedDot = 0 + private var errorImage = 0 + private var placeholder = 0 + private var swipeTimer = Timer() + + init { + LayoutInflater.from(getContext()).inflate(R.layout.image_slider, this, true) + viewPager = findViewById(R.id.view_pager) + pagerDots = findViewById(R.id.pager_dots) + + val typedArray = context.theme.obtainStyledAttributes( + attrs, + R.styleable.ImageSlider, + defStyleAttr, + defStyleAttr + ) + + cornerRadius = typedArray.getInt(R.styleable.ImageSlider_corner_radius, 0) + period = typedArray.getInt(R.styleable.ImageSlider_period, 1000).toLong() + delay = typedArray.getInt(R.styleable.ImageSlider_delay, 1000).toLong() + autoCycle = typedArray.getBoolean(R.styleable.ImageSlider_auto_cycle, false) + placeholder = + typedArray.getResourceId(R.styleable.ImageSlider_placeholder, R.drawable.placeholder) + errorImage = typedArray.getResourceId(R.styleable.ImageSlider_error_image, R.drawable.error) + selectedDot = typedArray.getResourceId( + R.styleable.ImageSlider_selected_dot, + R.drawable.default_selected_dot + ) + unselectedDot = typedArray.getResourceId( + R.styleable.ImageSlider_unselected_dot, + R.drawable.default_unselected_dot + ) + + } + + fun setImageList(imageList: List, centerCrop: Boolean = false) { + viewPagerAdapter = + ViewPagerAdapter(context, imageList, cornerRadius, errorImage, placeholder, centerCrop) + viewPager!!.adapter = viewPagerAdapter + imageCount = imageList.size + if (imageList.size > 1) { + setupDots(imageList.size) + if (autoCycle) { + startSliding() + } + } + } + + private fun setupDots(size: Int) { + pagerDots!!.removeAllViews() + dots = arrayOfNulls(size) + + for (i in 0 until size) { + dots!![i] = ImageView(context) + dots!![i]!!.setImageDrawable(ContextCompat.getDrawable(context, unselectedDot)) + val params = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ) + params.setMargins(8, 0, 8, 0) + pagerDots!!.addView(dots!![i], params) + } + dots!![0]!!.setImageDrawable(ContextCompat.getDrawable(context, selectedDot)) + + viewPager!!.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { + override fun onPageScrolled( + position: Int, + positionOffset: Float, + positionOffsetPixels: Int + ) { + } + + override fun onPageSelected(position: Int) { + currentPage = position + for (dot in dots!!) { + dot!!.setImageDrawable(ContextCompat.getDrawable(context, unselectedDot)) + } + dots!![position]!!.setImageDrawable(ContextCompat.getDrawable(context, selectedDot)) + } + + override fun onPageScrollStateChanged(state: Int) {} + }) + } + + fun startSliding(changeablePeriod: Long = period) { + scheduleTimer(changeablePeriod) + } + + fun stopSliding() { + swipeTimer.cancel() + swipeTimer.purge() + } + + private fun scheduleTimer(period: Long) { + val handler = Handler() + val update = Runnable { + if (currentPage == imageCount) { + currentPage = 0 + } + viewPager!!.setCurrentItem(currentPage++, true) + } + swipeTimer = Timer() + swipeTimer.schedule(object : TimerTask() { + override fun run() { + handler.post(update) + } + }, delay, period) + } + + fun setItemClickListener(itemClickListener: ItemClickListener) { + viewPagerAdapter?.setItemClickListener(itemClickListener) + } +} + diff --git a/carousel/src/main/java/com/example/carousel/adapters/ViewPagerAdapter.kt b/carousel/src/main/java/com/example/carousel/adapters/ViewPagerAdapter.kt new file mode 100644 index 0000000..92aaef9 --- /dev/null +++ b/carousel/src/main/java/com/example/carousel/adapters/ViewPagerAdapter.kt @@ -0,0 +1,102 @@ +package com.example.carousel.adapters + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.RelativeLayout +import android.widget.TextView +import androidx.viewpager.widget.PagerAdapter +import com.example.carousel.R +import com.example.carousel.interfaces.ItemClickListener +import com.example.carousel.models.SlideModel +import com.example.carousel.transformation.RoundedTransformation +import com.squareup.picasso.Picasso + +class ViewPagerAdapter(context: Context?, imageList: List, private var radius: Int, private var errorImage: Int, private var placeholder: Int, private var centerCrop: Boolean?) : PagerAdapter() { + + private var imageList: List? = imageList + private var layoutInflater: LayoutInflater? = context!!.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater? + + private var itemClickListener: ItemClickListener? = null + + override fun isViewFromObject(view: View, obj: Any): Boolean { + return view == obj + } + + override fun getCount(): Int { + return imageList!!.size + } + + override fun instantiateItem(container: ViewGroup, position: Int): View { + + val itemView = layoutInflater!!.inflate(R.layout.pager_row, container, false) + + val imageView = itemView.findViewById(R.id.image_view) + val linearLayout = itemView.findViewById(R.id.linear_layout) + val textView = itemView.findViewById(R.id.text_view) + + if (imageList!![position].title != null){ + textView.text = imageList!![position].title + }else{ + linearLayout.visibility = View.INVISIBLE + } + + if(imageList!![position].imageUrl == null){ + if(centerCrop!! || imageList!![position].centerCrop){ + Picasso.get() + .load(imageList!![position].imagePath!!) // Int + .fit() + .centerCrop() + .transform(RoundedTransformation(radius,0)) + .placeholder(placeholder) + .error(errorImage) + .into(imageView) + }else { + Picasso.get() + .load(imageList!![position].imagePath!!) // Int + .fit() + .transform(RoundedTransformation(radius, 0)) + .placeholder(placeholder) + .error(errorImage) + .into(imageView) + } + }else{ + if(centerCrop!! || imageList!![position].centerCrop) { + Picasso.get() + .load(imageList!![position].imageUrl!!) // String + .fit() + .centerCrop() + .transform(RoundedTransformation(radius, 0)) + .placeholder(placeholder) + .error(errorImage) + .into(imageView) + }else { + Picasso.get() + .load(imageList!![position].imageUrl!!) // String + .fit() + .transform(RoundedTransformation(radius, 0)) + .placeholder(placeholder) + .error(errorImage) + .into(imageView) + } + } + + container.addView(itemView) + + imageView.setOnClickListener{itemClickListener?.onItemSelected(position)} + + return itemView + } + + fun setItemClickListener(itemClickListener: ItemClickListener) { + this.itemClickListener = itemClickListener + } + + override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { + container.removeView(`object` as RelativeLayout) + } + +} \ No newline at end of file diff --git a/carousel/src/main/java/com/example/carousel/interfaces/ItemClickListener.kt b/carousel/src/main/java/com/example/carousel/interfaces/ItemClickListener.kt new file mode 100644 index 0000000..bb31dbd --- /dev/null +++ b/carousel/src/main/java/com/example/carousel/interfaces/ItemClickListener.kt @@ -0,0 +1,5 @@ +package com.example.carousel.interfaces + +interface ItemClickListener { + fun onItemSelected(position: Int) +} \ No newline at end of file diff --git a/carousel/src/main/java/com/example/carousel/models/SlideModel.kt b/carousel/src/main/java/com/example/carousel/models/SlideModel.kt new file mode 100644 index 0000000..d85012c --- /dev/null +++ b/carousel/src/main/java/com/example/carousel/models/SlideModel.kt @@ -0,0 +1,49 @@ +package com.example.carousel.models + +class SlideModel { + + var imageUrl: String? = null + var imagePath: Int? = 0 + var title: String? = null + var centerCrop = false + + constructor (imageUrl: String) { + this.imageUrl = imageUrl + } + + constructor (imagePath: Int) { + this.imagePath = imagePath + } + + constructor (imageUrl: String, title: String?) { + this.imageUrl = imageUrl + this.title = title + } + + constructor (imagePath: Int, title: String?) { + this.imagePath = imagePath + this.title = title + } + + constructor (imageUrl: String, centerCrop: Boolean) { + this.imageUrl = imageUrl + this.centerCrop = centerCrop + } + + constructor (imagePath: Int, centerCrop: Boolean) { + this.imagePath = imagePath + this.centerCrop = centerCrop + } + + constructor (imagePath: Int, title: String?, centerCrop: Boolean) { + this.imagePath = imagePath + this.title = title + this.centerCrop = centerCrop + } + + constructor (imageUrl: String, title: String?, centerCrop: Boolean) { + this.imageUrl = imageUrl + this.title = title + this.centerCrop = centerCrop + } +} \ No newline at end of file diff --git a/carousel/src/main/java/com/example/carousel/transformation/RoundedTransformation.kt b/carousel/src/main/java/com/example/carousel/transformation/RoundedTransformation.kt new file mode 100644 index 0000000..2fd1046 --- /dev/null +++ b/carousel/src/main/java/com/example/carousel/transformation/RoundedTransformation.kt @@ -0,0 +1,175 @@ +package com.example.carousel.transformation + +import android.graphics.* +import com.squareup.picasso.Transformation + +class RoundedTransformation @JvmOverloads constructor(radius:Int, margin:Int, cornerType: CornerType = CornerType.ALL): + Transformation { + private var mRadius:Float = 0f + private var mDiameter:Float = 0f + private var mMargin:Float = 0f + private var mCornerType: CornerType + enum class CornerType { + ALL, + TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, + TOP, BOTTOM, LEFT, RIGHT, + OTHER_TOP_LEFT, OTHER_TOP_RIGHT, OTHER_BOTTOM_LEFT, OTHER_BOTTOM_RIGHT, + DIAGONAL_FROM_TOP_LEFT, DIAGONAL_FROM_TOP_RIGHT + } + init{ + mRadius = radius.toFloat() + mDiameter = (radius * 2).toFloat() + mMargin = margin.toFloat() + mCornerType = cornerType + } + + override fun transform(source: Bitmap): Bitmap { + val width = source.getWidth() + val height = source.getHeight() + val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) + val canvas = Canvas(bitmap) + val paint = Paint() + paint.setAntiAlias(true) + paint.setShader(BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)) + drawRoundRect(canvas, paint, width.toFloat(), height.toFloat()) + source.recycle() + return bitmap + } + private fun drawRoundRect(canvas: Canvas, paint: Paint, width:Float, height:Float) { + val right = width - mMargin + val bottom = height - mMargin + when (mCornerType) { + CornerType.ALL -> canvas.drawRoundRect(RectF(mMargin, mMargin, right, bottom), mRadius, mRadius, paint) + CornerType.TOP_LEFT -> drawTopLeftRoundRect(canvas, paint, right, bottom) + CornerType.TOP_RIGHT -> drawTopRightRoundRect(canvas, paint, right, bottom) + CornerType.BOTTOM_LEFT -> drawBottomLeftRoundRect(canvas, paint, right, bottom) + CornerType.BOTTOM_RIGHT -> drawBottomRightRoundRect(canvas, paint, right, bottom) + CornerType.TOP -> drawTopRoundRect(canvas, paint, right, bottom) + CornerType.BOTTOM -> drawBottomRoundRect(canvas, paint, right, bottom) + CornerType.LEFT -> drawLeftRoundRect(canvas, paint, right, bottom) + CornerType.RIGHT -> drawRightRoundRect(canvas, paint, right, bottom) + CornerType.OTHER_TOP_LEFT -> drawOtherTopLeftRoundRect(canvas, paint, right, bottom) + CornerType.OTHER_TOP_RIGHT -> drawOtherTopRightRoundRect(canvas, paint, right, bottom) + CornerType.OTHER_BOTTOM_LEFT -> drawOtherBottomLeftRoundRect(canvas, paint, right, bottom) + CornerType.OTHER_BOTTOM_RIGHT -> drawOtherBottomRightRoundRect(canvas, paint, right, bottom) + CornerType.DIAGONAL_FROM_TOP_LEFT -> drawDiagonalFromTopLeftRoundRect(canvas, paint, right, bottom) + CornerType.DIAGONAL_FROM_TOP_RIGHT -> drawDiagonalFromTopRightRoundRect(canvas, paint, right, bottom) + //else -> canvas.drawRoundRect(RectF(mMargin, mMargin, right, bottom), mRadius, mRadius, paint) + } + } + private fun drawTopLeftRoundRect(canvas: Canvas, paint: Paint, right:Float, bottom:Float) { + canvas.drawRoundRect( + RectF(mMargin, mMargin, mMargin + mDiameter, mMargin + mDiameter), + mRadius, mRadius, paint) + canvas.drawRect(RectF(mMargin, mMargin + mRadius, mMargin + mRadius, bottom), paint) + canvas.drawRect(RectF(mMargin + mRadius, mMargin, right, bottom), paint) + } + private fun drawTopRightRoundRect(canvas: Canvas, paint: Paint, right:Float, bottom:Float) { + canvas.drawRoundRect( + RectF(right - mDiameter, mMargin, right, mMargin + mDiameter), mRadius, + mRadius, paint) + canvas.drawRect(RectF(mMargin, mMargin, right - mRadius, bottom), paint) + canvas.drawRect(RectF(right - mRadius, mMargin + mRadius, right, bottom), paint) + } + private fun drawBottomLeftRoundRect(canvas: Canvas, paint: Paint, right:Float, bottom:Float) { + canvas.drawRoundRect( + RectF(mMargin, bottom - mDiameter, mMargin + mDiameter, bottom), + mRadius, mRadius, paint) + canvas.drawRect(RectF(mMargin, mMargin, mMargin + mDiameter, bottom - mRadius), paint) + canvas.drawRect(RectF(mMargin + mRadius, mMargin, right, bottom), paint) + } + private fun drawBottomRightRoundRect(canvas: Canvas, paint: Paint, right:Float, bottom:Float) { + canvas.drawRoundRect( + RectF(right - mDiameter, bottom - mDiameter, right, bottom), mRadius, + mRadius, paint) + canvas.drawRect(RectF(mMargin, mMargin, right - mRadius, bottom), paint) + canvas.drawRect(RectF(right - mRadius, mMargin, right, bottom - mRadius), paint) + } + private fun drawTopRoundRect(canvas: Canvas, paint: Paint, right:Float, bottom:Float) { + canvas.drawRoundRect( + RectF(mMargin, mMargin, right, mMargin + mDiameter), mRadius, mRadius, + paint) + canvas.drawRect(RectF(mMargin, mMargin + mRadius, right, bottom), paint) + } + private fun drawBottomRoundRect(canvas: Canvas, paint: Paint, right:Float, bottom:Float) { + canvas.drawRoundRect( + RectF(mMargin, bottom - mDiameter, right, bottom), mRadius, mRadius, + paint) + canvas.drawRect(RectF(mMargin, mMargin, right, bottom - mRadius), paint) + } + private fun drawLeftRoundRect(canvas: Canvas, paint: Paint, right:Float, bottom:Float) { + canvas.drawRoundRect( + RectF(mMargin, mMargin, mMargin + mDiameter, bottom), mRadius, mRadius, + paint) + canvas.drawRect(RectF(mMargin + mRadius, mMargin, right, bottom), paint) + } + private fun drawRightRoundRect(canvas: Canvas, paint: Paint, right:Float, bottom:Float) { + canvas.drawRoundRect( + RectF(right - mDiameter, mMargin, right, bottom), mRadius, mRadius, + paint) + canvas.drawRect(RectF(mMargin, mMargin, right - mRadius, bottom), paint) + } + private fun drawOtherTopLeftRoundRect(canvas: Canvas, paint: Paint, right:Float, bottom:Float) { + canvas.drawRoundRect( + RectF(mMargin, bottom - mDiameter, right, bottom), mRadius, mRadius, + paint) + canvas.drawRoundRect( + RectF(right - mDiameter, mMargin, right, bottom), mRadius, mRadius, + paint) + canvas.drawRect(RectF(mMargin, mMargin, right - mRadius, bottom - mRadius), paint) + } + private fun drawOtherTopRightRoundRect(canvas: Canvas, paint: Paint, right:Float, bottom:Float) { + canvas.drawRoundRect( + RectF(mMargin, mMargin, mMargin + mDiameter, bottom), mRadius, mRadius, + paint) + canvas.drawRoundRect( + RectF(mMargin, bottom - mDiameter, right, bottom), mRadius, mRadius, + paint) + canvas.drawRect(RectF(mMargin + mRadius, mMargin, right, bottom - mRadius), paint) + } + private fun drawOtherBottomLeftRoundRect(canvas: Canvas, paint: Paint, right:Float, bottom:Float) { + canvas.drawRoundRect( + RectF(mMargin, mMargin, right, mMargin + mDiameter), mRadius, mRadius, + paint) + canvas.drawRoundRect( + RectF(right - mDiameter, mMargin, right, bottom), mRadius, mRadius, + paint) + canvas.drawRect(RectF(mMargin, mMargin + mRadius, right - mRadius, bottom), paint) + } + private fun drawOtherBottomRightRoundRect(canvas: Canvas, paint: Paint, right:Float, + bottom:Float) { + canvas.drawRoundRect( + RectF(mMargin, mMargin, right, mMargin + mDiameter), mRadius, mRadius, + paint) + canvas.drawRoundRect( + RectF(mMargin, mMargin, mMargin + mDiameter, bottom), mRadius, mRadius, + paint) + canvas.drawRect(RectF(mMargin + mRadius, mMargin + mRadius, right, bottom), paint) + } + private fun drawDiagonalFromTopLeftRoundRect(canvas: Canvas, paint: Paint, right:Float, + bottom:Float) { + canvas.drawRoundRect( + RectF(mMargin, mMargin, mMargin + mDiameter, mMargin + mDiameter), + mRadius, mRadius, paint) + canvas.drawRoundRect( + RectF(right - mDiameter, bottom - mDiameter, right, bottom), mRadius, + mRadius, paint) + canvas.drawRect(RectF(mMargin, mMargin + mRadius, right - mDiameter, bottom), paint) + canvas.drawRect(RectF(mMargin + mDiameter, mMargin, right, bottom - mRadius), paint) + } + private fun drawDiagonalFromTopRightRoundRect(canvas: Canvas, paint: Paint, right:Float, + bottom:Float) { + canvas.drawRoundRect( + RectF(right - mDiameter, mMargin, right, mMargin + mDiameter), mRadius, + mRadius, paint) + canvas.drawRoundRect( + RectF(mMargin, bottom - mDiameter, mMargin + mDiameter, bottom), + mRadius, mRadius, paint) + canvas.drawRect(RectF(mMargin, mMargin, right - mRadius, bottom - mRadius), paint) + canvas.drawRect(RectF(mMargin + mRadius, mMargin + mRadius, right, bottom), paint) + } + override fun key():String { + return ("RoundedTransformation(radius=" + mRadius + ", margin=" + mMargin + ", diameter=" + + mDiameter + ", cornerType=" + mCornerType.name + ")") + } +} \ No newline at end of file diff --git a/carousel/src/main/res/drawable-v24/ic_launcher_foreground.xml b/carousel/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/carousel/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/carousel/src/main/res/drawable/default_selected_dot.xml b/carousel/src/main/res/drawable/default_selected_dot.xml new file mode 100644 index 0000000..6ac42ce --- /dev/null +++ b/carousel/src/main/res/drawable/default_selected_dot.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/carousel/src/main/res/drawable/default_unselected_dot.xml b/carousel/src/main/res/drawable/default_unselected_dot.xml new file mode 100644 index 0000000..ec78956 --- /dev/null +++ b/carousel/src/main/res/drawable/default_unselected_dot.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/carousel/src/main/res/drawable/error.png b/carousel/src/main/res/drawable/error.png new file mode 100644 index 0000000..4cd813c Binary files /dev/null and b/carousel/src/main/res/drawable/error.png differ diff --git a/carousel/src/main/res/drawable/gradient.xml b/carousel/src/main/res/drawable/gradient.xml new file mode 100644 index 0000000..c2bc013 --- /dev/null +++ b/carousel/src/main/res/drawable/gradient.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/carousel/src/main/res/drawable/ic_launcher_background.xml b/carousel/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/carousel/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/carousel/src/main/res/drawable/placeholder.png b/carousel/src/main/res/drawable/placeholder.png new file mode 100644 index 0000000..963c65f Binary files /dev/null and b/carousel/src/main/res/drawable/placeholder.png differ diff --git a/carousel/src/main/res/layout/image_slider.xml b/carousel/src/main/res/layout/image_slider.xml new file mode 100644 index 0000000..0581de6 --- /dev/null +++ b/carousel/src/main/res/layout/image_slider.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/carousel/src/main/res/layout/pager_row.xml b/carousel/src/main/res/layout/pager_row.xml new file mode 100644 index 0000000..a2708d1 --- /dev/null +++ b/carousel/src/main/res/layout/pager_row.xml @@ -0,0 +1,31 @@ + + + + + + + + \ No newline at end of file diff --git a/carousel/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/carousel/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/carousel/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/carousel/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/carousel/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..6f3b755 --- /dev/null +++ b/carousel/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/carousel/src/main/res/mipmap-hdpi/ic_launcher.webp b/carousel/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000..c209e78 Binary files /dev/null and b/carousel/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/carousel/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/carousel/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000..b2dfe3d Binary files /dev/null and b/carousel/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/carousel/src/main/res/mipmap-mdpi/ic_launcher.webp b/carousel/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000..4f0f1d6 Binary files /dev/null and b/carousel/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/carousel/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/carousel/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000..62b611d Binary files /dev/null and b/carousel/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/carousel/src/main/res/mipmap-xhdpi/ic_launcher.webp b/carousel/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000..948a307 Binary files /dev/null and b/carousel/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/carousel/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/carousel/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..1b9a695 Binary files /dev/null and b/carousel/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/carousel/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/carousel/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/carousel/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/carousel/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/carousel/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/carousel/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/carousel/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/carousel/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000..aa7d642 Binary files /dev/null and b/carousel/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/carousel/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/carousel/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000..9126ae3 Binary files /dev/null and b/carousel/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/carousel/src/main/res/values-night/themes.xml b/carousel/src/main/res/values-night/themes.xml new file mode 100644 index 0000000..beff2b4 --- /dev/null +++ b/carousel/src/main/res/values-night/themes.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/carousel/src/main/res/values/attrs.xml b/carousel/src/main/res/values/attrs.xml new file mode 100644 index 0000000..fbc77c1 --- /dev/null +++ b/carousel/src/main/res/values/attrs.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/carousel/src/main/res/values/colors.xml b/carousel/src/main/res/values/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/carousel/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/carousel/src/main/res/values/strings.xml b/carousel/src/main/res/values/strings.xml new file mode 100644 index 0000000..711b210 --- /dev/null +++ b/carousel/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + carousel + \ No newline at end of file diff --git a/carousel/src/main/res/values/themes.xml b/carousel/src/main/res/values/themes.xml new file mode 100644 index 0000000..886a466 --- /dev/null +++ b/carousel/src/main/res/values/themes.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/carousel/src/test/java/com/example/carousel/ExampleUnitTest.kt b/carousel/src/test/java/com/example/carousel/ExampleUnitTest.kt new file mode 100644 index 0000000..8f6b192 --- /dev/null +++ b/carousel/src/test/java/com/example/carousel/ExampleUnitTest.kt @@ -0,0 +1,17 @@ +package com.example.carousel + +import org.junit.Test + +import org.junit.Assert.* + +/** + * Example local unit test, which will execute on the development machine (host). + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +class ExampleUnitTest { + @Test + fun addition_isCorrect() { + assertEquals(4, 2 + 2) + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 20e2a01..316a8ed 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,4 +20,5 @@ kotlin.code.style=official # Enables namespacing of each library's R class so that its R class includes only the # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library -android.nonTransitiveRClass=true \ No newline at end of file +android.nonTransitiveRClass=true +org.gradle.configuration-cache=true \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4f118a6..2349fe4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] agp = "8.7.3" androidMavenGradlePlugin = "1.4.1" -carouselsKotlin = "0.0.2" +glide = "4.10.0" gradle = "3.5.4" kotlin = "1.9.24" coreKtx = "1.15.0" @@ -18,7 +18,7 @@ picasso = "2.71828" android-maven-gradle-plugin = { module = "com.github.dcendents:android-maven-gradle-plugin", version.ref = "androidMavenGradlePlugin" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-multidex = { module = "androidx.multidex:multidex", version.ref = "multidex" } -carousels-kotlin = { module = "com.github.UmarAuna:Carousels-Kotlin", version.ref = "carouselsKotlin" } +glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" } gradle = { module = "com.android.tools.build:gradle", version.ref = "gradle" } junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 20ec24a..56b46ad 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,4 +21,5 @@ dependencyResolutionManagement { } rootProject.name = "Image Carousel Library" -include(":app") \ No newline at end of file +include(":app") +include(":carousel")