diff --git a/app/build.gradle b/app/build.gradle index 68d165b66..e31497466 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,10 +2,10 @@ apply plugin: 'com.android.application' android { compileSdkVersion 22 - buildToolsVersion "22" + buildToolsVersion "22.0.1" defaultConfig { - applicationId "com.hippo.ehviewer" + applicationId "com.hippo.ehviewer.test" minSdkVersion 14 targetSdkVersion 22 versionCode 1 @@ -13,7 +13,7 @@ android { } buildTypes { debug { - minifyEnabled false + minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } release { diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 23c99db2a..df08d904d 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -33,3 +33,7 @@ void set*(***); *** get*(); } +-keepclassmembers public class * extends com.hippo.scene.Scene { + void setBackgroundColor(int); + int getBackgroundColor(); +} diff --git a/app/src/main/java/android/content/res/VectorResources.java b/app/src/main/java/android/content/res/VectorResources.java index c9275fc34..f711181b6 100644 --- a/app/src/main/java/android/content/res/VectorResources.java +++ b/app/src/main/java/android/content/res/VectorResources.java @@ -33,6 +33,7 @@ import java.io.IOException; import java.io.InputStream; import java.lang.ref.WeakReference; +// TODO Only load register drawable from itself /** * It is a wrap */ @@ -215,5 +216,4 @@ public class VectorResources extends Resources { } return drawable; } - } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/StartActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/StartActivity.java index 74d2a0e85..b41e34aa6 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/StartActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/StartActivity.java @@ -57,7 +57,7 @@ public class StartActivity extends AbsActionBarActivity { Intent intent = new Intent(StartActivity.this, ContentActivity.class); startActivity(intent); } - }, 3000); + }, 0); } } } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java index a0c9455c4..d3cd86166 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java @@ -15,15 +15,16 @@ package com.hippo.ehviewer.ui.scene; -import android.annotation.SuppressLint; import android.content.res.Resources; import android.os.Bundle; import android.support.annotation.Nullable; +import android.view.View; import com.hippo.ehviewer.R; import com.hippo.ehviewer.ui.ContentActivity; import com.hippo.ehviewer.widget.ContentLayout; import com.hippo.scene.Scene; +import com.hippo.scene.TransitionCurtain; public class GalleryListScene extends Scene { @@ -36,7 +37,6 @@ public class GalleryListScene extends Scene { private ContentLayout mContentLayout; - @SuppressLint("InflateParams") @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -48,6 +48,23 @@ public class GalleryListScene extends Scene { mContentLayout = (ContentLayout) findViewById(R.id.content_layout); mContentLayout.showText("无法连接网络"); + + View view = getSceneView(); + assert view != null; + view.postDelayed(new Runnable() { + @Override + public void run() { + + TransitionCurtain tc = new TransitionCurtain( + new TransitionCurtain.ViewPair[]{ + new TransitionCurtain.ViewPair(R.id.haha, R.id.haha), + new TransitionCurtain.ViewPair(R.id.bbbbbb, R.id.bbbbbb) + } + ); + + startScene(TestScene.class, null, tc); + } + }, 1000); } protected void onGetFitPaddingBottom(int b) { diff --git a/app/src/main/java/com/hippo/scene/Scene.java b/app/src/main/java/com/hippo/scene/Scene.java index 781fed563..4d0d6410b 100644 --- a/app/src/main/java/com/hippo/scene/Scene.java +++ b/app/src/main/java/com/hippo/scene/Scene.java @@ -26,6 +26,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewTreeObserver; +import android.widget.AbsoluteLayout; import android.widget.FrameLayout; import com.hippo.util.AssertUtils; @@ -48,7 +49,7 @@ public abstract class Scene { private @Nullable Curtain mCurtain; - private @Nullable FrameLayout mSceneView; + private @Nullable AbsoluteLayout mSceneView; private int mBackgroundColor = 0xffeeeeee; // TODO Need a better to set background color @@ -82,7 +83,7 @@ public abstract class Scene { * * @return Null or nonull */ - public @Nullable View getSceneView() { + public @Nullable ViewGroup getSceneView() { return mSceneView; } @@ -115,7 +116,7 @@ public abstract class Scene { onCreate(savedInstanceState); if (mSceneView == null) { - mSceneView = new FrameLayout(getStageActivity()); + mSceneView = new AbsoluteLayout(getStageActivity()); initBackground(mSceneView); } @@ -181,7 +182,7 @@ public abstract class Scene { protected void setContentView(int resId) { StageActivity sa = getStageActivity(); - mSceneView = new FrameLayout(sa); + mSceneView = new AbsoluteLayout(sa); initBackground(mSceneView); mSceneView.setBackgroundColor(mBackgroundColor); sa.getLayoutInflater().inflate(resId, mSceneView); @@ -189,7 +190,7 @@ public abstract class Scene { protected void setContentView(View view) { StageActivity sa = getStageActivity(); - mSceneView = new FrameLayout(sa); + mSceneView = new AbsoluteLayout(sa); initBackground(mSceneView); mSceneView.addView(view, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); } diff --git a/app/src/main/java/com/hippo/scene/SceneManager.java b/app/src/main/java/com/hippo/scene/SceneManager.java index e18af68ab..93f88a4a8 100644 --- a/app/src/main/java/com/hippo/scene/SceneManager.java +++ b/app/src/main/java/com/hippo/scene/SceneManager.java @@ -144,12 +144,6 @@ class SceneManager { scene.setState(Scene.SCENE_STATE_DESTROY); scene.detachFromeStage(); } - - /* - // Switch stage bar - View stageBarContent = scene.onCreateStageBar(); - getStageActivity().getStageBar().updateContent(stageBarContent); - */ } } else { Log.e(TAG, "The scene is not in stage"); diff --git a/app/src/main/java/com/hippo/scene/StageBar.java b/app/src/main/java/com/hippo/scene/StageBar.java deleted file mode 100644 index 77788872f..000000000 --- a/app/src/main/java/com/hippo/scene/StageBar.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2015 Hippo Seven - * - * 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 - * 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.scene; - -import android.content.Context; -import android.support.v7.widget.CardView; -import android.util.AttributeSet; -import android.view.View; - -import com.hippo.util.UiUtils; - -/** - * It is shown at the top of stage, just like actionbar - */ -public class StageBar extends CardView { - - private Context mContext; - - public StageBar(Context context) { - super(context); - } - - public StageBar(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public StageBar(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - private void init(Context context) { - mContext = context; - setRadius(UiUtils.dp2pix(context, 2)); - } - - public void updateContent(View view) { - // TODO - } - - public void endAnimation() { - // TODO - } - - public boolean hasContent() { - // TODO - return false; - } -} diff --git a/app/src/main/java/com/hippo/scene/TransitionCurtain.java b/app/src/main/java/com/hippo/scene/TransitionCurtain.java index f4bd04ac7..92b280bd2 100644 --- a/app/src/main/java/com/hippo/scene/TransitionCurtain.java +++ b/app/src/main/java/com/hippo/scene/TransitionCurtain.java @@ -16,151 +16,232 @@ package com.hippo.scene; import android.animation.Animator; +import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; +import android.graphics.Bitmap; import android.graphics.Color; +import android.graphics.drawable.BitmapDrawable; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.view.View; -import android.view.ViewTreeObserver; +import android.view.ViewGroup; +import android.widget.AbsoluteLayout; import com.hippo.animation.ArgbEvaluator; import com.hippo.animation.SimpleAnimatorListener; +import com.hippo.util.AssertUtils; import com.hippo.util.Log; import com.hippo.util.ViewUtils; +import com.hippo.widget.GlobalLayoutSet; -import java.util.LinkedList; -import java.util.List; +import java.util.HashSet; +import java.util.Set; public class TransitionCurtain extends Curtain { private static final String TAG = TransitionCurtain.class.getSimpleName(); - private static long ANIMATE_TIME = 800L; + private static long ANIMATE_TIME = 500L; private ViewPair[] mViewPairArray; - private List mAnimList = new LinkedList<>(); - - private boolean mClearList = true; + private AnimatorSet mAnimatorSet; public TransitionCurtain(ViewPair[] viewPairArray) { mViewPairArray = viewPairArray; } + // TODO what if back key press before move animator start // Make background from transport to default. // Invisible other @Override public void open(final @NonNull Scene enter, final @NonNull Scene exit) { + final Set animatorCollection = new HashSet<>(); + // Handle background - final int bgColor = enter.getBackgroundColor(); + int bgColor = enter.getBackgroundColor(); enter.setBackgroundColor(Color.TRANSPARENT); ObjectAnimator colorAnim = ObjectAnimator.ofInt(enter, "backgroundColor", bgColor); colorAnim.setEvaluator(ArgbEvaluator.getInstance()); colorAnim.setDuration(ANIMATE_TIME); + animatorCollection.add(colorAnim); - colorAnim.addListener(new SimpleAnimatorListener() { - @Override - public void onAnimationEnd(Animator animation) { - dispatchOpenFinished(enter, exit); - hideSceneOnOpen(exit); - - if (mClearList) { - mAnimList.clear(); - } - } - }); - - colorAnim.start(); - - mAnimList.add(colorAnim); + GlobalLayoutSet globalLayoutSet = new GlobalLayoutSet(); + Set transitionItemSet = new HashSet<>(); // Handle transit part for (ViewPair pair : mViewPairArray) { final View enterView = pair.getToView(enter); final View exitView = pair.getFromView(exit); if (enterView == null) { - Log.w(TAG, "Can't get enterView when close"); + Log.e(TAG, "Can't get enterView when close."); continue; } if (exitView == null) { - Log.w(TAG, "Can't get exitView when close"); + Log.e(TAG, "Can't get exitView when close."); continue; } // First make enter view invisible ViewUtils.setVisibility(enterView, View.INVISIBLE); - enterView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - ViewUtils.removeOnGlobalLayoutListener(enterView.getViewTreeObserver(), this); + // Add item + TransitionItem item = new TransitionItem(); + item.enterView = enterView; + item.exitView = exitView; + transitionItemSet.add(item); - 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(); + globalLayoutSet.addListenerToObserver(enterView.getViewTreeObserver()); + // TODO show other part progressively + } - ViewUtils.setVisibility(exitView, View.INVISIBLE); - ViewUtils.setVisibility(enterView, View.VISIBLE); - enterView.setPivotX(0); - enterView.setPivotY(0); + globalLayoutSet.setOnAllLayoutListener(new OpenFirstAllLayoutListener( + enter, exit, transitionItemSet, animatorCollection)); + } - // Start animation - PropertyValuesHolder scaleXPvh = PropertyValuesHolder.ofFloat("scaleX", (float) startWidth / endWidth, 1f); - PropertyValuesHolder scaleYPvh = PropertyValuesHolder.ofFloat("scaleY", (float) startHeight / endHeight, 1f); - PropertyValuesHolder xPvh = PropertyValuesHolder.ofFloat("x", startloaction[0], endloaction[0]); - PropertyValuesHolder yPvh = PropertyValuesHolder.ofFloat("y", startloaction[1], endloaction[1]); + private class OpenFirstAllLayoutListener implements GlobalLayoutSet.OnAllLayoutListener{ - ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(enterView, scaleXPvh, scaleYPvh, xPvh, yPvh); - anim.setDuration(ANIMATE_TIME); + Scene mEnterScene; + Scene mExitScene; + Set mTransitionItemSet; + Set mAnimatorCollection; - anim.addListener(new SimpleAnimatorListener() { - @Override - public void onAnimationEnd(Animator animation) { - ViewUtils.setVisibility(exitView, View.VISIBLE); - } - }); + public OpenFirstAllLayoutListener(Scene enterScene, Scene exitScene, + Set transitionItemSet, Set animatorCollection) { + mEnterScene = enterScene; + mExitScene = exitScene; + mTransitionItemSet = transitionItemSet; + mAnimatorCollection = animatorCollection; + } - anim.start(); + @Override + public void onAllLayout() { + Set transitionItemSet = mTransitionItemSet; - mAnimList.add(anim); + ViewGroup enterSceneView = mEnterScene.getSceneView(); + AssertUtils.assertNotNull("Enter scene view must not be null.", enterSceneView); - // TODO show other part progressively - } - }); + GlobalLayoutSet globalLayoutSet = new GlobalLayoutSet(); + + for (TransitionItem item : transitionItemSet) { + final View enterView = item.enterView; + final View exitView = item.exitView; + + int[] startloaction = new int[2]; + ViewUtils.getLocationInAncestor(exitView, startloaction, mExitScene.getSceneView()); + int[] endloaction = new int[2]; + ViewUtils.getLocationInAncestor(enterView, endloaction, mEnterScene.getSceneView()); + int startWidth = exitView.getWidth(); + int startHeight = exitView.getHeight(); + item.endWidth = enterView.getWidth(); + item.endHeight = enterView.getHeight(); + item.startWidth = startWidth; + item.startHeight = startHeight; + item.endloaction = endloaction; + + Bitmap bmp = ViewUtils.getBitmapFromView(enterView); + View bmpView = new View(enterView.getContext()); + item.bmp = bmp; + item.bmpView = bmpView; + + bmpView.setBackgroundDrawable(new BitmapDrawable(bmp)); + AbsoluteLayout.LayoutParams lp = new AbsoluteLayout.LayoutParams( + startWidth, startHeight, startloaction[0], startloaction[1]); + enterSceneView.addView(bmpView, lp); + + ViewUtils.setVisibility(bmpView, View.INVISIBLE); + + globalLayoutSet.addListenerToObserver(bmpView.getViewTreeObserver()); + } + + globalLayoutSet.setOnAllLayoutListener(new OpenSecondAllLayoutListener( + mEnterScene, mExitScene, transitionItemSet, mAnimatorCollection)); } } + private class OpenSecondAllLayoutListener implements GlobalLayoutSet.OnAllLayoutListener{ + + Scene mEnterScene; + Scene mExitScene; + Set mTransitionItemSet; + Set mAnimatorCollection; + + public OpenSecondAllLayoutListener(Scene enterScene, Scene exitScene, + Set transitionItemSet, Set animatorCollection) { + mEnterScene = enterScene; + mExitScene = exitScene; + mTransitionItemSet = transitionItemSet; + mAnimatorCollection = animatorCollection; + } + + @Override + public void onAllLayout() { + Set transitionItemSet = mTransitionItemSet; + Set animatorCollection = mAnimatorCollection; + + for (TransitionItem item : transitionItemSet) { + View exitView = item.exitView; + View bmpView = item.bmpView; + + ViewUtils.setVisibility(exitView, View.INVISIBLE); + ViewUtils.setVisibility(bmpView, View.VISIBLE); + + bmpView.setPivotX(0); + bmpView.setPivotY(0); + + PropertyValuesHolder scaleXPvh = PropertyValuesHolder.ofFloat("scaleX", (float) item.endWidth / item.startWidth); + PropertyValuesHolder scaleYPvh = PropertyValuesHolder.ofFloat("scaleY", (float) item.endHeight/ item.startHeight); + PropertyValuesHolder xPvh = PropertyValuesHolder.ofFloat("x", item.endloaction[0]); + PropertyValuesHolder yPvh = PropertyValuesHolder.ofFloat("y", item.endloaction[1]); + ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(bmpView, scaleXPvh, scaleYPvh, xPvh, yPvh); + anim.setDuration(ANIMATE_TIME); + + animatorCollection.add(anim); + } + + mAnimatorSet = new AnimatorSet(); + mAnimatorSet.playTogether(animatorCollection); + mAnimatorSet.addListener(new SimpleAnimatorListener() { + @Override + public void onAnimationEnd(Animator animation) { + dispatchOpenFinished(mEnterScene, mExitScene); + hideSceneOnOpen(mExitScene); + for (TransitionItem item : mTransitionItemSet) { + ViewUtils.setVisibility(item.enterView, View.VISIBLE); + ViewUtils.setVisibility(item.exitView, View.VISIBLE); + + ViewGroup enterSceneView = mEnterScene.getSceneView(); + AssertUtils.assertNotNull("Enter scene view must not be null.", enterSceneView); + enterSceneView.removeView(item.bmpView); + + item.bmp.recycle(); + } + mAnimatorSet = null; + } + }); + mAnimatorSet.start(); + } + } + + @Override public void close(final @NonNull Scene enter, final @NonNull Scene exit) { showSceneOnClose(enter); + final Set animatorCollection = new HashSet<>(); + // Handle background ObjectAnimator colorAnim = ObjectAnimator.ofInt(exit, "backgroundColor", Color.TRANSPARENT); colorAnim.setEvaluator(ArgbEvaluator.getInstance()); colorAnim.setDuration(ANIMATE_TIME); + animatorCollection.add(colorAnim); - colorAnim.addListener(new SimpleAnimatorListener() { - @Override - public void onAnimationEnd(Animator animation) { - dispatchCloseFinished(enter, exit); - if (mClearList) { - mAnimList.clear(); - } - } - }); - - colorAnim.start(); - - mAnimList.add(colorAnim); + GlobalLayoutSet globalLayoutSet = new GlobalLayoutSet(); + Set transitionItemSet = new HashSet<>(); // Handle transit part for (ViewPair pair : mViewPairArray) { @@ -175,54 +256,168 @@ public class TransitionCurtain extends Curtain { continue; } - 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); + // First make enter view invisible ViewUtils.setVisibility(enterView, View.INVISIBLE); - exitView.setPivotX(0); - exitView.setPivotY(0); - // Start animation - PropertyValuesHolder scaleXPvh = PropertyValuesHolder.ofFloat("scaleX", (float) endWidth / startWidth); - PropertyValuesHolder scaleYPvh = PropertyValuesHolder.ofFloat("scaleY", (float) endHeight / startHeight); - PropertyValuesHolder xPvh = PropertyValuesHolder.ofFloat("x", endloaction[0]); - PropertyValuesHolder yPvh = PropertyValuesHolder.ofFloat("y", endloaction[1]); + // Add item + TransitionItem item = new TransitionItem(); + item.enterView = enterView; + item.exitView = exitView; + transitionItemSet.add(item); - ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(exitView, scaleXPvh, scaleYPvh, xPvh, yPvh); - anim.setDuration(ANIMATE_TIME); + globalLayoutSet.addListenerToObserver(enterView.getViewTreeObserver()); + // TODO show other part progressively + } - anim.addListener(new SimpleAnimatorListener() { + globalLayoutSet.setOnAllLayoutListener(new CloseFirstAllLayoutListener( + enter, exit, transitionItemSet, animatorCollection)); + } + + private class CloseFirstAllLayoutListener implements GlobalLayoutSet.OnAllLayoutListener{ + + Scene mEnterScene; + Scene mExitScene; + Set mTransitionItemSet; + Set mAnimatorCollection; + + public CloseFirstAllLayoutListener(Scene enterScene, Scene exitScene, + Set transitionItemSet, Set animatorCollection) { + mEnterScene = enterScene; + mExitScene = exitScene; + mTransitionItemSet = transitionItemSet; + mAnimatorCollection = animatorCollection; + } + + @Override + public void onAllLayout() { + Set transitionItemSet = mTransitionItemSet; + + ViewGroup exitSceneView = mExitScene.getSceneView(); + AssertUtils.assertNotNull("Exit scene view must not be null.", exitSceneView); + + GlobalLayoutSet globalLayoutSet = new GlobalLayoutSet(); + + for (TransitionItem item : transitionItemSet) { + final View enterView = item.enterView; + final View exitView = item.exitView; + + int[] startloaction = new int[2]; + ViewUtils.getLocationInAncestor(exitView, startloaction, mExitScene.getSceneView()); + int[] endloaction = new int[2]; + ViewUtils.getLocationInAncestor(enterView, endloaction, mEnterScene.getSceneView()); + int startWidth = exitView.getWidth(); + int startHeight = exitView.getHeight(); + item.endWidth = enterView.getWidth(); + item.endHeight = enterView.getHeight(); + item.startWidth = startWidth; + item.startHeight = startHeight; + item.endloaction = endloaction; + + Bitmap bmp = ViewUtils.getBitmapFromView(exitView); + View bmpView = new View(exitView.getContext()); + item.bmp = bmp; + item.bmpView = bmpView; + + bmpView.setBackgroundDrawable(new BitmapDrawable(bmp)); + AbsoluteLayout.LayoutParams lp = new AbsoluteLayout.LayoutParams( + startWidth, startHeight, startloaction[0], startloaction[1]); + exitSceneView.addView(bmpView, lp); + + ViewUtils.setVisibility(bmpView, View.INVISIBLE); + + globalLayoutSet.addListenerToObserver(bmpView.getViewTreeObserver()); + } + + globalLayoutSet.setOnAllLayoutListener(new CloseSecondAllLayoutListener( + mEnterScene, mExitScene, transitionItemSet, mAnimatorCollection)); + } + } + + private class CloseSecondAllLayoutListener implements GlobalLayoutSet.OnAllLayoutListener{ + + Scene mEnterScene; + Scene mExitScene; + Set mTransitionItemSet; + Set mAnimatorCollection; + + public CloseSecondAllLayoutListener(Scene enterScene, Scene exitScene, + Set transitionItemSet, Set animatorCollection) { + mEnterScene = enterScene; + mExitScene = exitScene; + mTransitionItemSet = transitionItemSet; + mAnimatorCollection = animatorCollection; + } + + @Override + public void onAllLayout() { + Set transitionItemSet = mTransitionItemSet; + Set animatorCollection = mAnimatorCollection; + + for (TransitionItem item : transitionItemSet) { + View exitView = item.exitView; + View bmpView = item.bmpView; + + ViewUtils.setVisibility(exitView, View.INVISIBLE); + ViewUtils.setVisibility(bmpView, View.VISIBLE); + + bmpView.setPivotX(0); + bmpView.setPivotY(0); + + PropertyValuesHolder scaleXPvh = PropertyValuesHolder.ofFloat("scaleX", (float) item.endWidth / item.startWidth); + PropertyValuesHolder scaleYPvh = PropertyValuesHolder.ofFloat("scaleY", (float) item.endHeight/ item.startHeight); + PropertyValuesHolder xPvh = PropertyValuesHolder.ofFloat("x", item.endloaction[0]); + PropertyValuesHolder yPvh = PropertyValuesHolder.ofFloat("y", item.endloaction[1]); + ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(bmpView, scaleXPvh, scaleYPvh, xPvh, yPvh); + anim.setDuration(ANIMATE_TIME); + + animatorCollection.add(anim); + } + + mAnimatorSet = new AnimatorSet(); + mAnimatorSet.playTogether(animatorCollection); + mAnimatorSet.addListener(new SimpleAnimatorListener() { @Override public void onAnimationEnd(Animator animation) { - ViewUtils.setVisibility(enterView, View.VISIBLE); + dispatchCloseFinished(mEnterScene, mExitScene); + for (TransitionItem item : mTransitionItemSet) { + ViewUtils.setVisibility(item.enterView, View.VISIBLE); + ViewUtils.setVisibility(item.exitView, View.VISIBLE); + + ViewGroup exitSceneView = mExitScene.getSceneView(); + AssertUtils.assertNotNull("Exit scene view must not be null.", exitSceneView); + exitSceneView.removeView(item.bmpView); + + item.bmp.recycle(); + } + mAnimatorSet = null; } }); - - anim.start(); - - mAnimList.add(anim); - // TODO show other part progressively + mAnimatorSet.start(); } } @Override public void endAnimation() { - mClearList = false; - for (ObjectAnimator oa : mAnimList) { - oa.end(); + if (mAnimatorSet != null) { + mAnimatorSet.end(); } - mClearList = true; - mAnimList.clear(); } @Override public boolean isInAnimation() { - return !mAnimList.isEmpty(); + return mAnimatorSet != null; + } + + private class TransitionItem { + View enterView; + View exitView; + Bitmap bmp; + View bmpView; + int[] endloaction; + int startWidth; + int startHeight; + int endWidth; + int endHeight; } public static class ViewPair { diff --git a/app/src/main/java/com/hippo/widget/Appbar.java b/app/src/main/java/com/hippo/widget/Appbar.java deleted file mode 100644 index 9dff8bb29..000000000 --- a/app/src/main/java/com/hippo/widget/Appbar.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2015 Hippo Seven - * - * 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 - * 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.widget; - -import android.annotation.TargetApi; -import android.content.Context; -import android.os.Build; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.TextView; - -import com.hippo.ehviewer.R; -import com.hippo.util.ViewUtils; - -public class Appbar extends FrameLayout { - - private Context mContext; - - private ImageView mNavigationIcon; - private TextView mTitle; - - private String mTitleString; - - public Appbar(Context context) { - super(context); - init(context); - } - - public Appbar(Context context, AttributeSet attrs) { - super(context, attrs); - init(context); - } - - public Appbar(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context); - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public Appbar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - init(context); - } - - private void init(Context context) { - mContext = context; - - LayoutInflater.from(context).inflate(R.layout.widget_app_bar, this); - - mNavigationIcon = (ImageView) findViewById(R.id.ab_navigation_icon); - mTitle = (TextView) findViewById(R.id.ab_title); - - ViewUtils.setVisibility(mNavigationIcon, View.GONE); - } - - public void setTitle(int resId) { - setTitle(mContext.getString(resId)); - } - - public void setTitle(String title) { - mTitleString = title; - mTitle.setText(title); - } -} diff --git a/app/src/main/java/com/hippo/widget/GlobalLayoutSet.java b/app/src/main/java/com/hippo/widget/GlobalLayoutSet.java new file mode 100644 index 000000000..74a2f0174 --- /dev/null +++ b/app/src/main/java/com/hippo/widget/GlobalLayoutSet.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2015 Hippo Seven + * + * 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 + * 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.widget; + +import android.view.ViewTreeObserver; + +import com.hippo.util.ViewUtils; + +public class GlobalLayoutSet { + + private OnAllLayoutListener mOnAllLayoutListener; + + private int mSize; + + public void setOnAllLayoutListener(OnAllLayoutListener listener) { + mOnAllLayoutListener = listener; + } + + public void addListenerToObserver(ViewTreeObserver observer) { + LayoutListener ll = new LayoutListener(observer); + observer.addOnGlobalLayoutListener(ll); + mSize++; + } + + private class LayoutListener implements ViewTreeObserver.OnGlobalLayoutListener { + private ViewTreeObserver mObserver; + + private LayoutListener(ViewTreeObserver observer) { + mObserver = observer; + } + + @Override + public void onGlobalLayout() { + ViewUtils.removeOnGlobalLayoutListener(mObserver, this); + + if (--mSize == 0) { + mOnAllLayoutListener.onAllLayout(); + } + } + } + + public interface OnAllLayoutListener { + void onAllLayout(); + } +} diff --git a/app/src/main/res/layout/scene_test.xml b/app/src/main/res/layout/scene_test.xml index 44836da62..22e417f02 100644 --- a/app/src/main/res/layout/scene_test.xml +++ b/app/src/main/res/layout/scene_test.xml @@ -13,26 +13,40 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - - + + - + - + + + + + + diff --git a/app/src/main/res/layout/widget_content_layout.xml b/app/src/main/res/layout/widget_content_layout.xml index 5dfdf2065..edec00b9f 100644 --- a/app/src/main/res/layout/widget_content_layout.xml +++ b/app/src/main/res/layout/widget_content_layout.xml @@ -32,19 +32,20 @@ android:orientation="vertical"> + android:paddingBottom="@dimen/keyline_margin"/> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 034b22129..fad22be47 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -15,7 +15,7 @@ --> - EhViewer + EhViewer Test Do not be a\nsad pandroid