diff --git a/library/src/main/java/com/google/android/material/motion/streams/MotionObservable.java b/library/src/main/java/com/google/android/material/motion/streams/MotionObservable.java index e9dc4e3..81dcc3a 100644 --- a/library/src/main/java/com/google/android/material/motion/streams/MotionObservable.java +++ b/library/src/main/java/com/google/android/material/motion/streams/MotionObservable.java @@ -16,6 +16,7 @@ package com.google.android.material.motion.streams; import android.support.annotation.IntDef; +import android.support.annotation.Nullable; import com.google.android.material.motion.observable.IndefiniteObservable; import com.google.android.material.motion.observable.Observer; @@ -77,4 +78,61 @@ public interface MotionObserver extends Observer { */ void state(@MotionState int state); } + + /** + * An operation is able to transform incoming values before choosing whether or not to pass them + * downstream. + * + * @param The incoming value type. + * @param The downstream value type. + */ + public interface Operation { + + /** + * Modifies the given value before passing it downstream, or blocks the value. + * + * @param observer Downstream. + * @param value The value from upstream. + */ + void next(MotionObserver observer, T value); + } + + /** + * A light-weight operator builder. + *

+ * This is the preferred method for building new operators. This builder can be used to create + * any operator that only needs to modify or block values. All state events are forwarded + * along. + * + * @see The + * operator() specification + */ + public MotionObservable operator(final Operation operation) { + final MotionObservable upstream = MotionObservable.this; + + return new MotionObservable<>(new Subscriber>() { + @Nullable + @Override + public Unsubscriber subscribe(final MotionObserver observer) { + final Subscription subscription = upstream.subscribe(new MotionObserver() { + @Override + public void next(T value) { + operation.next(observer, value); + } + + @Override + public void state(@MotionState int state) { + observer.state(state); + } + }); + + return new Unsubscriber() { + @Override + public void unsubscribe() { + subscription.unsubscribe(); + } + }; + } + }); + } } diff --git a/sample/src/main/java/com/google/android/material/motion/streams/sample/MainActivity.java b/sample/src/main/java/com/google/android/material/motion/streams/sample/MainActivity.java index 937bf49..3ad73d0 100644 --- a/sample/src/main/java/com/google/android/material/motion/streams/sample/MainActivity.java +++ b/sample/src/main/java/com/google/android/material/motion/streams/sample/MainActivity.java @@ -16,9 +16,13 @@ package com.google.android.material.motion.streams.sample; import android.graphics.Color; +import android.graphics.Typeface; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.style.StyleSpan; import android.view.View; import android.widget.Button; import android.widget.TextView; @@ -29,6 +33,7 @@ import com.google.android.material.motion.streams.MotionObservable; import com.google.android.material.motion.streams.MotionObservable.MotionObserver; import com.google.android.material.motion.streams.MotionObservable.MotionState; +import com.google.android.material.motion.streams.MotionObservable.Operation; import static com.google.android.material.motion.streams.MotionObservable.ACTIVE; import static com.google.android.material.motion.streams.MotionObservable.AT_REST; @@ -55,13 +60,15 @@ protected void onCreate(Bundle savedInstanceState) { Button nextButton = (Button) findViewById(R.id.next_button); Button unsubscribeButton = (Button) findViewById(R.id.unsubscribe_button); - MotionObservable observable = new MotionObservable<>( + final MotionObservable observable = new MotionObservable<>( new Subscriber>() { + @Nullable @Override public Unsubscriber subscribe(MotionObserver observer) { registerButtonCallback(observer); return new Unsubscriber() { + @Override public void unsubscribe() { unregisterButtonCallback(); @@ -70,9 +77,17 @@ public void unsubscribe() { } }); - final Subscription subscription = observable.subscribe(new MotionObserver() { + final Subscription subscription = observable.operator(new Operation() { + + @Override + public void next(MotionObserver observer, String value) { + CharSequence charSequence = italicizeAndCapitalize(value); + observer.next(charSequence); + } + }).subscribe(new MotionObserver() { + @Override - public void next(String value) { + public void next(CharSequence value) { text.setText(value); } @@ -116,6 +131,12 @@ public void onClick(View v) { }); } + private CharSequence italicizeAndCapitalize(String value) { + Spannable spannable = new SpannableString(value.toUpperCase()); + spannable.setSpan(new StyleSpan(Typeface.ITALIC), 0, spannable.length(), 0); + return spannable; + } + private void registerButtonCallback(MotionObserver observer) { callback = observer; }