Skip to content

Commit

Permalink
Library: Supports LightSource (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
fornewid committed Sep 25, 2020
1 parent 51d88b1 commit cfe9e10
Show file tree
Hide file tree
Showing 15 changed files with 163 additions and 15 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ There is a [sample](https://github.com/fornewid/neumorphism/tree/master/sample)
app:neumorph_shadowColorLight="@color/solid_light_color"
app:neumorph_shadowColorDark="@color/solid_dark_color"

// Set light source
app:neumorph_lightSource="leftTop|leftBottom|rightTop|rightBottom"

// Set shape type and corner size
app:neumorph_shapeType="{flat|pressed|basin}"
app:neumorph_shapeAppearance="@style/CustomShapeAppearance"
Expand Down Expand Up @@ -94,6 +97,11 @@ There is a [sample](https://github.com/fornewid/neumorphism/tree/master/sample)
</style>
```

- #### LightSource
| LEFT_TOP | LEFT_BOTTOM | RIGHT_TOP | RIGHT_BOTTOM |
| :--: | :-----: | :---: | :---: |
| <img width="100" src="https://github.com/fornewid/Neumorphism/blob/master/art/lightSource_leftTop.png"/> | <img width="100" src="https://github.com/fornewid/Neumorphism/blob/master/art/lightSource_leftBottom.png"/> | <img width="100" src="https://github.com/fornewid/Neumorphism/blob/master/art/lightSource_rightTop.png"/> | <img width="100" src="https://github.com/fornewid/Neumorphism/blob/master/art/lightSource_rightBottom.png"/> |

- #### ShapeType
| FLAT | PRESSED | BASIN |
| :--: | :-----: | :---: |
Expand Down
Binary file added art/lightSource_leftBottom.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added art/lightSource_leftTop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added art/lightSource_rightBottom.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added art/lightSource_rightTop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 39 additions & 0 deletions neumorphism/src/main/java/soup/neumorphism/LightSource.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package soup.neumorphism

import androidx.annotation.IntDef
import androidx.annotation.RestrictTo

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@IntDef(
LightSource.LEFT_TOP,
LightSource.LEFT_BOTTOM,
LightSource.RIGHT_TOP,
LightSource.RIGHT_BOTTOM
)
@Retention(AnnotationRetention.SOURCE)
annotation class LightSource {
companion object {
const val LEFT_TOP = 0
const val LEFT_BOTTOM = 1
const val RIGHT_TOP = 2
const val RIGHT_BOTTOM = 3

const val DEFAULT = LEFT_TOP

fun isLeft(@LightSource lightSource: Int): Boolean {
return lightSource == LEFT_TOP || lightSource == LEFT_BOTTOM
}

fun isTop(@LightSource lightSource: Int): Boolean {
return lightSource == LEFT_TOP || lightSource == RIGHT_TOP
}

fun isRight(@LightSource lightSource: Int): Boolean {
return lightSource == RIGHT_TOP || lightSource == RIGHT_BOTTOM
}

fun isBottom(@LightSource lightSource: Int): Boolean {
return lightSource == LEFT_BOTTOM || lightSource == RIGHT_BOTTOM
}
}
}
11 changes: 11 additions & 0 deletions neumorphism/src/main/java/soup/neumorphism/NeumorphButton.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class NeumorphButton @JvmOverloads constructor(
val fillColor = a.getColorStateList(R.styleable.NeumorphButton_neumorph_backgroundColor)
val strokeColor = a.getColorStateList(R.styleable.NeumorphButton_neumorph_strokeColor)
val strokeWidth = a.getDimension(R.styleable.NeumorphButton_neumorph_strokeWidth, 0f)
val lightSource = a.getInt(R.styleable.NeumorphButton_neumorph_lightSource, LightSource.DEFAULT)
val shapeType = a.getInt(R.styleable.NeumorphButton_neumorph_shapeType, ShapeType.DEFAULT)
val inset = a.getDimensionPixelSize(
R.styleable.NeumorphButton_neumorph_inset, 0
Expand Down Expand Up @@ -64,6 +65,7 @@ class NeumorphButton @JvmOverloads constructor(

shapeDrawable = NeumorphShapeDrawable(context, attrs, defStyleAttr, defStyleRes).apply {
setInEditMode(isInEditMode)
setLightSource(lightSource)
setShapeType(shapeType)
setShadowElevation(shadowElevation)
setShadowColorLight(shadowColorLight)
Expand Down Expand Up @@ -130,6 +132,15 @@ class NeumorphButton @JvmOverloads constructor(
return shapeDrawable.getStrokeWidth()
}

fun setLightSource(@LightSource lightSource: Int) {
shapeDrawable.setLightSource(lightSource)
}

@LightSource
fun getLightSource(): Int {
return shapeDrawable.getLightSource()
}

fun setShapeType(@ShapeType shapeType: Int) {
shapeDrawable.setShapeType(shapeType)
}
Expand Down
11 changes: 11 additions & 0 deletions neumorphism/src/main/java/soup/neumorphism/NeumorphCardView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class NeumorphCardView @JvmOverloads constructor(
val fillColor = a.getColorStateList(R.styleable.NeumorphCardView_neumorph_backgroundColor)
val strokeColor = a.getColorStateList(R.styleable.NeumorphCardView_neumorph_strokeColor)
val strokeWidth = a.getDimension(R.styleable.NeumorphCardView_neumorph_strokeWidth, 0f)
val lightSource = a.getInt(R.styleable.NeumorphCardView_neumorph_lightSource, LightSource.DEFAULT)
val shapeType = a.getInt(R.styleable.NeumorphCardView_neumorph_shapeType, ShapeType.DEFAULT)
val inset = a.getDimensionPixelSize(
R.styleable.NeumorphCardView_neumorph_inset, 0
Expand Down Expand Up @@ -66,6 +67,7 @@ class NeumorphCardView @JvmOverloads constructor(

shapeDrawable = NeumorphShapeDrawable(context, attrs, defStyleAttr, defStyleRes).apply {
setInEditMode(isInEditMode)
setLightSource(lightSource)
setShapeType(shapeType)
setShadowElevation(shadowElevation)
setShadowColorLight(shadowColorLight)
Expand Down Expand Up @@ -143,6 +145,15 @@ class NeumorphCardView @JvmOverloads constructor(
return shapeDrawable.getStrokeWidth()
}

fun setLightSource(@LightSource lightSource: Int) {
shapeDrawable.setLightSource(lightSource)
}

@LightSource
fun getLightSource(): Int {
return shapeDrawable.getLightSource()
}

fun setShapeType(@ShapeType shapeType: Int) {
shapeDrawable.setShapeType(shapeType)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ class NeumorphFloatingActionButton @JvmOverloads constructor(
val fillColor = a.getColorStateList(R.styleable.NeumorphFloatingActionButton_neumorph_backgroundColor)
val strokeColor = a.getColorStateList(R.styleable.NeumorphFloatingActionButton_neumorph_strokeColor)
val strokeWidth = a.getDimension(R.styleable.NeumorphFloatingActionButton_neumorph_strokeWidth, 0f)
val shapeType =
a.getInt(R.styleable.NeumorphFloatingActionButton_neumorph_shapeType, ShapeType.DEFAULT)
val lightSource = a.getInt(R.styleable.NeumorphFloatingActionButton_neumorph_lightSource, LightSource.DEFAULT)
val shapeType = a.getInt(R.styleable.NeumorphFloatingActionButton_neumorph_shapeType, ShapeType.DEFAULT)
val inset = a.getDimensionPixelSize(
R.styleable.NeumorphFloatingActionButton_neumorph_inset, 0
)
Expand Down Expand Up @@ -65,6 +65,7 @@ class NeumorphFloatingActionButton @JvmOverloads constructor(

shapeDrawable = NeumorphShapeDrawable(context, attrs, defStyleAttr, defStyleRes).apply {
setInEditMode(isInEditMode)
setLightSource(lightSource)
setShapeType(shapeType)
setShadowElevation(shadowElevation)
setShadowColorLight(shadowColorLight)
Expand Down Expand Up @@ -131,6 +132,15 @@ class NeumorphFloatingActionButton @JvmOverloads constructor(
return shapeDrawable.getStrokeWidth()
}

fun setLightSource(@LightSource lightSource: Int) {
shapeDrawable.setLightSource(lightSource)
}

@LightSource
fun getLightSource(): Int {
return shapeDrawable.getLightSource()
}

fun setShapeType(@ShapeType shapeType: Int) {
shapeDrawable.setShapeType(shapeType)
}
Expand Down
11 changes: 11 additions & 0 deletions neumorphism/src/main/java/soup/neumorphism/NeumorphImageButton.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class NeumorphImageButton @JvmOverloads constructor(
val fillColor = a.getColorStateList(R.styleable.NeumorphImageButton_neumorph_backgroundColor)
val strokeColor = a.getColorStateList(R.styleable.NeumorphImageButton_neumorph_strokeColor)
val strokeWidth = a.getDimension(R.styleable.NeumorphImageButton_neumorph_strokeWidth, 0f)
val lightSource = a.getInt(R.styleable.NeumorphImageButton_neumorph_lightSource, LightSource.DEFAULT)
val shapeType = a.getInt(R.styleable.NeumorphImageButton_neumorph_shapeType, ShapeType.DEFAULT)
val inset = a.getDimensionPixelSize(
R.styleable.NeumorphImageButton_neumorph_inset, 0
Expand Down Expand Up @@ -64,6 +65,7 @@ class NeumorphImageButton @JvmOverloads constructor(

shapeDrawable = NeumorphShapeDrawable(context, attrs, defStyleAttr, defStyleRes).apply {
setInEditMode(isInEditMode)
setLightSource(lightSource)
setShapeType(shapeType)
setShadowElevation(shadowElevation)
setShadowColorLight(shadowColorLight)
Expand Down Expand Up @@ -130,6 +132,15 @@ class NeumorphImageButton @JvmOverloads constructor(
return shapeDrawable.getStrokeWidth()
}

fun setLightSource(@LightSource lightSource: Int) {
shapeDrawable.setLightSource(lightSource)
}

@LightSource
fun getLightSource(): Int {
return shapeDrawable.getLightSource()
}

fun setShapeType(@ShapeType shapeType: Int) {
shapeDrawable.setShapeType(shapeType)
}
Expand Down
11 changes: 11 additions & 0 deletions neumorphism/src/main/java/soup/neumorphism/NeumorphImageView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class NeumorphImageView @JvmOverloads constructor(
val fillColor = a.getColorStateList(R.styleable.NeumorphImageView_neumorph_backgroundColor)
val strokeColor = a.getColorStateList(R.styleable.NeumorphImageView_neumorph_strokeColor)
val strokeWidth = a.getDimension(R.styleable.NeumorphImageView_neumorph_strokeWidth, 0f)
val lightSource = a.getInt(R.styleable.NeumorphImageView_neumorph_lightSource, LightSource.DEFAULT)
val shapeType = a.getInt(R.styleable.NeumorphImageView_neumorph_shapeType, ShapeType.DEFAULT)
val inset = a.getDimensionPixelSize(
R.styleable.NeumorphImageView_neumorph_inset, 0
Expand Down Expand Up @@ -64,6 +65,7 @@ class NeumorphImageView @JvmOverloads constructor(

shapeDrawable = NeumorphShapeDrawable(context, attrs, defStyleAttr, defStyleRes).apply {
setInEditMode(isInEditMode)
setLightSource(lightSource)
setShapeType(shapeType)
setShadowElevation(shadowElevation)
setShadowColorLight(shadowColorLight)
Expand Down Expand Up @@ -130,6 +132,15 @@ class NeumorphImageView @JvmOverloads constructor(
return shapeDrawable.getStrokeWidth()
}

fun setLightSource(@LightSource lightSource: Int) {
shapeDrawable.setLightSource(lightSource)
}

@LightSource
fun getLightSource(): Int {
return shapeDrawable.getLightSource()
}

fun setShapeType(@ShapeType shapeType: Int) {
shapeDrawable.setShapeType(shapeType)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,18 @@ class NeumorphShapeDrawable : Drawable {
invalidateSelf()
}

fun setLightSource(@LightSource lightSource: Int) {
if (drawableState.lightSource != lightSource) {
drawableState.lightSource = lightSource
invalidateSelf()
}
}

@LightSource
fun getLightSource(): Int {
return drawableState.lightSource
}

fun setShapeType(@ShapeType shapeType: Int) {
if (drawableState.shapeType != shapeType) {
drawableState.shapeType = shapeType
Expand Down Expand Up @@ -382,6 +394,8 @@ class NeumorphShapeDrawable : Drawable {

var alpha = 255

@LightSource
var lightSource: Int = LightSource.DEFAULT
@ShapeType
var shapeType: Int = ShapeType.DEFAULT
var shadowElevation: Float = 0f
Expand All @@ -408,6 +422,7 @@ class NeumorphShapeDrawable : Drawable {
strokeColor = orig.strokeColor
strokeWidth = orig.strokeWidth
alpha = orig.alpha
lightSource = orig.lightSource
shapeType = orig.shapeType
shadowElevation = orig.shadowElevation
shadowColorLight = orig.shadowColorLight
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import soup.neumorphism.CornerFamily
import soup.neumorphism.LightSource
import soup.neumorphism.NeumorphShapeAppearanceModel
import soup.neumorphism.NeumorphShapeDrawable.NeumorphShapeDrawableState
import soup.neumorphism.internal.util.onCanvas
Expand All @@ -29,20 +30,23 @@ internal class FlatShape(

override fun draw(canvas: Canvas, outlinePath: Path) {
canvas.withClipOut(outlinePath) {
val lightSource = drawableState.lightSource
val elevation = drawableState.shadowElevation
val z = drawableState.shadowElevation + drawableState.translationZ
val left: Float
val top: Float
val inset = drawableState.inset
left = inset.left.toFloat()
top = inset.top.toFloat()
val left = inset.left.toFloat()
val top = inset.top.toFloat()
lightShadowBitmap?.let {
val offsetX = if (LightSource.isLeft(lightSource)) -elevation - z else -elevation + z
val offsetY = if (LightSource.isTop(lightSource)) -elevation - z else -elevation + z
val offset = -elevation - z
drawBitmap(it, offset + left, offset + top, null)
drawBitmap(it, offsetX + left, offsetY + top, null)
}
darkShadowBitmap?.let {
val offsetX = if (LightSource.isLeft(lightSource)) -elevation + z else -elevation - z
val offsetY = if (LightSource.isTop(lightSource)) -elevation + z else -elevation - z
val offset = -elevation + z
drawBitmap(it, offset + left, offset + top, null)
drawBitmap(it, offsetX + left, offsetY + top, null)
}
}
}
Expand Down Expand Up @@ -94,7 +98,10 @@ internal class FlatShape(
val height = (h + shadowElevation * 2).roundToInt()
return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
.onCanvas {
withTranslation(shadowElevation, shadowElevation) {
withTranslation(
x = shadowElevation,
y = shadowElevation
) {
draw(this)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.graphics.Path
import android.graphics.Rect
import android.graphics.drawable.GradientDrawable
import soup.neumorphism.CornerFamily
import soup.neumorphism.LightSource
import soup.neumorphism.NeumorphShapeDrawable.NeumorphShapeDrawableState
import soup.neumorphism.internal.util.onCanvas
import soup.neumorphism.internal.util.withClip
Expand Down Expand Up @@ -58,7 +59,9 @@ internal class PressedShape(
drawableState.shapeAppearanceModel.getCornerSize()
)
shape = GradientDrawable.RECTANGLE
cornerRadii = floatArrayOf(0f, 0f, 0f, 0f, cornerSize, cornerSize, 0f, 0f)
cornerRadii = cornerSize.let {
floatArrayOf(it, it, it, it, it, it, it, it)
}
}
}
}
Expand All @@ -76,7 +79,9 @@ internal class PressedShape(
drawableState.shapeAppearanceModel.getCornerSize()
)
shape = GradientDrawable.RECTANGLE
cornerRadii = floatArrayOf(cornerSize, cornerSize, 0f, 0f, 0f, 0f, 0f, 0f)
cornerRadii = cornerSize.let {
floatArrayOf(it, it, it, it, it, it, it, it)
}
}
}
}
Expand All @@ -97,12 +102,21 @@ internal class PressedShape(
}

val shadowElevation = drawableState.shadowElevation
val lightSource = drawableState.lightSource
return Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
.onCanvas {
withTranslation(-shadowElevation, -shadowElevation) {
withTranslation(
x = if (LightSource.isLeft(lightSource)) -shadowElevation else 0f,
y = if (LightSource.isTop(lightSource)) -shadowElevation else 0f
) {
lightShadowDrawable.draw(this)
}
darkShadowDrawable.draw(this)
withTranslation(
x = if (LightSource.isRight(lightSource)) -shadowElevation else 0f,
y = if (LightSource.isBottom(lightSource)) -shadowElevation else 0f
) {
darkShadowDrawable.draw(this)
}
}
.blurred()
}
Expand Down
Loading

0 comments on commit cfe9e10

Please sign in to comment.