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.
Cricin

Description

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

View
s background or
ImageView
s
src
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)

Usage

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

    groovy
    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

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

shape

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:

layerlist


levellist


selector


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

app:selectorItemXStates
to set state flags,and use
app:selectorItemXDrawable
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.

ripple


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

RippleFallback
for you, you can provide a substitude drawable if ripple is unavailable, let's try a create a
selector
instead of
ripple
:
java
Folivora.setRippleFallback(new RippleFallback()){
  @Override
  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;
  }
}

clip


inset


scale


animation


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

tools:ignore="MissingPrefix"
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.
xmlns:tools="
http://schemas.android.com/tools"
. See https://code.google.com/p/android/issues/detail?id=65176.

  • STEP3 : enable folivora in your app, there are two ways:
public class MainActivity extends Activity {
  @Override
  protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(Folivora.wrap(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:

```xml

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

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

    WindmillDrawable
    , just like the way of custom view:
    xml
    
     
     
     
     
     
     
     
     
    
    
    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

    WindmillDrawable
    ,extends
    Drawable
    , provide a
    public WindmillDrawable(Context ctx, AttributeSet attrs)
    constructor,you can retrieve custom attrs here, like this:
    java
    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);
        break;
      case R.styleable.WindmillDrawable_wdColor0:
        mColors[0] = a.getColor(index, mColors[0]);
        break;
      case R.styleable.WindmillDrawable_wdColor1:
        mColors[1] = a.getColor(index, mColors[1]);
        break;
      ...
      default://no-op unexpected attr index
        break;
    }
    }
    a.recycle();
    }
    
    this is samilar to costom
    View
    ,the main purpose is to add a constructor that takes a
    Context
    and
    AttributeSet
    as parameter, other code is emitted here, for more details,click to view source code
  3. use

    WindmillDrawable
    in your layout files,Folivora provided a
    drawableName
    attr,you can declare the drawable name here:
    xml
    
    
    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

Context
and
AttributeSet
as parameter

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

DrawableFactory
interface,assume
WindmillDrawable
only have a constructor takes no parameter,but provided some methods to modify it, to support
WindmillDrawable
,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

app:drawableId
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
drawableId
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

drawableId
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

attr

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

attr

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

attr

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

attr

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

attr

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

attr

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

attr

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

attr

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

attr

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

attr

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

License

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

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.

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.