Skip to content

Commit

Permalink
Merge branch 'develop' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Nielssg committed Jun 12, 2021
2 parents b3b0e0b + 18b013d commit 8630db4
Show file tree
Hide file tree
Showing 6 changed files with 434 additions and 184 deletions.
70 changes: 61 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,17 @@ Different kinds of buttons, layouts and images you can create
4. [Load image](#load-image)
5. [Attributes](#attributes)
6. [Methods](#methods)
3. [Todo](#todo)
4. [Contributing](#contributing)
5. [Contributors](#contributors)
6. [Showcase](#showcase)
7. [Changelog](#changelog)
8. [Attribution](#attribution)
9. [License](#license)
3. [Android Shapes](#android-shapes)
1. [ShapeAppearance](#shapeappearance)
2. [ShapeDrawable](#shapedrawable)
3. [Methods and classes](#methods-and-classes)
4. [Todo](#todo)
5. [Contributing](#contributing)
6. [Contributors](#contributors)
7. [Showcase](#showcase)
8. [Changelog](#changelog)
9. [Attribution](#attribution)
10. [License](#license)

---

Expand All @@ -63,7 +67,7 @@ Also add the SquircleView dependency to your app build.gradle

```groovy
dependencies {
implementation "app.juky:squircleview:0.0.1"
implementation "app.juky:squircleview:0.0.2"
}
```

Expand Down Expand Up @@ -176,6 +180,49 @@ Glide.with(this).load(R.drawable.my_image)
fun setImage(drawable: Drawable?)
```

## Android Shapes

As you might have encountered before, Android does support
custom [Shapes](https://material.io/design/shape/about-shape.html#shaping-material) to be applied to buttons, images,
ConstraintLayout, etc. I've decided to create a custom view to allow some flexibility when it comes to using gradients
and other functionalities which don't work really well with shapes. If you would still like to use a ShapeDrawable /
ShapeAppearance, I've decided to add this functionality to the library. Please note that this is only supported
programmatically, not via XML.

### ShapeAppearance

```kotlin
binding.buttonWithShapeDrawable.shapeAppearanceModel = SquircleShape.getShapeAppearance().build()
```

### ShapeDrawable

```kotlin
// The background color is not preserved, so it needs to be re-applied
binding.constraintLayoutWithShapeDrawable.background =
SquircleShape.getShapeDrawable(binding.constraintLayoutWithShapeDrawable).apply {
this.paint.apply {
this.color = ContextCompat.getColor(this, R.color.my_color)
}
}
```

### Methods and classes

#### Methods

```kotlin
// Methods derived from SquircleShape
fun getSquirclePath(rect: RectF, width: Int, height: Int): ShapePath
fun getShapeAppearance(): ShapeAppearanceModel.Builder
fun getShapeDrawable(view: View): ShapeDrawable
```

#### Classes

If you would like to apply the Squircle to only a certain corner or such, you can retrieve the custom CutCornerTreatment
implementation, which is called `SquircleCornerTreatment`.

## Todo

- [ ] Inner shadow support
Expand All @@ -189,6 +236,7 @@ fun setImage(drawable: Drawable?)
- [ ] Option to determine text color by background / image
- [ ] Use precise angle of gradient instead of matching it to a segment
- [ ] Improve outer shadow boundaries
- [ ] Jetpack compose support

## Contributing

Expand Down Expand Up @@ -226,7 +274,11 @@ Check out the [CONTRIBUTING.md](CONTRIBUTING.md) file to know more

## Changelog

- V0.0.1 (10 june 2021): Initial release
- V0.0.2 (12 june 2021):
- Added support for Android shapes
- Fixed Maven using the wrong source url
- V0.0.1 (10 june 2021):
- Initial release

## Attribution

Expand Down
5 changes: 3 additions & 2 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ android {
minSdkVersion 23
targetSdkVersion 30
versionCode 1
versionName "0.0.1"
versionName "0.0.2"
project.archivesBaseName = "SquircleView"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
Expand All @@ -62,6 +62,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.core:core-ktx:1.5.0'
implementation 'com.google.android.material:material:1.3.0'

// Testing
testImplementation 'junit:junit:4.13.2'
Expand All @@ -82,4 +83,4 @@ nexusPublishing {
}
}

apply from: './publish-helper.gradle'
apply from: './publish-helper.gradle'
128 changes: 128 additions & 0 deletions library/src/main/java/app/juky/squircleview/utils/SquircleShape.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package app.juky.squircleview.utils

import android.graphics.Rect
import android.graphics.RectF
import android.graphics.drawable.ShapeDrawable
import android.graphics.drawable.shapes.PathShape
import android.view.View
import com.google.android.material.shape.CornerSize
import com.google.android.material.shape.CutCornerTreatment
import com.google.android.material.shape.ShapeAppearanceModel
import com.google.android.material.shape.ShapePath

/**
* This class provides a ShapePath, ShapeAppearance and ShapeDrawable which can be used
* instead of the custom view, allowing you to use the default shapes in Android.
*/
object SquircleShape {
fun getSquirclePath(rect: RectF, width: Int, height: Int): ShapePath {
val radius = SquirclePath.getRadiusByHeightOrWidth(height, width)

val startX = rect.left
val endX = rect.right
val startY = rect.top
val endY = rect.bottom

val path = ShapePath()

// Top left corner
path.cubicToPoint(
startX,
startY,
startX,
startY,
startX + radius,
startY
)

// Top line
path.lineTo(endX - radius, startY)

// Top right corner
path.cubicToPoint(
endX,
startY,
endX,
startY,
endX,
startY + radius,
)

// Right line
path.lineTo(endX, endY - radius)

// Bottom right corner
path.cubicToPoint(
endX,
endY,
endX,
endY,
endX - radius,
endY,
)

// Bottom line
path.lineTo(startX + radius, endY)

// Bottom left corner
path.cubicToPoint(
startX,
endY,
startX,
endY,
startX,
endY - radius,
)

return path
}

fun getShapeAppearance(): ShapeAppearanceModel.Builder =
ShapeAppearanceModel.builder().setAllCorners(SquircleCornerTreatment())

fun getShapeDrawable(view: View): ShapeDrawable {
val path = SquirclePath.getSquirclePath(
rect = RectF(0f, 0f, view.width.toFloat(), view.height.toFloat()),
width = view.width,
height = view.height
)

return object : ShapeDrawable(PathShape(path, view.width.toFloat(), view.height.toFloat())) {
override fun onBoundsChange(bounds: Rect) {
super.onBoundsChange(bounds)
shape = PathShape(
SquirclePath.getSquirclePath(
RectF(0f, 0f, bounds.width().toFloat(), bounds.height().toFloat()),
width = bounds.width(),
height = bounds.height()
),
bounds.width().toFloat(),
bounds.height().toFloat()
)
}
}
}

/**
* CornerTreatment used to apply a treatment to the corners of buttons, images, constraintlayouts, etc.
*/
class SquircleCornerTreatment : CutCornerTreatment() {
override fun getCornerPath(shapePath: ShapePath, angle: Float, interpolation: Float, bounds: RectF, size: CornerSize) {
val startX = 0f
val startY = 0f
val radius = SquirclePath.getRadiusByHeightOrWidth(bounds.height().toInt(), bounds.width().toInt())

shapePath.lineTo(startX, startY + radius)
shapePath.reset(0f, radius)

shapePath.cubicToPoint(
startX,
startY,
startX,
startY,
startX + radius,
startY
)
}
}
}
6 changes: 3 additions & 3 deletions sample/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'

// Import the library
// implementation project(':library')
implementation project(':library')

// Test the library using the Maven central / local dependency
implementation 'app.juky:squircleview:0.0.1'
//implementation 'app.juky:squircleview:0.0.2'

// Image loading
implementation 'com.github.bumptech.glide:glide:4.12.0'
Expand All @@ -64,4 +64,4 @@ dependencies {
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package app.juky.squircleview.sample

import android.graphics.Color
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import app.juky.squircleview.sample.databinding.ActivityMainBinding
import app.juky.squircleview.utils.SquircleShape
import app.juky.squircleview.views.SquircleImageView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
Expand All @@ -24,6 +27,15 @@ class MainActivity : AppCompatActivity() {
Handler(Looper.getMainLooper()).postDelayed({
loadImageWithResourceLoading()
}, 5000)

// The methods down below are native ShapeDrawable and ShapeAppearance usages
binding.buttonWithShapeDrawable.shapeAppearanceModel = SquircleShape.getShapeAppearance().build()
binding.imageWithShapeAppearance.shapeAppearanceModel = SquircleShape.getShapeAppearance().build()
binding.constraintLayoutWithShapeDrawable.background = SquircleShape.getShapeDrawable(binding.constraintLayoutWithShapeDrawable).apply {
this.paint.apply {
this.color = ContextCompat.getColor(this@MainActivity, R.color.teal_700)
}
}
}

private fun loadImageDrawable() {
Expand All @@ -33,7 +45,7 @@ class MainActivity : AppCompatActivity() {
}

private fun loadImageWithResourceLoading() {
Glide.with( applicationContext).load(R.drawable.second_image)
Glide.with(applicationContext).load(R.drawable.second_image)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(object : CustomViewTarget<SquircleImageView, Drawable>(binding.imageButton) {
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
Expand Down
Loading

0 comments on commit 8630db4

Please sign in to comment.