Last active
December 14, 2017 03:31
-
-
Save bangarharshit/a7b4614bd5d2fc77171fca8cdbb11f8b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.animation.Animator; | |
import android.animation.AnimatorListenerAdapter; | |
import android.view.View; | |
import com.example.harshitbangar.ribswithoutdagger.ScreenStackImpl; | |
import static android.view.View.GONE; | |
import static android.view.View.VISIBLE; | |
public class CrossfadeTransition implements Transition { | |
@Override | |
public void animate( | |
final View from, final View to, ScreenStackImpl.NavigationType navType, ScreenStackImpl.Direction direction, final Callback callback) { | |
to.setAlpha(0f); | |
from.setAlpha(1f); | |
to.setVisibility(VISIBLE); | |
from.setVisibility(VISIBLE); | |
from.animate().alpha(0f).setListener(new AnimatorListenerAdapter() { | |
@Override | |
public void onAnimationEnd(Animator animation) { | |
from.setVisibility(GONE); | |
to.animate().alpha(1f).setListener(new AnimatorListenerAdapter() { | |
@Override | |
public void onAnimationEnd(Animator animation) { | |
callback.onAnimationEnd(); | |
} | |
}).start(); | |
} | |
}).start(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.harshitbangar.ribswithoutdagger; | |
import android.os.Parcelable; | |
import android.util.SparseArray; | |
import android.view.View; | |
import android.view.ViewGroup; | |
import com.example.harshitbangar.ribswithoutdagger.transition.Transition; | |
import com.uber.rib.core.screenstack.ScreenStackBase; | |
import com.uber.rib.core.screenstack.ViewProvider; | |
import java.util.ArrayDeque; | |
import java.util.Deque; | |
import static com.example.harshitbangar.ribswithoutdagger.ScreenStackImpl.Direction.FORWARD; | |
import static com.example.harshitbangar.ribswithoutdagger.Views.whenMeasured; | |
public class ScreenStackImpl implements ScreenStackBase { | |
private final Deque<StateFulViewProvider> backStack = new ArrayDeque<>(); | |
private final ViewGroup parentViewGroup; | |
private View ghostView; // keep track of the disappearing view we are animating | |
private final Transition defaultTransiton; | |
private Transition overridingTransition; | |
public ScreenStackImpl(ViewGroup parentViewGroup, Transition defaultTransiton) { | |
this.parentViewGroup = parentViewGroup; | |
this.defaultTransiton = defaultTransiton; | |
} | |
public void setOverridingTransition(Transition overridingTransition) { | |
this.overridingTransition = overridingTransition; | |
} | |
@Override public void pushScreen(final ViewProvider viewProvider) { | |
pushScreen(viewProvider, false); | |
} | |
@Override public void pushScreen(final ViewProvider viewProvider, boolean shouldAnimate) { | |
navigate(new Runnable() { | |
@Override public void run() { | |
backStack.push(new StateFulViewProvider(viewProvider)); | |
} | |
}, Direction.FORWARD); | |
} | |
@Override public void popScreen() { | |
popScreen(false); | |
} | |
@Override public void popScreen(boolean shouldAnimate) { | |
navigate(new Runnable() { | |
@Override public void run() { | |
backStack.remove(); | |
} | |
}, Direction.BACKWARD); | |
} | |
@Override public void popBackTo(int index, boolean shouldAnimate) { } | |
@Override public boolean handleBackPress() { | |
return false; | |
} | |
@Override public boolean handleBackPress(boolean shouldAnimate) { | |
return false; | |
} | |
@Override public int size() { | |
return backStack.size(); | |
} | |
private void navigate(final Runnable backStackOperation, final Direction direction) { | |
View from = removeCurrentScreen(); | |
saveCurrentState(from); | |
backStackOperation.run(); | |
View to = showCurrentScreen(direction); | |
animateAndRemove(from, to, direction); | |
restoreCurrentState(to); | |
} | |
private void restoreCurrentState(View currentView) { | |
StateFulViewProvider stateFulViewProvider = currentStateFulViewProvider(); | |
if (stateFulViewProvider == null) { | |
return; | |
} | |
currentView.restoreHierarchyState(stateFulViewProvider.parcelableSparseArray); | |
} | |
private void saveCurrentState(View currentView) { | |
StateFulViewProvider stateFulViewProvider = currentStateFulViewProvider(); | |
if (stateFulViewProvider == null) { | |
return; | |
} | |
currentView.saveHierarchyState(stateFulViewProvider.parcelableSparseArray); | |
} | |
private View removeCurrentScreen() { | |
if (isAnimating()) { | |
parentViewGroup.removeView(ghostView); | |
ghostView = null; | |
} | |
return parentViewGroup.getChildAt(0); | |
} | |
private boolean isAnimating() { | |
return ghostView != null; | |
} | |
private View showCurrentScreen(final Direction direction) { | |
StateFulViewProvider stateFulViewProvider = currentStateFulViewProvider(); | |
if (stateFulViewProvider == null) { | |
return null; | |
} | |
View currentView = stateFulViewProvider.viewProvider.buildView(parentViewGroup); | |
parentViewGroup.addView(currentView, direction == FORWARD ? parentViewGroup.getChildCount() : 0); | |
return currentView; | |
} | |
private void animateAndRemove( | |
final View from, final View to, final Direction direction) { | |
if (from == null) { | |
return; | |
} | |
if (to == null) { | |
parentViewGroup.removeView(from); | |
return; | |
} | |
ghostView = from; | |
final Transition transitionToUse = overridingTransition != null ? overridingTransition : defaultTransiton; | |
overridingTransition = null; | |
whenMeasured(to, new Views.OnMeasured() { | |
@Override | |
public void onMeasured() { | |
transitionToUse.animate(from, to, direction, new Transition.Callback() { | |
@Override | |
public void onAnimationEnd() { | |
if (parentViewGroup != null) { | |
parentViewGroup.removeView(from); | |
if (from == ghostView) { | |
// Only clear the ghost if it's the same as the view we just removed | |
ghostView = null; | |
} | |
} | |
} | |
}); | |
} | |
}); | |
} | |
private StateFulViewProvider currentStateFulViewProvider() { | |
if (!backStack.isEmpty()) { | |
return backStack.peek(); | |
} | |
return null; | |
} | |
static class StateFulViewProvider { | |
private final ViewProvider viewProvider; | |
private final SparseArray<Parcelable> parcelableSparseArray; | |
public StateFulViewProvider(ViewProvider viewProvider) { | |
this.viewProvider = viewProvider; | |
this.parcelableSparseArray = new SparseArray<>(); | |
} | |
} | |
public enum Direction { | |
FORWARD(1), | |
BACKWARD(-1); | |
private final int sign; | |
Direction(int sign) { | |
this.sign = sign; | |
} | |
public int sign() { | |
return sign; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.view.View; | |
import com.example.harshitbangar.ribswithoutdagger.ScreenStackImpl; | |
public interface Transition { | |
void animate(View from, View to, ScreenStackImpl.NavigationType navType, ScreenStackImpl.Direction direction, Callback callback); | |
interface Callback { | |
void onAnimationEnd(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.view.View; | |
import android.view.ViewTreeObserver; | |
final class Views { | |
private Views() { | |
throw new AssertionError(); | |
} | |
static void whenMeasured(final View view, final OnMeasured onMeasured) { | |
int width = view.getWidth(); | |
int height = view.getHeight(); | |
if (width > 0 && height > 0) { | |
onMeasured.onMeasured(); | |
return; | |
} | |
view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { | |
@Override | |
public boolean onPreDraw() { | |
final ViewTreeObserver observer = view.getViewTreeObserver(); | |
if (observer.isAlive()) { | |
observer.removeOnPreDrawListener(this); | |
} | |
onMeasured.onMeasured(); | |
return true; | |
} | |
}); | |
} | |
interface OnMeasured { | |
void onMeasured(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment