android-ui Java androidstudio android-library
Need help with Folivora?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.


An android library that supports set various drawables to view directly in your layout.xml

208 Stars 20 Forks Apache License 2.0 64 Commits 0 Opened issues

Services available

Need anything else?

English | 中文

Why Folivora

For most android develpers, it is usual to set

s background or
by reference a drawable, which required to define a drawable.xml under drawable folder, but some drawable files may be only referenced once, or only to used as a round corner backgrond. more and more drawables may lead to develop and maintain hardly, is there a way to create and use drawables in layout.xml? yeah, Folivora can do this work for you.

What does Folivora can do?

Folivora sets a View's background, foreground or ImageView's src in your layout.xml files, currently supported drawables are:

  • shape (GradientDrawable)
  • selector (StateListDrawable)
  • ripple (RippleDrawable)
  • layerlist (LayerListDrawable)
  • levellist (LevelListDrawable)
  • inset (InsetDrawable)
  • clip (ClipDrawable)
  • scale (ScaleDrawable)
  • animation (AnimationDrawable)
  • custom drawable (newly supported)


  • STEP1 : gradle dependency, add below in your project's build.gradle

    dependencies {
    implementation 'cn.cricin:folivora:0.1.0'
  • STEP2 : write down the attribute provided by folivora, tell folivora how to create drawable, prefix of drawables folivora builtin supported are:

    • shape -> shape
    • selectror -> selector
    • layer-list -> layer
    • level-list -> level
    • clip -> clip
    • scale -> scale
    • inset -> inset
    • ripple -> ripple
    • animation -> anim

for example, all attributes prefix of a GradientDrawable is shape, like

, IDE will gives you all available attributes after you write down
and typed the drawable prefix.


let's try to write down some code to introduce how folivora works with the first view above

here are some other supported drawable usages:




since 0.0.7,Folivora added support about complicated state selector,use

to set state flags,and use
set corresponding drawable to the states(X can be 0,1,2,3,4),now we can use the new way to describe drawable above。

Note:it is recommended to not mixed two selector definitions,just use the new way is better,which is ordered when add in selector by item index, constraint is only support 5 items for now, which is enough for usual selectors.


much cooler after used ripple drawable, but ripple effect is introduced in lollipop, if the device platform version is lower than lolipop, folivora provided a

for you, you can provide a substitude drawable if ripple is unavailable, let's try a create a
instead of
Folivora.setRippleFallback(new RippleFallback()){
  public Drawable onFallback(ColorStateList ripple, Drawable content, Drawable mask, Context ctx){
    StateListDrawable sld = new StateListDrawable();
    sld.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(ripple.getDefaultColor()));
    sld.addState(new int[0], content);
    return sld;





Note: Popular IDE's (Android Studio, IntelliJ) will likely mark this as an error despite being correct. You may want to add

to either the View itself or its parent ViewGroup to avoid this. You'll need to add the tools namespace to have access to this "ignore" attribute.
. See

  • STEP3 : enable folivora in your app, there are two ways:
public class MainActivity extends Activity {
  protected void attachBaseContext(Context newBase) {

or ```java public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Folivra.installViewFactory(this); setContentView(R.layout.yourlayoutxml_name); } }

#### Use nested shape

Folivora now support nest shape in drawable, except animation, all drawable's child drawable can use @drawable/xxx, a color, or one of shape/shape1/shape2/shape3/shape4, you can use this prefix combine with the shape attrs, let's define two round corner shape nested in selector:


effect is:

Use custom drawable

since 0.0.4,Folivora support use custom drawable, makes it easyly to use custom drawables just like custom views,for example, let's write a

which draws a paper windmill:
  1. first, write down some attrs we needed for

    , just like the way of custom view:
    Note: declare-styleable name must equals with the drawable's simple class name, so folivora will support code completion about the custom attrs.
  2. Create a

    , provide a
    public WindmillDrawable(Context ctx, AttributeSet attrs)
    constructor,you can retrieve custom attrs here, like this:
    public WindmillDrawable(Context ctx, AttributeSet attrs) {
    TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.WindmillDrawable);
    int count = a.getIndexCount();
    for (int i = 0; i < count; i++) {
    int index = a.getIndex(i);
    switch (index) {
      case R.styleable.WindmillDrawable_wdSize:
        mSize = a.getDimensionPixelSize(index, mSize);
      case R.styleable.WindmillDrawable_wdColor0:
        mColors[0] = a.getColor(index, mColors[0]);
      case R.styleable.WindmillDrawable_wdColor1:
        mColors[1] = a.getColor(index, mColors[1]);
      default://no-op unexpected attr index
    this is samilar to costom
    ,the main purpose is to add a constructor that takes a
    as parameter, other code is emitted here, for more details,click to view source code
  3. use

    in your layout files,Folivora provided a
    attr,you can declare the drawable name here:
    at runtime, the drawable is created by folivora and get worked:

you may ask, the drawable's name is to long to remember, it's difficult to write down,don't worry at it,folivora will gives the candidate of custom drawables if you typed down drawableName attr, attrs about the specific drawable is also will have code completion support.

Support of custom drawables do not have the constructor which recieves

as parameter

Folivora take concerned it, source code of some drawables is not permited to modify, so,we provided a

only have a constructor takes no parameter,but provided some methods to modify it, to support
,we can do this: ```java Folivora.addDrawableFactory(new Folivora.DrawableFactory() { @Override public Drawable newDrawable(Context context, AttributeSet attrs) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WindmillDrawable); WindmillDrawable d = new WindmillDrawable(); d.setColor0(a.getColor(R.styleable.WindmillDrawablewdColor0, Color.BLACK)); d.setRotateDegrees(a.getInt(R.styleable.WindmillDrawablewdRotateDegrees, 0)); ... a.recycle(); return d; }

@Override public Class<? extends Drawable> drawableClass() { return WindmillDrawable.class; } }); ```

If you are using custom drawable,and your drawable contains other drawables, it is recommended to use

Folivora.getDrawable(Context ctx, TypedArray a, AttributeSet attrs, int attrIndex)
to get a drawable, this method will take care about nested shape creation, also you can do not follow this tip if you do not need nested shape support。

Drawable caches

In previous releases,Folivora will create drawables according to attrs from view tag, a new instance is created for per view, which is waste resources, now Folivora supported drawable caching(LruCache,max = 128), usage is very simple,just add

attr,set a id(string type,not android's id type) to drawable is ok。Folivora will lookup cache to find a cached drawable, which means,if in a layout.xml,a drawable should be referenced multi places, define it at first occurrence, then at other place, use the same
to reference this drawable.
<textview android:layout_width="100dp" android:layout_height="40dp" android:text="shape1" android:gravity="center" android:textcolor="@android:color/white" app:drawableid="shape_rounded_6dp" app:drawabletype="shape" app:shapecornerradius="6dp" app:shapesolidcolor="@color/blue_light"></textview>

<textview android:layout_width="100dp" android:layout_height="40dp" android:text="shape2" android:gravity="center" android:textcolor="@android:color/white" app:drawableid="shape_rounded_6dp"></textview>

It is recommended to set

to drawable which is reusable or inside a frequently used layout files, which makes a better performance.

Download Sample APK

Click to download

Design time preview

preview result

after you added folivora in gradle and sync project,preview would been enabled by default, if unavailable, try to build your project.

Attrs Reference

Common Attrs


value desc
app:setAs background(default) src
app:drawableType shape layerlist
app:drawableName string fq class name of custom drawable
app:drawableId string drawable unique id for cache use

Shape Attrs


value desc
app:shapeType rectangle(default) oval
app:shapeSolidSize dimension
app:shapeSolidWidth dimension
app:shapeSolidHeight dimension
app:shapeSolidColor color
app:shapeStokeWidth dimension
app:shapeStokeDashWidth dimension
app:shapeStokeDashGap dimension
app:shapeCornerRadius dimension
app:shapeCornerRadiusTopLeft dimension
app:shapeCornerRadiusTopRight dimension
app:shapeCornerRadiusBottomLeft dimension
app:shapeCornerRadiusBottomRight dimension
app:shapeGradientType linear radial
app:shapeGradientAngle tb trbl
app:shapeGradientStartColor color
app:shapeGradientCenterColor color
app:shapeGradientEndColor color
app:shapeGradientRadius dimension
app:shapeGradientCenterX float(default 0.5)
app:shapeGradientCenterY float(default 0.5)

Selector Attrs


value desc
app:selectorStateFirst reference color
app:selectorStateMiddle reference color
app:selectorStateLast reference color
app:selectorStateActive reference color
app:selectorStateActivated reference color
app:selectorStateAccelerate reference color
app:selectorStateChecked reference color
app:selectorStateCheckable reference color
app:selectorStateEnabled reference color
app:selectorStateFocused reference color
app:selectorStatePressed reference color
app:selectorStateNormal reference color
LayerList Attrs


value desc
app:layerItem0Drawable reference color
app:layerItem0Insets dimension margin for drawable
app:layerItem0Left dimension left margin
app:layerItem0Right dimension right margin
app:layerItem0Top dimension top margin
app:layerItem0Bottom dimension bottom margin


layerlist supports at most 5 children drawables, just substitute the digit

Ripple Attrs


value desc
app:rippleColor color ripple color when touched
app:rippleMask reference color
app:rippleContent reference color
LevelList Attrs


value desc
app:levelCurrentLevel integer current level
app:levelItem0Drawable reference color
app:levelItem1MinLevel integer min level for item0
app:levelItem1MaxLevel integer max level for item0


levellist supports at most 5 children drawables, just substitute the digit

Clip Attrs


value desc
app:clipDrawable reference color
app:clipGravity same as View's layout_gravity gravity to clip
app:clipOrientation vertical horizontal
app:clipLevel integer current level(used to clip the drawable)

Scale Attrs


value desc
app:scaleDrawable reference color
app:scaleGravity same as View's layout_gravity gravity to scale
app:scaleWidth float[0,1] or -1() scale ratio for width
app:scaleHeight float[0,1] or -1() scale ratio for height
app:scaleLevel integer[0,10000] current level(used to scale the drawable)

Inset Attrs


value desc
app:insetDrawable reference color
app:insetAll dimension all inset
app:insetLeft dimension inset of left
app:insetTop dimension inset of top
app:insetRight dimension inset of right
app:insetBottom dimension inset of bottom

Animation Attrs


value desc
app:animAutoPlay boolean play animation automaticly
app:animDuration int(millisecond) displayed duration per frame
app:animOneShot boolean play just once
app:animFrame0 reference color
app:animDuration0 int(millisecond) first frame displayed duration

animation supports at most 10 frames, just substitute the digit


Copyright 2019 Cricin

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

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.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.