package com.kaichunlin.transition.app;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.annotation.UiThread;
import android.support.v4.view.animation.FastOutLinearInInterpolator;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import com.kaichunlin.transition.Cascade;
import com.kaichunlin.transition.ViewTransitionBuilder;
import com.kaichunlin.transition.adapter.SlidingUpPanelLayoutAdapter;
import com.kaichunlin.transition.adapter.UnifiedAdapter;
import com.kaichunlin.transition.animation.Animation;
import com.kaichunlin.transition.animation.AnimationListener;
import com.kaichunlin.transition.internal.TransitionController;
import com.kaichunlin.transition.internal.debug.TraceAnimationListener;
import com.kaichunlin.transition.internal.debug.TraceTransitionManagerListener;
import com.kaichunlin.transition.transformer.ScaledTransformer;
import com.kaichunlin.transition.util.TransitionUtil;
import com.sothree.slidinguppanel.SlidingUpPanelLayout;
import kaichunlin.transition.app.R;
public class SlidingUpPanelActivity extends AppCompatActivity implements View.OnClickListener {
private UnifiedAdapter mUnifiedAdapter;
private Toolbar mToolbar;
private Interpolator mInterpolator = new AccelerateDecelerateInterpolator();
private View mLastSelection;
private Menu mMenu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_slideup_actionbar);
findViewById(R.id.rotate_slide).setOnClickListener(this);
findViewById(R.id.sliding_actionbar_view).setOnClickListener(this);
findViewById(R.id.change_actionbar_color).setOnClickListener(this);
findViewById(R.id.change_actionbar_color_hsv).setOnClickListener(this);
findViewById(R.id.fading_actionbar).setOnClickListener(this);
findViewById(R.id.rotating_actionbar).setOnClickListener(this);
findViewById(R.id.grayscale_bg).setOnClickListener(this);
findViewById(R.id.cascade_fading).setOnClickListener(this);
findViewById(R.id.cascade_rolling).setOnClickListener(this);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
SlidingUpPanelLayout supl = ((SlidingUpPanelLayout) findViewById(R.id.sliding_layout));
//set up the adapter
SlidingUpPanelLayoutAdapter mSlidingUpPanelLayoutAdapter = new SlidingUpPanelLayoutAdapter();
supl.addPanelSlideListener(mSlidingUpPanelLayoutAdapter);
//the adapter accepts another SlidingUpPanelLayout.PanelSlideListener so other customizations can be performed
mSlidingUpPanelLayoutAdapter.setPanelSlideListener(new DialogPanelSlideListener(this));
mUnifiedAdapter = new UnifiedAdapter(mSlidingUpPanelLayoutAdapter);
mUnifiedAdapter.setDuration(1000);
mUnifiedAdapter.addAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animationManager) {
}
@Override
public void onAnimationEnd(Animation animationManager) {
mUnifiedAdapter.setReverseAnimation(!mUnifiedAdapter.isReverseAnimation());
}
@Override
public void onAnimationCancel(Animation animationManager) {
mUnifiedAdapter.setReverseAnimation(!mUnifiedAdapter.isReverseAnimation());
}
@Override
public void onAnimationReset(Animation animationManager) {
}
});
//debug
mUnifiedAdapter.addTransitionListener(new TraceTransitionManagerListener());
mUnifiedAdapter.addAnimationListener(new TraceAnimationListener());
//this is required since some transition requires the width/height/position of a view, which is not yet properly initialized until layout is complete
//in this example, another way of achieving correct behavior without using ViewUtil.executeOnGlobalLayout() would be to change all
// translationYAsFractionOfHeight() calls to delayTranslationYAsFractionOfHeight() which would defer the calculation until the transition is just about to start
TransitionUtil.executeOnGlobalLayout(this, new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
updateTransition(findViewById(R.id.rotate_slide), false);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.sliding_up_panel, menu);
mMenu = menu;
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem menu) {
super.onOptionsItemSelected(menu);
boolean changeInterpolator = true;
switch (menu.getItemId()) {
case R.id.menu_default:
mInterpolator = new AccelerateDecelerateInterpolator();
break;
case R.id.menu_linear:
mInterpolator = new LinearInterpolator();
break;
case R.id.menu_accelerate:
mInterpolator = new AccelerateInterpolator();
break;
case R.id.menu_decelerate:
mInterpolator = new DecelerateInterpolator();
break;
case R.id.menu_linearin:
mInterpolator = new FastOutLinearInInterpolator();
break;
case R.id.menu_anticipate:
mInterpolator = new AnticipateInterpolator();
break;
case R.id.menu_animate:
changeInterpolator = false;
mUnifiedAdapter.startAnimation(1000);
break;
}
if (changeInterpolator) {
updateTransition(mLastSelection, false);
}
return true;
}
@Override
public void onClick(View v) {
updateTransition(v, mUnifiedAdapter.isReverseAnimation() || mUnifiedAdapter.isAnimating());
}
@UiThread
public void updateTransition(View v, boolean animate) {
if (animate) {
mUnifiedAdapter.setReverseAnimation(true);
mUnifiedAdapter.startAnimation();
return;
}
//TODO removeAllTransitions() has to be called *after* mAnimationAdapter.resetAnimation(), this subtle order of execution requirement should be removed
mUnifiedAdapter.removeAllTransitions();
mLastSelection = v;
boolean enableAnimationMenu = true;
//configure a builder with properties shared by all instances and just clone it for future use
//since adapter(ITransitionAdapter) is set, simply call buildFor(mUnifiedAdapter) would add the resultant ViewTransition to the adapter
ViewTransitionBuilder baseBuilder = ViewTransitionBuilder.transit(mToolbar).interpolator(mInterpolator);
ViewTransitionBuilder builder;
((ImageView) findViewById(R.id.content_bg)).setColorFilter(null);
boolean setHalfHeight = false;
switch (v.getId()) {
//TODO visual artifact on Android 5.1 (Nexus 7 2013) when rotationX is ~45, why???
case R.id.rotate_slide:
builder = baseBuilder.clone();
builder.scale(0.8f).rotationX(40).translationYAsFractionOfHeight(-1f).buildFor(mUnifiedAdapter);
builder = baseBuilder.clone().target(findViewById(R.id.content_bg)).rotationX(42f).scale(0.8f).translationYAsFractionOfHeight(-0.5f);
builder.buildFor(mUnifiedAdapter);
builder.target(findViewById(R.id.content)).buildFor(mUnifiedAdapter);
builder = baseBuilder.clone().target(findViewById(R.id.content));
Cascade cascade = new Cascade(Cascade.STAGGERED, 0.6f).reverse();
builder.transitViewGroup(new ViewTransitionBuilder.ViewGroupTransition() {
@Override
public void transit(ViewTransitionBuilder builder, ViewTransitionBuilder.ViewGroupTransitionConfig config) {
builder.translationYAsFractionOfHeight(config.parentViewGroup, 1f).buildFor(mUnifiedAdapter);
}
}, cascade);
enableAnimationMenu = false;
break;
case R.id.sliding_actionbar_view:
baseBuilder.clone().translationYAsFractionOfHeight(-1f).buildFor(mUnifiedAdapter);
builder = baseBuilder.clone().target(findViewById(R.id.content)).translationYAsFractionOfHeight(-0.5f);
builder.buildFor(mUnifiedAdapter);
//apply the exact same transition to another view
builder.target(findViewById(R.id.content_bg2)).buildFor(mUnifiedAdapter);
break;
case R.id.change_actionbar_color:
baseBuilder.clone().backgroundColorResource(getResources(), R.color.primary, R.color.accent).buildFor(mUnifiedAdapter);
break;
case R.id.change_actionbar_color_hsv:
baseBuilder.clone().backgroundColorResourceHSV(getResources(), R.color.primary, R.color.drawer_opened).buildFor(mUnifiedAdapter);
break;
case R.id.fading_actionbar:
baseBuilder.clone().alpha(1f, 0f).buildFor(mUnifiedAdapter);
break;
case R.id.rotating_actionbar:
baseBuilder.clone().delayTranslationYAsFractionOfHeight(-0.5f).delayRotationX(90f).scale(0.8f).buildFor(mUnifiedAdapter);
break;
case R.id.grayscale_bg:
//Uses a CustomTransitionController that applies a ColorMatrixColorFilter to the background view
baseBuilder.clone().addViewTransformer(new ScaledTransformer() {
ColorMatrix matrix = new ColorMatrix();
ImageView bg;
@Override
public void updateViewScaled(TransitionController controller, View target, float progress) {
matrix.setSaturation(1 - progress);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
if(bg==null) {
bg=(ImageView) findViewById(R.id.content_bg);
}
bg.setColorFilter(filter);
}
}).range(0f, 1f).buildFor(mUnifiedAdapter);
setHalfHeight = true;
break;
case R.id.cascade_fading:
builder = baseBuilder.clone().target(findViewById(R.id.content));
cascade = new Cascade(Cascade.STAGGERED, 0.54f).reverse();
builder.transitViewGroup(new ViewTransitionBuilder.ViewGroupTransition() {
@Override
public void transit(ViewTransitionBuilder builder, ViewTransitionBuilder.ViewGroupTransitionConfig config) {
builder.alpha(0f).buildFor(mUnifiedAdapter);
}
}, cascade);
break;
case R.id.cascade_rolling:
builder = baseBuilder.clone().target(findViewById(R.id.content));
cascade = new Cascade(Cascade.SEQUENTIAL, 0.64f).reverse();
builder.transitViewGroup(new ViewTransitionBuilder.ViewGroupTransition() {
@Override
public void transit(ViewTransitionBuilder builder, ViewTransitionBuilder.ViewGroupTransitionConfig config) {
builder.rotationX(90f).buildFor(mUnifiedAdapter);
}
}, cascade);
break;
}
//only show animate MenuItem when it's not the first option
if (mMenu != null) {
mMenu.findItem(R.id.menu_animate).setEnabled(enableAnimationMenu);
}
setSlidingUpPanelHeight(setHalfHeight);
}
private void setSlidingUpPanelHeight(boolean halfHeight) {
SlidingUpPanelLayout supl = ((SlidingUpPanelLayout) findViewById(R.id.sliding_layout));
View panel = supl.getChildAt(1);
ViewGroup.LayoutParams params = panel.getLayoutParams();
Rect rectangle = new Rect();
Window window = getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectangle);
int height = rectangle.bottom - rectangle.top;
params.height = halfHeight ? height / 2 : height;
supl.requestLayout();
}
}