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
AttachWithSpring · TranslationGestureRecognizer · $.translated · GestureSource Tossable
Status Library
Draft as of December 16, 2016 interactions

Tossable specification

This is the engineering specification for the Tossable interaction.

Overview

The tossable interaction allows an element to be dragged and tossed to a destination.

Example use:

let tossable = Tossable(position: propertyOf(view).center,
                        to: propertyOf(targetView).center,
                        containerView: view,
                        springSource: popSpringSource)

MVP

Expose a Tossable type

Subclass the AttachWithSpring interaction.

public class Tossable: AttachWithSpring

Expose configurable values

All property values should be readonly, all stream values should be settable.

class Tossable {
  /** A stream that emits the pan gesture's velocity when the gesture ends. */
  public var initialVelocityStream: MotionObservable<CGPoint>

Expose an initializer

class Tossable {
  public init(position: ReactiveProperty<CGPoint>,
              to destination: ReactiveProperty<CGPoint>,
              containerView: UIView,
              springSource: SpringSource<CGPoint>,
              panGestureRecognizer: UIPanGestureRecognizer? = nil)
}

Create a pan gesture recognizer if one was not provided

class Tossable {
  init(...) {
    let panGestureRecognizer = panGestureRecognizer ?? UIPanGestureRecognizer()
    if panGestureRecognizer.view == nil {
      containerView.addGestureRecognizer(panGestureRecognizer)
    }

    ...

Create a translation stream

class Tossable {
  init(...) {
    ...

    let dragStream = gestureSource(panGestureRecognizer)
    let translationStream = dragStream.translated(from: position, in: containerView)

    ...

Store the initial velocity stream

class Tossable {
  init(...) {
    ...

    self.initialVelocityStream = dragStream.onRecognitionState(.ended).velocity(in: container)

    ...

Call super and store the position stream

class Tossable {
  init(...) {
    ...

    super.init(position: position, to: destination, springSource: springSource)

    self.positionStream = self.positionStream.toggled(with: translationStream)
  }