Skip to content

Commit

Permalink
Add colorRes and drawableRes API (#98)
Browse files Browse the repository at this point in the history
* Add API to set the color using its resource

* Add API to set the drawable using its resource

* Add test

* Fix test
  • Loading branch information
fondesa committed May 18, 2020
1 parent 260be49 commit 4544283
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.util.TypedValue
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.annotation.Px
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
Expand Down Expand Up @@ -112,6 +115,14 @@ class DividerBuilder internal constructor(private val context: Context) {
*/
fun asSpace(): DividerBuilder = apply { asSpace = true }

/**
* Sets the divider's drawable as a solid color.
*
* @param colorRes the resource of the color used for each divider.
* @return this [DividerBuilder] instance.
*/
fun colorRes(@ColorRes colorRes: Int): DividerBuilder = color(ContextCompat.getColor(context, colorRes))

/**
* Sets the divider's drawable as a solid color.
*
Expand All @@ -120,6 +131,14 @@ class DividerBuilder internal constructor(private val context: Context) {
*/
fun color(@ColorInt color: Int): DividerBuilder = drawable(drawable = ColorDrawable(color))

/**
* Sets the divider's drawable.
*
* @param drawableRes the resource of the [Drawable] used for each divider.
* @return this [DividerBuilder] instance.
*/
fun drawableRes(@DrawableRes drawableRes: Int): DividerBuilder = drawable(context.getDrawableCompat(drawableRes))

/**
* Sets the divider's drawable.
*
Expand Down Expand Up @@ -293,4 +312,7 @@ class DividerBuilder internal constructor(private val context: Context) {
}
return transparentDrawable()
}

private fun Context.getDrawableCompat(@DrawableRes drawableRes: Int): Drawable = ContextCompat.getDrawable(this, drawableRes)
?: throw NullPointerException("The drawable with resource id $drawableRes can't be loaded. Use the method .drawable() instead.")
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.util.TypedValue
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.annotation.Px
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.fondesa.recyclerviewdivider.drawable.getThemeDrawable
Expand Down Expand Up @@ -82,6 +84,15 @@ class StaggeredDividerBuilder(private val context: Context) {
*/
fun asSpace(): StaggeredDividerBuilder = apply { asSpace = true }

/**
* Sets the divider's color.
* If the color of this divider is not completely opaque (contains some transparency), this builder can't ensure a correct rendering.
*
* @param colorRes the resource of the color used for each divider.
* @return this [StaggeredDividerBuilder] instance.
*/
fun colorRes(@ColorRes colorRes: Int): StaggeredDividerBuilder = color(ContextCompat.getColor(context, colorRes))

/**
* Sets the divider's color.
* If the color of this divider is not completely opaque (contains some transparency), this builder can't ensure a correct rendering.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@

package com.fondesa.recyclerviewdivider

import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.os.Build
import android.util.TypedValue
import androidx.annotation.ColorInt
import androidx.annotation.Px
Expand All @@ -41,7 +48,11 @@ import com.fondesa.recyclerviewdivider.tint.TintProvider
import com.fondesa.recyclerviewdivider.tint.TintProviderImpl
import com.fondesa.recyclerviewdivider.visibility.VisibilityProvider
import com.fondesa.recyclerviewdivider.visibility.VisibilityProviderImpl
import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.anyOrNull
import com.nhaarman.mockitokotlin2.doReturn
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.spy
import com.nhaarman.mockitokotlin2.verify
import com.nhaarman.mockitokotlin2.verifyZeroInteractions
import org.junit.After
Expand Down Expand Up @@ -108,6 +119,22 @@ class DividerBuilderTest {
verifyZeroInteractions(logger)
}

@Test
fun `build - colorRes invoked - returns decoration with color`() {
scenario = launchThemeActivity(R.style.TestTheme_All)

val decoration = dividerBuilder()
.colorRes(R.color.test_recyclerViewDividerDrawable)
.build()

val provider = (decoration as DividerItemDecoration).drawableProvider
assertTrue(provider is DrawableProviderImpl)
val providerDrawable = (provider as DrawableProviderImpl).drawable
assertTrue(providerDrawable is ColorDrawable)
assertEquals(ContextCompat.getColor(context, R.color.test_recyclerViewDividerDrawable), (providerDrawable as ColorDrawable).color)
verifyZeroInteractions(logger)
}

@Test
fun `build - color invoked - returns decoration with color`() {
scenario = launchThemeActivity(R.style.TestTheme_All)
Expand All @@ -124,6 +151,38 @@ class DividerBuilderTest {
verifyZeroInteractions(logger)
}

@Test
fun `build - drawableRes invoked - returns decoration with drawable`() {
scenario = launchThemeActivity(R.style.TestTheme_All)
val expectedDrawable = requireNotNull(ContextCompat.getDrawable(context, R.drawable.test_recycler_view_drawable_not_solid))

val decoration = dividerBuilder()
.drawableRes(R.drawable.test_recycler_view_drawable_not_solid)
.build()

val provider = (decoration as DividerItemDecoration).drawableProvider
assertTrue(provider is DrawableProviderImpl)
val providerDrawable = (provider as DrawableProviderImpl).drawable
assertTrue(providerDrawable is GradientDrawable)
assertTrue(expectedDrawable.getBitmap().sameAs(providerDrawable.getBitmap()))
verifyZeroInteractions(logger)
}

@Test(expected = NullPointerException::class)
fun `build - drawableRes invoked with invalid Drawable - throws NullPointerException`() {
val resources = mock<Resources> {
@Suppress("DEPRECATION")
on(it.getDrawable(any())) doReturn null
if (Build.VERSION.SDK_INT >= 21) {
on(it.getDrawable(any(), anyOrNull())) doReturn null
}
}
val context = spy(context) {
on(it.resources) doReturn resources
}
DividerBuilder(context).drawableRes(R.drawable.test_recycler_view_drawable_not_solid)
}

@Test
fun `build - drawable invoked - returns decoration with drawable`() {
scenario = launchThemeActivity(R.style.TestTheme_All)
Expand Down Expand Up @@ -651,4 +710,16 @@ class DividerBuilderTest {
} else {
DividerBuilder(context)
}

private fun Drawable.getBitmap(): Bitmap = if (this is BitmapDrawable) {
bitmap
} else {
val width = intrinsicWidth.takeIf { it >= 0 } ?: 1
val height = intrinsicHeight.takeIf { it >= 0 } ?: 1
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
setBounds(0, 0, canvas.width, canvas.height)
draw(canvas)
bitmap
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,20 @@ class StaggeredDividerBuilderTest {
verifyZeroInteractions(logger)
}

@Test
fun `build - colorRes invoked - returns decoration with color`() {
scenario = launchThemeActivity(R.style.TestTheme_All)

val decoration = staggeredDividerBuilder()
.colorRes(R.color.test_recyclerViewDividerDrawable)
.build()

val drawable = (decoration as StaggeredDividerItemDecoration).drawable
assertTrue(drawable is ColorDrawable)
assertEquals(ContextCompat.getColor(context, R.color.test_recyclerViewDividerDrawable), (drawable as ColorDrawable).color)
verifyZeroInteractions(logger)
}

@Test
fun `build - color invoked - returns decoration with color`() {
scenario = launchThemeActivity(R.style.TestTheme_All)
Expand Down

0 comments on commit 4544283

Please sign in to comment.