Update Scene
This commit is contained in:
1 parent
781bf86ef1
commit
e8d1d92bfb
9 files changed
+294
-44
No files matched your search
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.animation;
|
||||
|
||||
import android.animation.TypeEvaluator;
|
||||
|
||||
/**
|
||||
* This evaluator can be used to perform type interpolation between integer
|
||||
* values that represent ARGB colors.
|
||||
*/
|
||||
public class ArgbEvaluator implements TypeEvaluator {
|
||||
private static final ArgbEvaluator sInstance = new ArgbEvaluator();
|
||||
|
||||
/**
|
||||
* Returns an instance of <code>ArgbEvaluator</code> that may be used in
|
||||
* {@link android.animation.ValueAnimator#setEvaluator(TypeEvaluator)}. The same instance may
|
||||
* be used in multiple <code>Animator</code>s because it holds no state.
|
||||
* @return An instance of <code>ArgbEvalutor</code>.
|
||||
*/
|
||||
public static ArgbEvaluator getInstance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns the calculated in-between value for a color
|
||||
* given integers that represent the start and end values in the four
|
||||
* bytes of the 32-bit int. Each channel is separately linearly interpolated
|
||||
* and the resulting calculated values are recombined into the return value.
|
||||
*
|
||||
* @param fraction The fraction from the starting to the ending values
|
||||
* @param startValue A 32-bit int value representing colors in the
|
||||
* separate bytes of the parameter
|
||||
* @param endValue A 32-bit int value representing colors in the
|
||||
* separate bytes of the parameter
|
||||
* @return A value that is calculated to be the linearly interpolated
|
||||
* result, derived by separating the start and end values into separate
|
||||
* color channels and interpolating each one separately, recombining the
|
||||
* resulting values in the same way.
|
||||
*/
|
||||
public Object evaluate(float fraction, Object startValue, Object endValue) {
|
||||
int startInt = (Integer) startValue;
|
||||
int startA = (startInt >> 24) & 0xff;
|
||||
int startR = (startInt >> 16) & 0xff;
|
||||
int startG = (startInt >> 8) & 0xff;
|
||||
int startB = startInt & 0xff;
|
||||
|
||||
int endInt = (Integer) endValue;
|
||||
int endA = (endInt >> 24) & 0xff;
|
||||
int endR = (endInt >> 16) & 0xff;
|
||||
int endG = (endInt >> 8) & 0xff;
|
||||
int endB = endInt & 0xff;
|
||||
|
||||
return ((startA + (int)(fraction * (endA - startA))) << 24) |
|
||||
((startR + (int)(fraction * (endR - startR))) << 16) |
|
||||
((startG + (int)(fraction * (endG - startG))) << 8) |
|
||||
((startB + (int)(fraction * (endB - startB))));
|
||||
}
|
||||
}
|
||||
@@ -62,15 +62,14 @@ public class GalleryListScene extends Scene implements SearchLayout.SearhLayoutH
|
||||
|
||||
private PagerAdapter mPagerAdapter;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
mActivity = (ContentActivity) getStageActivity();
|
||||
mResources = mActivity.getResources();
|
||||
}
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
@Override
|
||||
public View onCreateSceneView(Bundle savedInstanceState) {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mActivity = (ContentActivity) getStageActivity();
|
||||
mResources = mActivity.getResources();
|
||||
|
||||
LayoutInflater inflater = mActivity.getLayoutInflater();
|
||||
|
||||
// Search View
|
||||
@@ -94,9 +93,9 @@ public class GalleryListScene extends Scene implements SearchLayout.SearhLayoutH
|
||||
});
|
||||
|
||||
// Main View
|
||||
View sceneView = inflater.inflate(R.layout.scene_gallery_list, null);
|
||||
mAppbar = (Appbar) sceneView.findViewById(R.id.appbar);
|
||||
mViewPager = (ViewPager) sceneView.findViewById(R.id.viewPager);
|
||||
setContentView(R.layout.scene_gallery_list);
|
||||
mAppbar = (Appbar) findViewById(R.id.appbar);
|
||||
mViewPager = (ViewPager) findViewById(R.id.viewPager);
|
||||
|
||||
mAppbar.setTitle(mResources.getString(R.string.app_name));
|
||||
|
||||
@@ -110,8 +109,6 @@ public class GalleryListScene extends Scene implements SearchLayout.SearhLayoutH
|
||||
if (fitPaddingBottom != -1) {
|
||||
setFitPaddingBottom(fitPaddingBottom);
|
||||
}
|
||||
|
||||
return sceneView;
|
||||
}
|
||||
|
||||
private void setFitPaddingBottom(int fitPaddingBottom) {
|
||||
@@ -195,5 +192,4 @@ public class GalleryListScene extends Scene implements SearchLayout.SearhLayoutH
|
||||
view.removeView((View) object);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,8 +17,6 @@ package com.hippo.ehviewer.ui.scene;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.ui.ContentActivity;
|
||||
@@ -31,14 +29,10 @@ public class TestScene extends Scene {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.scene_test);
|
||||
|
||||
mActivity = (ContentActivity) getStageActivity();
|
||||
mResources = mActivity.getResources();
|
||||
}
|
||||
|
||||
@SuppressWarnings("InflateParams")
|
||||
public View onCreateSceneView(Bundle savedInstanceState) {
|
||||
LayoutInflater inflater = mActivity.getLayoutInflater();
|
||||
|
||||
return inflater.inflate(R.layout.scene_test, null);
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,9 @@ import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.hippo.util.AssertUtils;
|
||||
|
||||
@@ -35,7 +37,9 @@ import com.hippo.util.AssertUtils;
|
||||
*/
|
||||
public abstract class Scene {
|
||||
|
||||
private @Nullable View mSceneView;
|
||||
private @Nullable FrameLayout mSceneView;
|
||||
|
||||
private int mBackgroundColor = 0xffeeeeee; // TODO Need a better to set background color
|
||||
|
||||
private static SceneManager sSceneManager;
|
||||
|
||||
@@ -50,7 +54,12 @@ public abstract class Scene {
|
||||
return stageActivity;
|
||||
}
|
||||
|
||||
@Nullable View getSceneView() {
|
||||
/**
|
||||
* You will get null before onCreate and after onDestroy mostly
|
||||
*
|
||||
* @return Null or nonull
|
||||
*/
|
||||
public @Nullable View getSceneView() {
|
||||
return mSceneView;
|
||||
}
|
||||
|
||||
@@ -73,7 +82,11 @@ public abstract class Scene {
|
||||
|
||||
void create(Bundle savedInstanceState) {
|
||||
onCreate(savedInstanceState);
|
||||
mSceneView = onCreateSceneView(savedInstanceState);
|
||||
|
||||
if (mSceneView == null) {
|
||||
mSceneView = new FrameLayout(getStageActivity());
|
||||
initBackground(mSceneView);
|
||||
}
|
||||
|
||||
// Make sure scene view is attach from stage
|
||||
attachToStage();
|
||||
@@ -104,15 +117,45 @@ public abstract class Scene {
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
}
|
||||
|
||||
/**
|
||||
* It is called after {@link #onCreate(android.os.Bundle)}.
|
||||
* Create view of the scene.
|
||||
*
|
||||
* @param savedInstanceState null for first time, non null for recrearte
|
||||
* @return the view of the scene
|
||||
*/
|
||||
protected @Nullable View onCreateSceneView(Bundle savedInstanceState) {
|
||||
return null;
|
||||
public void setBackgroundColor(int bgColor) {
|
||||
if (mBackgroundColor != bgColor) {
|
||||
mBackgroundColor = bgColor;
|
||||
View sceneView = getSceneView();
|
||||
if (sceneView != null) {
|
||||
sceneView.setBackgroundColor(bgColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getBackgroundColor() {
|
||||
return mBackgroundColor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected void setContentView(int resId) {
|
||||
AssertUtils.assertNull("Only call setContentView once", mSceneView);
|
||||
|
||||
StageActivity sa = getStageActivity();
|
||||
mSceneView = new FrameLayout(sa);
|
||||
initBackground(mSceneView);
|
||||
mSceneView.setBackgroundColor(mBackgroundColor);
|
||||
sa.getLayoutInflater().inflate(resId, mSceneView);
|
||||
}
|
||||
|
||||
protected void setContentView(View view) {
|
||||
AssertUtils.assertNull("Only call setContentView once", mSceneView);
|
||||
|
||||
StageActivity sa = getStageActivity();
|
||||
mSceneView = new FrameLayout(sa);
|
||||
initBackground(mSceneView);
|
||||
mSceneView.addView(view, new FrameLayout.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
}
|
||||
|
||||
private void initBackground(@NonNull View bg) {
|
||||
bg.setBackgroundColor(mBackgroundColor);
|
||||
bg.setClickable(true);
|
||||
}
|
||||
|
||||
protected void onResume() {
|
||||
@@ -125,6 +168,23 @@ public abstract class Scene {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds a view that was identified by the id attribute from the XML that
|
||||
* was processed in {@link #onCreate}.
|
||||
*
|
||||
* @param resId the Id
|
||||
* @return The view if found or null otherwise.
|
||||
*/
|
||||
public View findViewById(int resId) {
|
||||
View sceneView = getSceneView();
|
||||
if (sceneView != null) {
|
||||
return sceneView.findViewById(resId);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is scene view attached to stage
|
||||
*
|
||||
|
||||
@@ -85,7 +85,7 @@ class SceneManager {
|
||||
scene.destroy(false);
|
||||
|
||||
if (previousState != null) {
|
||||
curtain.open(previousState, scene);
|
||||
curtain.close(previousState, scene);
|
||||
}
|
||||
} else {
|
||||
scene.destroy(true);
|
||||
@@ -138,7 +138,8 @@ class SceneManager {
|
||||
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
for (Pair<Scene, Curtain> p : mSceneStack) {
|
||||
p.first.saveInstanceState(outState);
|
||||
Scene scene = p.first;
|
||||
scene.saveInstanceState(outState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,17 +15,21 @@
|
||||
|
||||
package com.hippo.scene;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.graphics.Color;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
||||
import com.hippo.animation.ArgbEvaluator;
|
||||
import com.hippo.util.ViewUtils;
|
||||
|
||||
public class TransitionCurtain extends Curtain {
|
||||
|
||||
private static long ANIMATE_TIME = 300L;
|
||||
private static long ANIMATE_DELAY = 500L;
|
||||
private static long ANIMATE_TIME = 800L;
|
||||
|
||||
private ViewPair[] mViewPairArray;
|
||||
|
||||
@@ -33,14 +37,28 @@ public class TransitionCurtain extends Curtain {
|
||||
mViewPairArray = viewPairArray;
|
||||
}
|
||||
|
||||
|
||||
// Make background from transport to default.
|
||||
// Invisible other
|
||||
@Override
|
||||
public void open(final @NonNull Scene enter, final @NonNull Scene exit) {
|
||||
|
||||
// Handle background
|
||||
final int bgColor = enter.getBackgroundColor();
|
||||
enter.setBackgroundColor(Color.TRANSPARENT);
|
||||
|
||||
ObjectAnimator colorAnim = ObjectAnimator.ofInt(enter, "backgroundColor", bgColor);
|
||||
colorAnim.setEvaluator(ArgbEvaluator.getInstance());
|
||||
colorAnim.setDuration(ANIMATE_TIME);
|
||||
|
||||
colorAnim.start();
|
||||
|
||||
// Handle transit part
|
||||
for (ViewPair pair : mViewPairArray) {
|
||||
final View enterView = pair.getToView(enter);
|
||||
final View exitView = pair.getFromView(exit);
|
||||
if (enterView == null || exitView == null) {
|
||||
// Can't get to view
|
||||
// Can't get view
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -53,9 +71,9 @@ public class TransitionCurtain extends Curtain {
|
||||
ViewUtils.removeOnGlobalLayoutListener(enterView.getViewTreeObserver(), this);
|
||||
|
||||
int[] startloaction = new int[2];
|
||||
ViewUtils.getLocationInAncestor(exitView, startloaction, exit.getStageActivity().getStageLayout());
|
||||
ViewUtils.getLocationInAncestor(exitView, startloaction, exit.getSceneView());
|
||||
int[] endloaction = new int[2];
|
||||
ViewUtils.getLocationInAncestor(enterView, endloaction, enter.getStageActivity().getStageLayout());
|
||||
ViewUtils.getLocationInAncestor(enterView, endloaction, enter.getSceneView());
|
||||
int startWidth = exitView.getWidth();
|
||||
int startHeight = exitView.getHeight();
|
||||
int endWidth = enterView.getWidth();
|
||||
@@ -63,6 +81,8 @@ public class TransitionCurtain extends Curtain {
|
||||
|
||||
ViewUtils.setVisibility(exitView, View.INVISIBLE);
|
||||
ViewUtils.setVisibility(enterView, View.VISIBLE);
|
||||
enterView.setPivotX(0);
|
||||
enterView.setPivotY(0);
|
||||
|
||||
// Start animation
|
||||
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(enterView, "scaleX", (float) startWidth / endWidth, 1f);
|
||||
@@ -74,18 +94,93 @@ public class TransitionCurtain extends Curtain {
|
||||
ObjectAnimator yAnim = ObjectAnimator.ofFloat(enterView, "y", startloaction[1], endloaction[1]);
|
||||
yAnim.setDuration(ANIMATE_TIME);
|
||||
|
||||
yAnim.addListener(new SimpleAnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
ViewUtils.setVisibility(exitView, View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
ViewUtils.setVisibility(exitView, View.VISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
scaleXAnim.start();
|
||||
scaleYAnim.start();
|
||||
xAnim.start();
|
||||
yAnim.start();
|
||||
|
||||
// TODO show other part progressively
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(@NonNull Scene enter, @NonNull Scene exit) {
|
||||
dispatchDetachFromeStage(exit);
|
||||
public void close(@NonNull Scene enter, final @NonNull Scene exit) {
|
||||
|
||||
// Handle background
|
||||
ObjectAnimator colorAnim = ObjectAnimator.ofInt(exit, "backgroundColor", Color.TRANSPARENT);
|
||||
colorAnim.setEvaluator(ArgbEvaluator.getInstance());
|
||||
colorAnim.setDuration(ANIMATE_TIME);
|
||||
|
||||
colorAnim.start();
|
||||
|
||||
// Handle transit part
|
||||
for (ViewPair pair : mViewPairArray) {
|
||||
final View enterView = pair.getFromView(enter);
|
||||
final View exitView = pair.getToView(exit);
|
||||
if (enterView == null || exitView == null) {
|
||||
// Can't get view
|
||||
continue;
|
||||
}
|
||||
|
||||
int[] startloaction = new int[2];
|
||||
ViewUtils.getLocationInAncestor(exitView, startloaction, exit.getSceneView());
|
||||
int[] endloaction = new int[2];
|
||||
ViewUtils.getLocationInAncestor(enterView, endloaction, enter.getSceneView());
|
||||
int startWidth = exitView.getWidth();
|
||||
int startHeight = exitView.getHeight();
|
||||
int endWidth = enterView.getWidth();
|
||||
int endHeight = enterView.getHeight();
|
||||
|
||||
ViewUtils.setVisibility(exitView, View.VISIBLE);
|
||||
ViewUtils.setVisibility(enterView, View.INVISIBLE);
|
||||
exitView.setPivotX(0);
|
||||
exitView.setPivotY(0);
|
||||
|
||||
// Start animation
|
||||
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(exitView, "scaleX", (float) endWidth / startWidth);
|
||||
scaleXAnim.setDuration(ANIMATE_TIME);
|
||||
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(exitView, "scaleY", (float) endHeight / startHeight);
|
||||
scaleYAnim.setDuration(ANIMATE_TIME);
|
||||
ObjectAnimator xAnim = ObjectAnimator.ofFloat(exitView, "x", endloaction[0]);
|
||||
xAnim.setDuration(ANIMATE_TIME);
|
||||
ObjectAnimator yAnim = ObjectAnimator.ofFloat(exitView, "y", endloaction[1]);
|
||||
yAnim.setDuration(ANIMATE_TIME);
|
||||
|
||||
yAnim.addListener(new SimpleAnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
dispatchDetachFromeStage(exit);
|
||||
ViewUtils.setVisibility(enterView, View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
dispatchDetachFromeStage(exit);
|
||||
ViewUtils.setVisibility(enterView, View.VISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
scaleXAnim.start();
|
||||
scaleYAnim.start();
|
||||
xAnim.start();
|
||||
yAnim.start();
|
||||
|
||||
// TODO show other part progressively
|
||||
}
|
||||
}
|
||||
|
||||
public static class ViewPair {
|
||||
@@ -132,4 +227,23 @@ public class TransitionCurtain extends Curtain {
|
||||
|
||||
public abstract View getToView(@Nullable View sceneView);
|
||||
}
|
||||
|
||||
public class SimpleAnimatorListener implements Animator.AnimatorListener {
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animator animation) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,12 @@ package com.hippo.util;
|
||||
|
||||
public class AssertUtils {
|
||||
|
||||
public static void assertNull(String message, Object object) {
|
||||
if (object != null) {
|
||||
throw new AssertError(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertNotNull(String message, Object object) {
|
||||
if (object == null) {
|
||||
throw new AssertError(message);
|
||||
@@ -29,6 +35,13 @@ public class AssertUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertNullEx(String message, Object object)
|
||||
throws AssertException {
|
||||
if (object != null) {
|
||||
throw new AssertException(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertNotNullEx(String message, Object object)
|
||||
throws AssertException {
|
||||
if (object == null) {
|
||||
|
||||
Reference in new issue
Block a user