Search Docs
Loading...
Skip to content

Apply Transitions

Add visual transitions to video clips by attaching CE.SDK In and Out animations to timeline blocks.

6 mins
estimated time
GitHub

Transitions in Android video compositions are block animations. An In animation runs after a clip becomes visible, and an Out animation runs before that clip leaves the page timeline. Android uses these animation APIs for this flow rather than a separate clip-to-clip transition object.

Create a Video Timeline#

Start with a video scene, a page, a track, and two graphic blocks that use video fills. The blocks act as clips on the track timeline.

val page = engine.block.create(DesignBlockType.Page)
engine.block.appendChild(parent = scene, child = page)
engine.block.setWidth(page, value = 1280F)
engine.block.setHeight(page, value = 720F)
engine.block.setDuration(page, duration = 8.0)
val track = engine.block.create(DesignBlockType.Track)
engine.block.appendChild(parent = page, child = track)
val firstClip = engine.block.create(DesignBlockType.Graphic)
engine.block.setShape(firstClip, shape = engine.block.createShape(ShapeType.Rect))
val firstVideoFill = engine.block.createFill(FillType.Video)
// Video source assignment uses CE.SDK's URI-valued fill property key.
engine.block.setUri(
block = firstVideoFill,
property = "fill/video/fileURI",
value = Uri.parse(
"https://cdn.img.ly/assets/demo/v1/ly.img.video/videos/pexels-drone-footage-of-a-surfer-barrelling-a-wave-12715991.mp4",
),
)
engine.block.setFill(block = firstClip, fill = firstVideoFill)
val secondClip = engine.block.create(DesignBlockType.Graphic)
engine.block.setShape(secondClip, shape = engine.block.createShape(ShapeType.Rect))
val secondVideoFill = engine.block.createFill(FillType.Video)
engine.block.setUri(
block = secondVideoFill,
property = "fill/video/fileURI",
value = Uri.parse("https://cdn.img.ly/assets/demo/v3/ly.img.video/videos/pexels-kampus-production-8154913.mp4"),
)
engine.block.setFill(block = secondClip, fill = secondVideoFill)
engine.block.appendChild(parent = track, child = firstClip)
engine.block.appendChild(parent = track, child = secondClip)
engine.block.fillParent(track)

The sample adds both clips to the track in playback order and keeps them full-screen with fillParent.

Check Animation Support#

Check each clip before creating transition animations. If a block does not support animations, skip transition setup instead of failing later.

if (!engine.block.supportsAnimation(firstClip) || !engine.block.supportsAnimation(secondClip)) {
engine.stop()
return@launch
}

Coordinate Clip Timing#

Set the clip durations in seconds. The track uses child order and each clip’s duration to place the second clip after the first.

engine.block.setDuration(block = firstClip, duration = 4.0)
engine.block.setDuration(block = secondClip, duration = 4.0)

The Out animation on the first clip plays during the final part of its duration. The In animation on the second clip plays after that clip reaches its time offset.

Apply an Exit Transition#

Create a fade animation, set its duration, and attach it as the first clip’s Out animation.

val firstClipOut = engine.block.createAnimation(AnimationType.Fade)
engine.block.setDuration(block = firstClipOut, duration = 0.8)
engine.block.setOutAnimation(block = firstClip, animation = firstClipOut)

Apply an Entrance Transition#

Create a slide animation, set its duration, and attach it as the second clip’s In animation.

val secondClipIn = engine.block.createAnimation(AnimationType.Slide)
engine.block.setDuration(block = secondClipIn, duration = 0.8)
engine.block.setInAnimation(block = secondClip, animation = secondClipIn)

The animation duration controls how long the transition effect lasts. It does not change the clip’s own timeline duration.

Configure Properties#

Use findAllProperties before setting type-specific animation properties. Common easing values are exposed through AnimationEasingType.

val slideProperties = engine.block.findAllProperties(secondClipIn)
// Animation properties use engine property keys; inspect type-specific keys first.
if ("animation/slide/direction" in slideProperties) {
engine.block.setFloat(
block = secondClipIn,
property = "animation/slide/direction",
value = Math.PI.toFloat(),
)
}
engine.block.setEnum(
block = secondClipIn,
property = "animationEasing",
value = AnimationEasingType.EASE_OUT.key,
)

The slide direction uses radians. Easing changes how quickly the transition accelerates and decelerates during its duration.

Replace a Transition#

When replacing the first clip’s Out transition, destroy the old animation block before assigning the replacement. Detached animation blocks are not destroyed automatically.

val currentOut = engine.block.getOutAnimation(firstClip)
if (engine.block.isValid(currentOut)) {
engine.block.destroy(currentOut)
}
val replacementOut = engine.block.createAnimation(AnimationType.Fade)
engine.block.setDuration(block = replacementOut, duration = 0.6)
engine.block.setOutAnimation(block = firstClip, animation = replacementOut)

Verify Attached Animations#

Read back the In and Out animation handles when your workflow needs to validate or update existing transitions.

val attachedIn = engine.block.getInAnimation(secondClip)
val attachedOut = engine.block.getOutAnimation(firstClip)
// Let the scheduled engine update lay out track children before reading derived offsets.
yield()
check(engine.block.isValid(attachedIn))
check(engine.block.isValid(attachedOut))
check(engine.block.getType(attachedIn) == AnimationType.Slide.key)
check(engine.block.getType(attachedOut) == AnimationType.Fade.key)
check(engine.block.getDuration(attachedIn) == 0.8)
check(engine.block.getDuration(attachedOut) == 0.6)
check(engine.block.getEnum(attachedIn, "animationEasing") == AnimationEasingType.EASE_OUT.key)
check(engine.block.getTimeOffset(secondClip) == 4.0)

Invalid handles mean that no animation is attached for that slot.

Troubleshooting#

  • Animation does not play: Verify supportsAnimation, clip visibility timing, and animation duration.
  • Transition appears at the wrong time: Check the clip’s timeOffset, the clip’s duration, and the transition animation’s own duration.
  • Property update fails: Inspect findAllProperties(animation) before setting type-specific keys like animation/slide/direction.

API Reference#

MethodPurpose
engine.block.appendChild(parent=_, child=_)Add the page, track, and clip blocks in timeline order.
engine.block.fillParent(block=_)Size the track clips to fill the page.
engine.block.setUri(block=_, property="fill/video/fileURI", value=_)Assign a video URI to a video fill.
engine.block.supportsAnimation(block=_)Check whether a block can use animations.
engine.block.createAnimation(type=_)Create an animation block for a supported AnimationType.
engine.block.setInAnimation(block=_, animation=_)Attach an entrance transition.
engine.block.setOutAnimation(block=_, animation=_)Attach an exit transition.
engine.block.getInAnimation(block=_)Read the current entrance animation handle.
engine.block.getOutAnimation(block=_)Read the current exit animation handle.
engine.block.setDuration(block=_, duration=_)Set clip or animation duration in seconds.
engine.block.getTimeOffset(block=_)Read the offset assigned by the track.
engine.block.setEnum(block=_, property="animationEasing", value=_)Configure an animation easing curve.
engine.block.setFloat(block=_, property="animation/slide/direction", value=_)Configure slide direction in radians.
engine.block.findAllProperties(block=_)Discover properties supported by a specific animation block.
engine.block.destroy(block=_)Destroy a replaced animation block.

Next Steps#