Code Monkey home page Code Monkey logo

drawabletoolbox's Introduction

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.

drawabletoolbox's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

drawabletoolbox's Issues

java.lang.NullPointerException: Attempt to invoke virtual method 'android.graphics.drawable.Drawable$ConstantState android.graphics.drawable.Drawable.getConstantState()' on a null object reference

java.lang.NullPointerException: Attempt to invoke virtual method 'android.graphics.drawable.Drawable$ConstantState android.graphics.drawable.Drawable.getConstantState()' on a null object reference
        at android.graphics.drawable.RotateDrawable$RotateState.canConstantState(RotateDrawable.java:598)
        at android.graphics.drawable.RotateDrawable.getConstantState(RotateDrawable.java:398)
        at top.defaults.drawabletoolbox.CompatibleKt.setDrawable(Compatible.kt:173)
        at top.defaults.drawabletoolbox.RotateDrawableBuilder.build(RotateDrawableBuilder.kt:21)
        at top.defaults.drawabletoolbox.DrawableBuilder.wrapRotateIfNeeded(DrawableBuilder.kt:368)
        at top.defaults.drawabletoolbox.DrawableBuilder.access$wrapRotateIfNeeded(DrawableBuilder.kt:11)
        at top.defaults.drawabletoolbox.DrawableBuilder$wrap$1.invoke(DrawableBuilder.kt:329)
        at top.defaults.drawabletoolbox.DrawableBuilder$wrap$1.invoke(DrawableBuilder.kt:11)
        at top.defaults.drawabletoolbox.DrawableBuilder.wrap(DrawableBuilder.kt:336)
        at top.defaults.drawabletoolbox.DrawableBuilder.build(DrawableBuilder.kt:171)
        at top.defaults.drawabletoolboxapp.SampleCodeSnippetsKt$samples$11.build(SampleCodeSnippets.kt:183)
        at top.defaults.drawabletoolboxapp.DrawableFactory$DefaultImpls.build(DrawableFactory.kt:8)
        at top.defaults.drawabletoolboxapp.SampleCodeSnippetsKt$samples$11.build(SampleCodeSnippets.kt:173)
        at top.defaults.drawabletoolboxapp.spec.DrawableSpec.build(DrawableSpec.kt:8)
        at top.defaults.drawabletoolboxapp.spec.DrawableSpec.build$default(DrawableSpec.kt:8)
        at top.defaults.drawabletoolboxapp.DrawableSpecAdapter$ViewHolder.bind(DrawableSpecAdapter.kt:78)
        at top.defaults.drawabletoolboxapp.DrawableSpecAdapter.onBindViewHolder(DrawableSpecAdapter.kt:27)
        at top.defaults.drawabletoolboxapp.DrawableSpecAdapter.onBindViewHolder(DrawableSpecAdapter.kt:17)
        at android.support.v7.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:6781)
        at android.support.v7.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:6823)
        at android.support.v7.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:5752)
        at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6019)
        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5858)
        at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5854)
        at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2230)
        at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1557)
        at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
        at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612)
        at android.support.v7.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:3924)
        at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:3641)
        at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:4194)
        at android.view.View.layout(View.java:16009)
        at android.view.ViewGroup.layout(ViewGroup.java:5181)
        at android.support.constraint.ConstraintLayout.onLayout(ConstraintLayout.java:1858)
        at android.view.View.layout(View.java:16009)
        at android.view.ViewGroup.layout(ViewGroup.java:5181)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:639)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:574)
        at android.view.View.layout(View.java:16009)
        at android.view.ViewGroup.layout(ViewGroup.java:5181)
        at android.support.v7.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:444)
        at android.view.View.layout(View.java:16009)
        at android.view.ViewGroup.layout(ViewGroup.java:5181)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:639)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:574)
        at android.view.View.layout(View.java:16009)
        at android.view.ViewGroup.layout(ViewGroup.java:5181)

ripple issue when setting drawable

On Samsung j7 android 6.1 when changing background drawable with ripple effect, ripple plays without touching.

even setting clickable to false wont fix the problem, but fixed problem for my other devices

this.setClickable(false);
this.setBackground(offRipple);
this.setClickable(true);

hivabutton

No field mGradientRadius in class Landroid/graphics/drawable/GradientDrawable$GradientState;

W: Accessing hidden field Landroid/graphics/drawable/GradientDrawable$GradientState;->mGradientRadius:F (dark greylist, reflection)
W: java.lang.NoSuchFieldException: No field mGradientRadius in class Landroid/graphics/drawable/GradientDrawable$GradientState; (declaration of 'android.graphics.drawable.GradientDrawable$GradientState' appears in /system/framework/framework.jar)
W: at java.lang.Class.getDeclaredField(Native Method)
W: at top.defaults.drawabletoolbox.a.a(Compatible.kt:33)
W: at top.defaults.drawabletoolbox.a.a(Compatible.kt:147)
W: at top.defaults.drawabletoolbox.DrawableBuilder.a(DrawableBuilder.kt:307)
W: at top.defaults.drawabletoolbox.DrawableBuilder.a(DrawableBuilder.kt:187)
W: at b.b.a.a.b.a(DrawableUtil.kt:87)
W: at com.wwyy.wzhxl.ui.main.recommend.AdapterRecommend.a(AdapterRecommend.kt:999)
W: at com.wwyy.wzhxl.ui.main.recommend.AdapterRecommend.b(AdapterRecommend.kt:804)
W: at com.zjw.des.base.BaseAdapter.a(BaseAdapter.kt:51)
W: at com.zjw.des.base.BaseAdapter.onBindViewHolder(BaseAdapter.kt:41)
W: at com.zjw.des.base.BaseAdapter.onBindViewHolder(BaseAdapter.kt:10)
W: at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
W: at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
W: at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
W: at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
W: at androidx.recyclerview.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:288)
W: at androidx.recyclerview.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:345)
W: at androidx.recyclerview.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:361)
W: at androidx.recyclerview.widget.GapWorker.prefetch(GapWorker.java:368)
W: at androidx.recyclerview.widget.GapWorker.run(GapWorker.java:399)
W: at android.os.Handler.handleCallback(Handler.java:873)
W: at android.os.Handler.dispatchMessage(Handler.java:99)
W: at android.os.Looper.loop(Looper.java:226)
W: at android.app.ActivityThread.main(ActivityThread.java:7225)
W: at java.lang.reflect.Method.invoke(Native Method)
W: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:499)
W: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:962)

Project status

Hi,

Can we use it in production? I see some old issues and PR.

Thanks.

[FEATURE] GradientDrawable support colors

RT,
may this library support 'colors' rather than begin/center/end color?

如题,似乎可以支持设置colors 来支持更强的渐变效果,而不是限制死 begin/center/end颜色。
为什么不这么做,是有什么坑么?

请求关于示例代码中阴影效果

示例代码中,1、2、5、6点击看不到底部阴影效果,3、4、7、8、9点击却能明显看到阴影效果,还望作者请教指点一下

Strange stroke behavior

Very strange showing on Android of a stroke with corners. Take a look on top right and bottom right corners
This is code:

val bgFormInputError = DrawableBuilder()
        .cornerRadius(16)
        .solidColor(bgColor)
        .strokeColor(strokeBgColor)
        .strokeWidth(2)
        .build()

изображение

Some features not working

First of all, rotate is not working in any situation.

Secondly, baseDrawable not working as expected
Suppose there is a drawable d1. It has solid color red
And i am creating another drawable d2 based on d1. What i did is i used baseDrawable to make the d1 base of d2. I set solidColorPressed blue to d2. Now i am expecting d2 as red but blue on pressed. But it does not happens. Red in normal is working but blue in pressed not happens.

So, am i expecting wrong or what happens to baseDrawble or what is the exact behaviour of baseDrawable.

Also I tried to run your sample app but it crashed every times.
Here is the log
2021-04-25 20:15:56.368 18279-18279/top.defaults.drawabletoolboxapp A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xaef010100 in tid 18279 (wabletoolboxapp), pid 18279 (wabletoolboxapp)

Padding?

How to add padding to our drawble?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.