Update Scene

This commit is contained in:
seven332 committed 2015-03-24 14:16:42 +08:00
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);
}
}
+72 -12
View File
@@ -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) {