Litho provides extensive support for stylized borders on component layouts. All of the available options are specified through a Border object via a builder pattern.

Border Widths

Litho supports setting a border width for all edges, or a different width per edge. Specifying a width for a certain edge is done via the various width builder methods.

For example, let’s say you wanted to specify a 10 dip border width for all edges:

Red Border

1
2
3
4
5
6
7
8
9
10
11
Row.create(c)
  .child(
    Text.create(c)
      .text("Hello Litho")
      .textSizeSp(16))
  .border(
    Border.create(c)
      .widthDip(YogaEdge.ALL, 5)
      .color(YogaEdge.ALL, 0xfff36b7f)
      .build())
  .build()

Or that you’d like to specify specific widths for a specific edge:

Red Left Border

1
2
3
4
5
6
7
8
9
10
11
Row.create(c)
  .child(
    Text.create(c)
      .text("Hello Litho")
      .textSizeSp(16))
  .border(
    Border.create(c)
      .widthDip(YogaEdge.LEFT, 5)
      .color(YogaEdge.LEFT, 0xfff36b7f)
      .build())
  .build()

Maybe you just want something different per edge:

Varying Border Width

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Row.create(c)
  .child(
    Text.create(c)
      .text("Hello Litho")
      .textSizeSp(16))
  .border(
    Border.create(c)
      .widthDip(YogaEdge.START, 5)
      .widthDip(YogaEdge.TOP, 10)
      .widthDip(YogaEdge.RIGHT, 15)
      .widthDip(YogaEdge.BOTTOM, 20)
      .color(YogaEdge.ALL, 0xfff36b7f)
      .build())
  .build()

Border Colors

Setting a color for a certain border edge is set via the various color builder methods.

You can set each border edge to any color you’d like:

Varying Border Color

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Row.create(c)
  .child(
    Text.create(c)
      .text("Hello Litho")
      .textSizeSp(16))
  .border(
    Border.create(c)
      .widthDip(YogaEdge.ALL, 5)
      .color(YogaEdge.START, 0xfff36b7f)
      .color(YogaEdge.TOP, 0xff7ff36b)
      .color(YogaEdge.END, 0xff6b7ff3)
      .color(YogaEdge.BOTTOM, 0xfff39b6b)
      .build())
  .build();

It still works for varying widths:

Varying Border Color with Varying Width

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Row.create(c)
  .child(
    Text.create(c)
      .text("Hello Litho")
      .textSizeSp(16))
  .border(
    Border.create(c)
      .widthDip(YogaEdge.START, 5)
      .widthDip(YogaEdge.TOP, 10)
      .widthDip(YogaEdge.RIGHT, 15)
      .widthDip(YogaEdge.BOTTOM, 20)
      .color(YogaEdge.START, 0xfff36b7f)
      .color(YogaEdge.TOP, 0xff7ff36b)
      .color(YogaEdge.END, 0xff6b7ff3)
      .color(YogaEdge.BOTTOM, 0xfff39b6b)
      .build())
  .build();

Border Effects

Border effects are powerful tools to help you stylize your borders even further. The following effects are currently available:

Under the hood, each effect utilizes a standard PathEffect supplied by the Android Framework. You may use up to two effects at the same time. If you use two effects, they will both be composed with each other in the order given.

Border effects are specified via the various *Effect methods on the Border.Builder object.

IMPORTANT: Currently Litho does not support varying border widths with effects. Each border width must be the same.

Dash

The dash effect applies a sequence of “on” and “off” sections of the border color. This effect utilizes DashPathEffect internally.

Dash Effect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Row.create(c)
  .child(
    Text.create(c)
      .text("Hello Litho")
      .textSizeSp(16))
  .border(
    Border.create(c)
      .widthDip(YogaEdge.ALL, 5)
      .color(YogaEdge.ALL, 0xfff36b7f)
      // We want "on" segments of length 10, "off" of length 5
      // We also specify 0 for the phase as we do not want to offset the start
      .dashEffect(new float[] {10f, 5f}, 0f)
      .build())
  .build();

Corner

A corner effect will round any sharp angles in your border. This typically means it will produce rounded corners for your border. This effect utilizes CornerPathEffect internally.

Corner Effect

1
2
3
4
5
6
7
8
9
10
11
12
13
Row.create(c)
  .child(
    Text.create(c)
      .text("Hello Litho")
      .textSizeSp(16))
  .border(
    Border.create(c)
      .widthDip(YogaEdge.ALL, 5)
      .color(YogaEdge.ALL, 0xfff36b7f)
      // We set a corner radius of 10 here
      .cornerEffect(10f)
      .build())
  .build();

Discrete

The discrete effect will divide your border into segments whereby each segment will randomly deviate in the cross axis. This effect utilizes DiscretePathEffect internally.

Discrete Effect

1
2
3
4
5
6
7
8
9
10
11
12
13
Row.create(c)
  .child(
    Text.create(c)
      .text("Hello Litho")
      .textSizeSp(16))
  .border(
    Border.create(c)
      .widthDip(YogaEdge.ALL, 5)
      .color(YogaEdge.ALL, 0xfff36b7f)
      // We set a segment length of 10 with a maximum deviation of 5
      .discreteEffect(10f, 5f)
      .build())
  .build();

Path Dash

Path dash will take in a custom Android path object and continually stamp the path along the border. This effect utilizes PathDashPathEffect internally.

Path Effect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Our stamp shape will be a simple circle
Path dot = new Path();
dot.addCircle(0f, 0f, 5f, Path.Direction.CCW);

Row.create(c)
  .child(
    Text.create(c)
      .text("Hello Litho")
      .textSizeSp(16))
  .border(
    Border.create(c)
      .widthDip(YogaEdge.ALL, 5)
      .color(YogaEdge.ALL, 0xfff36b7f)
      // We set the spacing between stamps to 15
      .pathDashEffect(dot, 15f, 0f, PathDashPathEffect.Style.ROTATE)
      .build())
  .build();

Composition

You may compose multiple effects by simply specifying more than one. This effect utilizes ComposePathEffect internally.

IMPORTANT: Currently Litho does not support composing more than two effects.

Composed Effect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Row.create(c)
  .child(
    Text.create(c)
      .text("Hello Litho")
      .textSizeSp(16))
  .border(
    Border.create(c)
      .widthDip(YogaEdge.ALL, 5)
      .color(YogaEdge.ALL, 0xfff36b7f)
      // The effects below will be composed together
      // resulting in a rounded corner, dashed border
      .dashEffect(new float[] {10f, 5f}, 0f)
      .cornerEffect(10f)
      .build())
  .build();

Edit on GitHub