🛠️ The missing drawable toolbox for Android. Create drawables programmatically and get rid of the boring and always repeated drawable.xml files.
Switch branches/tags
Clone or download
Latest commit 43e1c6e Sep 11, 2018
Permalink
Failed to load latest commit information.
.idea Release 1.0.1 Aug 1, 2018
app Release 1.0.7 Sep 11, 2018
art Update README Aug 13, 2018
drawabletoolbox Release 1.0.7 Sep 11, 2018
gradle/wrapper Initial commit Jul 31, 2018
.gitignore Initial commit Jul 31, 2018
LICENSE Fix LICENSE Aug 9, 2018
README.md Update README Aug 17, 2018
README_cn.md 😎 Become awesome Aug 14, 2018
build.gradle Upgrade the build tools and kotlin version Aug 9, 2018
gradle.properties Initial commit Jul 31, 2018
gradlew Initial commit Jul 31, 2018
gradlew.bat Initial commit Jul 31, 2018
settings.gradle Initial commit Jul 31, 2018

README.md

DrawableToolbox

gitHub release platform license Awesome Kotlin Badge

English | 中文

The missing DrawableToolbox for Android. Create drawables programmatically and get rid of the boring and always repeated drawable.xml files.


Features

  • Create drawables programmatically
  • Support <shape>, <rotate>, <scale>, <ripple>, <layer-list> drawables
  • Support 'flip' (vertical or horizontal)

Contribute

Gradle

dependencies {
    implementation 'com.github.duanhong169:drawabletoolbox:${latestVersion}'
    ...
}

Replace ${latestVersion} with the latest version code. See releases.

Usage

Use the DrawableBuilder to setup the Drawable and call build() to create it.

Please check all the supported APIs in DrawableBuilder.kt.

Here are some examples:

Code:

DrawableBuilder()
        .rectangle()
        .hairlineBordered()
        .strokeColor(COLOR_DEFAULT)
        .strokeColorPressed(COLOR_PRESSED)
        .ripple()
        .build()

Result:

Bordered with Ripple

Code:

DrawableBuilder()
        .rectangle()
        .hairlineBordered()
        .mediumDashed()
        .strokeColor(COLOR_DEFAULT)
        .strokeColorPressed(COLOR_PRESSED)
        .ripple()
        .build()

Result:

Medium-dashed, Bordered with Ripple

Code:

DrawableBuilder()
        .rectangle()
        .rounded()
        .solidColor(COLOR_DEFAULT)
        .solidColorPressed(COLOR_PRESSED)
        .build()

Result:

Rounded, Filled with States

Code:

DrawableBuilder()
        .rectangle()
        .hairlineBordered()
        .longDashed()
        .rounded()
        .strokeColor(COLOR_DEFAULT)
        .strokeColorPressed(COLOR_PRESSED)
        .ripple()
        .build()

Result:

Rounded, Long-dashed, Bordered with Ripple

Code:

DrawableBuilder()
        .rectangle()
        .rounded()
        .gradient()
        .linearGradient()
        .angle(90)
        .startColor(COLOR_DEFAULT)
        .endColor(ContextCompat.getColor(context, R.color.colorPrimaryDark))
        .ripple()
        .rippleColor(COLOR_PRESSED)
        .build()

Result:

Rounded, Gradient with Ripple

Code:

val baseBuilder = DrawableBuilder()
        .rectangle()
        .rounded()
        .gradient()
        .gradientType(GradientDrawable.LINEAR_GRADIENT)
        .angle(90)
val normalState = baseBuilder
        .startColor(COLOR_DEFAULT)
        .endColor(ContextCompat.getColor(context, R.color.colorPrimaryDark))
        .build()
val pressedState = baseBuilder
        .startColor(COLOR_PRESSED)
        .endColor(ContextCompat.getColor(context, R.color.colorAccentDark))
        .build()

StateListDrawableBuilder()
        .normal(normalState)
        .pressed(pressedState)
        .build()

Result:

Rounded, Gradient with States

Code:

val baseBuilder = DrawableBuilder()
        .rectangle()
        .rounded()
        .hairlineBordered()
        .strokeColor(COLOR_DEFAULT)
        .solidColorSelected(COLOR_DEFAULT)
        .ripple()

return when(type) {
    SegmentedControlDrawableSpec.TYPE_LEFT_MOST -> {
        baseBuilder.topRightRadius(0)
                .bottomRightRadius(0)
                .build()
    }
    SegmentedControlDrawableSpec.TYPE_RIGHT_MOST -> {
        baseBuilder.topLeftRadius(0)
                .bottomLeftRadius(0)
                .build()
    }
    else -> {
        baseBuilder.cornerRadius(0).build()
    }
}

Result:

Segmented Control

Code:

val layer1 = DrawableBuilder()
        .size(200)
        .rectangle()
        .rounded()
        .hairlineBordered()
        .strokeColor(COLOR_DEFAULT)
        .strokeColorPressed(COLOR_PRESSED)
        .build()
val layer2 = DrawableBuilder()
        .rectangle()
        .rounded()
        .solidColor(COLOR_DEFAULT)
        .build()
val layer3 = DrawableBuilder()
        .rectangle()
        .rounded()
        .solidColor(Color.WHITE)
        .ripple()
        .rippleColor(COLOR_DEFAULT)
        .build()
LayerDrawableBuilder()
        .add(layer1)
        .add(layer2)
        .inset(10)
        .add(layer3)
        .inset(20)
        .build()

Result:

Layer List: Several Borders

Code:

val layer1 = DrawableBuilder()
        .size(180)
        .rectangle()
        .build()
val layer2 = DrawableBuilder()
        .oval()
        .solidColor(COLOR_DEFAULT)
        .build()
val layer3 = DrawableBuilder()
        .rectangle()
        .solidColor(COLOR_DEFAULT_DARK)
        .rotate(45f)
        .build()
val layer4 = DrawableBuilder()
        .rectangle()
        .bottomLeftRadius(100)
        .solidColor(COLOR_DEFAULT_DARK)
        .build()
val layer5 = DrawableBuilder()
        .oval()
        .solidColor(COLOR_DEFAULT)
        .build()
val layerDrawable = LayerDrawableBuilder()
        .add(layer1)
        .add(layer2)
        .inset(20, 20, 100, 100)
        .add(layer3)
        .inset(100, 20, 20, 100)
        .add(layer4)
        .inset(20, 100, 100, 20)
        .add(layer5)
        .inset(100, 100, 20, 20)
        .build()
DrawableBuilder()
        .baseDrawable(layerDrawable)
        .rotate(0f, 360f)
        .build()

Result:

Showcase: Layer List 1

Code:

// Rotate & Leveled the Ring
DrawableBuilder()
        .size(200)
        .ring()
        .useLevelForRing()
        .solidColor(COLOR_DEFAULT)
        .innerRadiusRatio(3f)
        .thicknessRatio(10f)
        .rotate(0f, 720f)
        .build()

Result:

Rotate & Leveled the Ring

Code:

// Rotate, Sweep & Flip the Ring
DrawableBuilder()
        .size(200)
        .ring()
        .innerRadiusRatio(3f)
        .thicknessRatio(10f)
        .gradient()
        .sweepGradient()
        .rotate(0f, 360f)
        .flip()
        .build()

Result:

Rotate, Sweep & Flip the Ring

Code:

// Rotate, Sweep & Scale the Oval with States
val baseBuilder = DrawableBuilder()
        .size(400)
        .oval()
        .gradient()
        .sweepGradient()
        .rotate(0f, 360f)
        .scale(0.5f)
        .scaleGravity(Gravity.START or Gravity.TOP)
val normalState = baseBuilder.build()
val pressedState = baseBuilder
        .startColor(COLOR_PRESSED)
        .endColor(0x7FFFFFFF)
        .build()
StateListDrawableBuilder()
        .normal(normalState)
        .pressed(pressedState)
        .build()

Result:

Rotate, Sweep & Scale the Oval with States

Please check out the app sample code SampleCodeSnippets.kt for more details.

License

Copyright 2018 Hong Duan

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.