Material Motion Exploring solutions that will empower creators with the tools needed to describe and implement rich, interactive motion on any platform. Edit this page · History

February 09-15, 2017

This weekly update captures what changed in a given week across the Material Motion ecosystem.


🎉 Core team spent most of the week preparing for and presenting an architectural overview talk for Google.

🎉 We have archived all pre-reactive libraries as part of a general cleanup effort in preparation for our end of month API freeze. View the old libraries.

Android platform

🎉 Formalized using reactive properties as interaction input/output. Case study: Tossable and Tap.

Tossable tossable = new Tossable(ReactiveProperty.of(ViewProperties.POSITION.get(target)));
runtime.addInteraction(tossable, target);

Tap tap = new Tap(container);
runtime.addInteraction(tap, tossable.anchor);

📝 Formalizing Interaction.enabled reactive property as a way to pause interactions.

📝 Importing Material Motion into Google. Internal integration to come soon.

📝 Componentizing physics-android library to potentially replace rebound.

Apple platforms

🎉 Eliminated the state channel on MotionObservable. This resolves a class of problems related to connecting gesture recognizers and springs.

🎉 Landed a first pass of a timeline scrubbing API. The following demo shows how one might use this to visualize changes to a paused animation in real time.

timeline.timeOffset.value = slider.value * 0.4
timeline.paused.value = true

let arcMove = ArcMove(duration: 0.4, from: square.position, to: circle.position, system: coreAnimation)
arcMove.timeline = timeline
runtime.add(arcMove, to: square2)

// Later on, in reaction to slider value change:
timeline.timeOffset.value = slider.value * 0.4

📝 Timelines can be paused and unpaused. When using Core Animation to back the animation, the remainder of the animation will be run via Core Animation rather than the main thread.

📝 Exploring a prototype of a “breakable rubber band”.

📝 Added a carousel case study. This demo shows how one might key certain animations off of scroll position.

let pageEdge = stream.x().offset(by: -page.frame.origin.x)

runtime.add(pageEdge.mapRange(rangeStart: 0, rangeEnd: 128,
                              destinationStart: 1, destinationEnd: 0),
            to: page.alpha)
runtime.add(pageEdge.mapRange(rangeStart: -view.bounds.width, rangeEnd: 0,
                              destinationStart: 0.5, destinationEnd: 1.0),
            to: page.scale)

📝 Added a rudimentary chat heads demo.

  .closestEdge(in: view.bounds.insetBy(dx: circle.bounds.width / 2 - 8,
                                       dy: circle.bounds.width / 2 - 8)),
            to: tossable.destination)
runtime.add(tossable, to: circle)

Web frameworks

📝 Working on collaboration between gestures and springs in bottom sheet demo.


📝 Exploring debug visualizations for path-based tweens.

This demo shows animations leaving a trail:

This demo shows animations plotting their course at all times:


Android platform support

Library Build status Coverage Version Issues
conventions-android       0 open
gestures-android passing 91% v1.0.0 4 open
indefinite-observable-android passing 100% v2.0.0 0 open
physics-android       0 open
streams-android passing 27% v1.0.0 12 open

Apple platform support

Library Build status Coverage Version Platforms Docs Issues
catalog-swift passing         10 open
conventions-objc           0 open
indefinite-observable-swift passing 100% v3.1.0 ios / osx 54% 0 open
streams-swift passing 6%       13 open

Web platform support

Library Build status Coverage Version Issues
indefinite-observable-js passing 100% v1.0.1 3 open
material-motion-js passing     41 open

Misc libraries

Library Build status Coverage Version Issues
apidiff passing 86% v1.0.0 11 open
chrome-inspector       4 open
ci-staging-area       0 open
direct-web       0 open
material-motion       [-38-]{+39+} open
milemarker       18 open
starmap       48 open
sublime       4 open
tools       [-100-]{+101+} open

Learn more

Join us on Discord!