diff options
| author | Dianne Hackborn <hackbod@google.com> | 2010-05-19 19:14:57 -0700 |
|---|---|---|
| committer | Dianne Hackborn <hackbod@google.com> | 2010-05-19 19:25:38 -0700 |
| commit | 5ae74d6e89a30e79ea85c487b32223ef55314985 (patch) | |
| tree | 5c56a1ec314090d3117fbb84e43c567cd320ceef /core/java | |
| parent | 6cf8b9a3eaf2c625395b5fe524976334f63667bb (diff) | |
| download | frameworks_base-5ae74d6e89a30e79ea85c487b32223ef55314985.zip frameworks_base-5ae74d6e89a30e79ea85c487b32223ef55314985.tar.gz frameworks_base-5ae74d6e89a30e79ea85c487b32223ef55314985.tar.bz2 | |
More fragment work.
Clean up FragmentTransaction API, add more animation control, add new
Fragment APIs for hiding and showing.
Change-Id: Iffe31351024a7a63d164270b8a955a499076600e
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/app/Activity.java | 3 | ||||
| -rw-r--r-- | core/java/android/app/BackStackEntry.java | 379 | ||||
| -rw-r--r-- | core/java/android/app/Fragment.java | 89 | ||||
| -rw-r--r-- | core/java/android/app/FragmentManager.java | 302 | ||||
| -rw-r--r-- | core/java/android/app/FragmentTransaction.java | 85 |
5 files changed, 612 insertions, 246 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 174c15b..090f664 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -3877,6 +3877,9 @@ public class Activity extends ContextThemeWrapper // instantiated this fragment from the state and should use // that instance instead of making a new one. Fragment fragment = mFragments.findFragmentById(id); + if (FragmentManager.DEBUG) Log.v(TAG, "onCreateView: id=0x" + + Integer.toHexString(id) + " fname=" + fname + + " existing=" + fragment); if (fragment == null) { fragment = Fragment.instantiate(this, fname); fragment.mFromLayout = true; diff --git a/core/java/android/app/BackStackEntry.java b/core/java/android/app/BackStackEntry.java new file mode 100644 index 0000000..33e456d --- /dev/null +++ b/core/java/android/app/BackStackEntry.java @@ -0,0 +1,379 @@ +/* + * 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 android.app; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; + +final class BackStackState implements Parcelable { + final int[] mOps; + final int mTransition; + final int mTransitionStyle; + final String mName; + + public BackStackState(FragmentManager fm, BackStackEntry bse) { + mOps = new int[bse.mNumOp*4]; + BackStackEntry.Op op = bse.mHead; + int pos = 0; + while (op != null) { + mOps[pos++] = op.cmd; + mOps[pos++] = op.fragment.mIndex; + mOps[pos++] = op.enterAnim; + mOps[pos++] = op.exitAnim; + op = op.next; + } + mTransition = bse.mTransition; + mTransitionStyle = bse.mTransitionStyle; + mName = bse.mName; + } + + public BackStackState(Parcel in) { + mOps = in.createIntArray(); + mTransition = in.readInt(); + mTransitionStyle = in.readInt(); + mName = in.readString(); + } + + public BackStackEntry instantiate(FragmentManager fm) { + BackStackEntry bse = new BackStackEntry(fm); + int pos = 0; + while (pos < mOps.length) { + BackStackEntry.Op op = new BackStackEntry.Op(); + op.cmd = mOps[pos++]; + Fragment f = fm.mActive.get(mOps[pos++]); + f.mBackStackNesting++; + op.fragment = f; + op.enterAnim = mOps[pos++]; + op.exitAnim = mOps[pos++]; + bse.addOp(op); + } + bse.mTransition = mTransition; + bse.mTransitionStyle = mTransitionStyle; + bse.mName = mName; + return bse; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel dest, int flags) { + dest.writeIntArray(mOps); + dest.writeInt(mTransition); + dest.writeInt(mTransitionStyle); + dest.writeString(mName); + } + + public static final Parcelable.Creator<BackStackState> CREATOR + = new Parcelable.Creator<BackStackState>() { + public BackStackState createFromParcel(Parcel in) { + return new BackStackState(in); + } + + public BackStackState[] newArray(int size) { + return new BackStackState[size]; + } + }; +} + +/** + * @hide Entry of an operation on the fragment back stack. + */ +final class BackStackEntry implements FragmentTransaction, Runnable { + final FragmentManager mManager; + + static final int OP_NULL = 0; + static final int OP_ADD = 1; + static final int OP_REMOVE = 2; + static final int OP_HIDE = 3; + static final int OP_SHOW = 4; + + static final class Op { + Op next; + Op prev; + int cmd; + Fragment fragment; + int enterAnim; + int exitAnim; + } + + Op mHead; + Op mTail; + int mNumOp; + int mEnterAnim; + int mExitAnim; + int mTransition; + int mTransitionStyle; + boolean mAddToBackStack; + String mName; + boolean mCommitted; + + public BackStackEntry(FragmentManager manager) { + mManager = manager; + } + + void addOp(Op op) { + if (mHead == null) { + mHead = mTail = op; + } else { + op.prev = mTail; + mTail.next = op; + mTail = op; + } + op.enterAnim = mEnterAnim; + op.exitAnim = mExitAnim; + mNumOp++; + } + + public FragmentTransaction add(Fragment fragment, String tag) { + return add(0, fragment, tag); + } + + public FragmentTransaction add(int containerViewId, Fragment fragment) { + return add(containerViewId, fragment, null); + } + + public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) { + if (fragment.mActivity != null) { + throw new IllegalStateException("Fragment already added: " + fragment); + } + + if (tag != null) { + if (fragment.mTag != null && !tag.equals(fragment.mTag)) { + throw new IllegalStateException("Can't change tag of fragment " + + fragment + ": was " + fragment.mTag + + " now " + tag); + } + fragment.mTag = tag; + } + + if (containerViewId != 0) { + if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) { + throw new IllegalStateException("Can't change container ID of fragment " + + fragment + ": was " + fragment.mFragmentId + + " now " + containerViewId); + } + fragment.mContainerId = fragment.mFragmentId = containerViewId; + } + + Op op = new Op(); + op.cmd = OP_ADD; + op.fragment = fragment; + addOp(op); + + return this; + } + + public FragmentTransaction replace(int containerViewId, Fragment fragment) { + return replace(containerViewId, fragment, null); + } + + public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) { + if (containerViewId == 0) { + throw new IllegalArgumentException("Must use non-zero containerViewId"); + } + if (mManager.mAdded != null) { + for (int i=0; i<mManager.mAdded.size(); i++) { + Fragment old = mManager.mAdded.get(i); + if (old.mContainerId == containerViewId) { + remove(old); + } + } + } + return add(containerViewId, fragment, tag); + } + + public FragmentTransaction remove(Fragment fragment) { + if (fragment.mActivity == null) { + throw new IllegalStateException("Fragment not added: " + fragment); + } + + Op op = new Op(); + op.cmd = OP_REMOVE; + op.fragment = fragment; + addOp(op); + + return this; + } + + public FragmentTransaction hide(Fragment fragment) { + if (fragment.mActivity == null) { + throw new IllegalStateException("Fragment not added: " + fragment); + } + + Op op = new Op(); + op.cmd = OP_HIDE; + op.fragment = fragment; + addOp(op); + + return this; + } + + public FragmentTransaction show(Fragment fragment) { + if (fragment.mActivity == null) { + throw new IllegalStateException("Fragment not added: " + fragment); + } + + Op op = new Op(); + op.cmd = OP_SHOW; + op.fragment = fragment; + addOp(op); + + return this; + } + + public FragmentTransaction setCustomAnimations(int enter, int exit) { + mEnterAnim = enter; + mExitAnim = exit; + return this; + } + + public FragmentTransaction setTransition(int transition) { + mTransition = transition; + return this; + } + + public FragmentTransaction setTransitionStyle(int styleRes) { + mTransitionStyle = styleRes; + return this; + } + + public FragmentTransaction addToBackStack(String name) { + mAddToBackStack = true; + mName = name; + return this; + } + + public void commit() { + if (mCommitted) throw new IllegalStateException("commit already called"); + mCommitted = true; + mManager.mActivity.mHandler.post(this); + } + + public void run() { + Op op = mHead; + while (op != null) { + switch (op.cmd) { + case OP_ADD: { + Fragment f = op.fragment; + if (mAddToBackStack) { + f.mBackStackNesting++; + } + f.mNextAnim = op.enterAnim; + mManager.addFragment(f, false); + } break; + case OP_REMOVE: { + Fragment f = op.fragment; + if (mAddToBackStack) { + f.mBackStackNesting++; + } + f.mNextAnim = op.exitAnim; + mManager.removeFragment(f, mTransition, mTransitionStyle); + } break; + case OP_HIDE: { + Fragment f = op.fragment; + if (mAddToBackStack) { + f.mBackStackNesting++; + } + f.mNextAnim = op.exitAnim; + mManager.hideFragment(f, mTransition, mTransitionStyle); + } break; + case OP_SHOW: { + Fragment f = op.fragment; + if (mAddToBackStack) { + f.mBackStackNesting++; + } + f.mNextAnim = op.enterAnim; + mManager.showFragment(f, mTransition, mTransitionStyle); + } break; + default: { + throw new IllegalArgumentException("Unknown cmd: " + op.cmd); + } + } + + op = op.next; + } + + mManager.moveToState(mManager.mCurState, mTransition, + mTransitionStyle, true); + if (mAddToBackStack) { + mManager.addBackStackState(this); + } + } + + public void popFromBackStack() { + Op op = mTail; + while (op != null) { + switch (op.cmd) { + case OP_ADD: { + Fragment f = op.fragment; + if (mAddToBackStack) { + f.mBackStackNesting--; + } + mManager.removeFragment(f, + FragmentManager.reverseTransit(mTransition), + mTransitionStyle); + } break; + case OP_REMOVE: { + Fragment f = op.fragment; + if (mAddToBackStack) { + f.mBackStackNesting--; + } + mManager.addFragment(f, false); + } break; + case OP_HIDE: { + Fragment f = op.fragment; + if (mAddToBackStack) { + f.mBackStackNesting--; + } + mManager.showFragment(f, + FragmentManager.reverseTransit(mTransition), mTransitionStyle); + } break; + case OP_SHOW: { + Fragment f = op.fragment; + if (mAddToBackStack) { + f.mBackStackNesting--; + } + mManager.hideFragment(f, + FragmentManager.reverseTransit(mTransition), mTransitionStyle); + } break; + default: { + throw new IllegalArgumentException("Unknown cmd: " + op.cmd); + } + } + + op = op.prev; + } + + mManager.moveToState(mManager.mCurState, + FragmentManager.reverseTransit(mTransition), mTransitionStyle, true); + } + + public String getName() { + return mName; + } + + public int getTransition() { + return mTransition; + } + + public int getTransitionStyle() { + return mTransitionStyle; + } +} diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index c64b3e8..d3f56ad 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -29,7 +29,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; -import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; @@ -128,12 +127,8 @@ final class FragmentState implements Parcelable { * that can be placed in an {@link Activity}. */ public class Fragment implements ComponentCallbacks { - private static final Object[] sConstructorArgs = new Object[0]; - - private static final Class[] sConstructorSignature = new Class[] { }; - - private static final HashMap<String, Constructor> sConstructorMap = - new HashMap<String, Constructor>(); + private static final HashMap<String, Class> sClassMap = + new HashMap<String, Class>(); static final int INITIALIZING = 0; // Not yet created. static final int CREATED = 1; // Created. @@ -178,6 +173,10 @@ public class Fragment implements ComponentCallbacks { // fragments that are not part of the layout. String mTag; + // Set to true when the app has requested that this fragment be hidden + // from the user. + boolean mHidden; + // If set this fragment would like its instance retained across // configuration changes. boolean mRetainInstance; @@ -188,6 +187,9 @@ public class Fragment implements ComponentCallbacks { // Used to verify that subclasses call through to super class. boolean mCalled; + // If app has requested a specific animation, this is the one to use. + int mNextAnim; + // The parent container of the fragment after dynamically added to UI. ViewGroup mContainer; @@ -201,16 +203,14 @@ public class Fragment implements ComponentCallbacks { throws NoSuchMethodException, ClassNotFoundException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { - Constructor constructor = sConstructorMap.get(fname); - Class clazz = null; + Class clazz = sClassMap.get(fname); - if (constructor == null) { + if (clazz == null) { // Class not found in the cache, see if it's real, and try to add it clazz = activity.getClassLoader().loadClass(fname); - constructor = clazz.getConstructor(sConstructorSignature); - sConstructorMap.put(fname, constructor); + sClassMap.put(fname, clazz); } - return (Fragment)constructor.newInstance(sConstructorArgs); + return (Fragment)clazz.newInstance(); } void restoreViewState() { @@ -244,6 +244,27 @@ public class Fragment implements ComponentCallbacks { return super.hashCode(); } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(128); + sb.append("Fragment{"); + sb.append(Integer.toHexString(System.identityHashCode(this))); + if (mIndex >= 0) { + sb.append(" #"); + sb.append(mIndex); + } + if (mFragmentId != 0) { + sb.append(" id=0x"); + sb.append(Integer.toHexString(mFragmentId)); + } + if (mTag != null) { + sb.append(" "); + sb.append(mTag); + } + sb.append('}'); + return sb.toString(); + } + /** * Return the identifier this fragment is known by. This is either * the android:id value supplied in a layout or the container view ID @@ -268,6 +289,44 @@ public class Fragment implements ComponentCallbacks { } /** + * Return true if the fragment is currently added to its activity. + */ + public boolean isAdded() { + return mActivity != null && mActivity.mFragments.mAdded.contains(this); + } + + /** + * Return true if the fragment is currently visible to the user. This means + * it: (1) has been added, (2) has its view attached to the window, and + * (3) is not hidden. + */ + public boolean isVisible() { + return isAdded() && !isHidden() && mView != null + && mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE; + } + + /** + * Return true if the fragment has been hidden. By default fragments + * are shown. You can find out about changes to this state with + * {@link #onHiddenChanged()}. Note that the hidden state is orthogonal + * to other states -- that is, to be visible to the user, a fragment + * must be both started and not hidden. + */ + public boolean isHidden() { + return mHidden; + } + + /** + * Called when the hidden state (as returned by {@link #isHidden()} of + * the fragment has changed. Fragments start out not hidden; this will + * be called whenever the fragment changes state from that. + * @param hidden True if the fragment is now hidden, false if it is not + * visible. + */ + public void onHiddenChanged(boolean hidden) { + } + + /** * Control whether a fragment instance is retained across Activity * re-creation (such as from a configuration change). This can only * be used with fragments not in the back stack. If set, the fragment @@ -351,7 +410,7 @@ public class Fragment implements ComponentCallbacks { mCalled = true; } - public Animation onCreateAnimation(int transit, boolean enter) { + public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { return null; } @@ -459,7 +518,7 @@ public class Fragment implements ComponentCallbacks { public void onDestroy() { mCalled = true; } - + /** * Called when the fragment is no longer attached to its activity. This * is called after {@link #onDestroy()}. diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 7556718..a10a191 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -21,240 +21,15 @@ import android.os.Bundle; import android.os.Handler; import android.os.Parcel; import android.os.Parcelable; +import android.util.Log; import android.util.SparseArray; +import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import java.util.ArrayList; -final class BackStackEntry implements FragmentTransaction, Runnable { - final FragmentManager mManager; - - ArrayList<Fragment> mAdded; - ArrayList<Fragment> mRemoved; - int mTransition; - int mTransitionStyle; - boolean mAddToBackStack; - String mName; - boolean mCommitted; - - public BackStackEntry(FragmentManager manager) { - mManager = manager; - } - - public FragmentTransaction add(Fragment fragment, String tag) { - fragment.mTag = tag; - return add(fragment, 0); - } - - public FragmentTransaction add(Fragment fragment, int containerViewId) { - if (fragment.mActivity != null) { - throw new IllegalStateException("Fragment already added: " + fragment); - } - if (mRemoved != null) { - mRemoved.remove(fragment); - } - if (mAdded == null) { - mAdded = new ArrayList<Fragment>(); - } - fragment.mContainerId = fragment.mFragmentId = containerViewId; - mAdded.add(fragment); - return this; - } - - public FragmentTransaction replace(Fragment fragment, int containerViewId) { - if (containerViewId == 0) { - throw new IllegalArgumentException("Must use non-zero containerViewId"); - } - if (mManager.mAdded != null) { - for (int i=0; i<mManager.mAdded.size(); i++) { - Fragment old = mManager.mAdded.get(i); - if (old.mContainerId == containerViewId) { - remove(old); - } - } - } - return add(fragment, containerViewId); - } - - public FragmentTransaction remove(Fragment fragment) { - if (fragment.mActivity == null) { - throw new IllegalStateException("Fragment not added: " + fragment); - } - if (mAdded != null) { - mAdded.remove(fragment); - } - if (mRemoved == null) { - mRemoved = new ArrayList<Fragment>(); - } - mRemoved.add(fragment); - return this; - } - - public FragmentTransaction setTransition(int transition) { - mTransition = transition; - return this; - } - - public FragmentTransaction setTransitionStyle(int styleRes) { - mTransitionStyle = styleRes; - return this; - } - - public FragmentTransaction addToBackStack(String name) { - mAddToBackStack = true; - mName = name; - return this; - } - - public void commit() { - if (mCommitted) throw new IllegalStateException("commit already called"); - mCommitted = true; - mManager.mActivity.mHandler.post(this); - } - - public void run() { - if (mRemoved != null) { - for (int i=mRemoved.size()-1; i>=0; i--) { - Fragment f = mRemoved.get(i); - if (mAddToBackStack) { - f.mBackStackNesting++; - } - mManager.removeFragment(f, mTransition, mTransitionStyle); - } - } - if (mAdded != null) { - for (int i=mAdded.size()-1; i>=0; i--) { - Fragment f = mAdded.get(i); - if (mAddToBackStack) { - f.mBackStackNesting++; - } - mManager.addFragment(f, false); - } - } - mManager.moveToState(mManager.mCurState, mTransition, - mTransitionStyle, true); - if (mAddToBackStack) { - mManager.addBackStackState(this); - } - } - - public void popFromBackStack() { - if (mAdded != null) { - for (int i=mAdded.size()-1; i>=0; i--) { - Fragment f = mAdded.get(i); - if (mAddToBackStack) { - f.mBackStackNesting--; - } - mManager.removeFragment(f, - FragmentManager.reverseTransit(mTransition), - mTransitionStyle); - } - } - if (mRemoved != null) { - for (int i=mRemoved.size()-1; i>=0; i--) { - Fragment f = mRemoved.get(i); - if (mAddToBackStack) { - f.mBackStackNesting--; - } - mManager.addFragment(f, false); - } - } - } - - public String getName() { - return mName; - } - - public int getTransition() { - return mTransition; - } - - public int getTransitionStyle() { - return mTransitionStyle; - } -} - -final class BackStackState implements Parcelable { - final int[] mAdded; - final int[] mRemoved; - final int mTransition; - final int mTransitionStyle; - final String mName; - - public BackStackState(FragmentManager fm, BackStackEntry bse) { - mAdded = buildFragmentStateList(fm, bse.mAdded); - mRemoved = buildFragmentStateList(fm, bse.mRemoved); - mTransition = bse.mTransition; - mTransitionStyle = bse.mTransitionStyle; - mName = bse.mName; - } - - public BackStackState(Parcel in) { - mAdded = in.createIntArray(); - mRemoved = in.createIntArray(); - mTransition = in.readInt(); - mTransitionStyle = in.readInt(); - mName = in.readString(); - } - - public BackStackEntry instantiate(FragmentManager fm) { - BackStackEntry bse = new BackStackEntry(fm); - bse.mAdded = buildFragmentList(fm, mAdded); - bse.mRemoved = buildFragmentList(fm, mRemoved); - bse.mTransition = mTransition; - bse.mTransitionStyle = mTransitionStyle; - bse.mName = mName; - return bse; - } - - static int[] buildFragmentStateList(FragmentManager fm, ArrayList<Fragment> frags) { - if (frags == null) return null; - final int N = frags.size(); - int[] ids = new int[N]; - for (int i=0; i<N; i++) { - ids[i] = frags.get(i).mIndex; - } - return ids; - } - - static ArrayList<Fragment> buildFragmentList(FragmentManager fm, int[] states) { - if (states == null) return null; - final int N = states.length; - ArrayList<Fragment> frags = new ArrayList<Fragment>(N); - for (int i=0; i<N; i++) { - Fragment f = fm.mActive.get(states[i]); - f.mBackStackNesting++; - frags.add(f); - } - return frags; - } - - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - dest.writeIntArray(mAdded); - dest.writeIntArray(mRemoved); - dest.writeInt(mTransition); - dest.writeInt(mTransitionStyle); - dest.writeString(mName); - } - - public static final Parcelable.Creator<BackStackState> CREATOR - = new Parcelable.Creator<BackStackState>() { - public BackStackState createFromParcel(Parcel in) { - return new BackStackState(in); - } - - public BackStackState[] newArray(int size) { - return new BackStackState[size]; - } - }; -} - final class FragmentManagerState implements Parcelable { FragmentState[] mActive; int[] mAdded; @@ -296,6 +71,9 @@ final class FragmentManagerState implements Parcelable { * Container for fragments associated with an activity. */ public class FragmentManager { + static final boolean DEBUG = true; + static final String TAG = "FragmentManager"; + ArrayList<Fragment> mActive; ArrayList<Fragment> mAdded; ArrayList<Integer> mAvailIndices; @@ -310,11 +88,19 @@ public class FragmentManager { Animation loadAnimation(Fragment fragment, int transit, boolean enter, int transitionStyle) { - Animation animObj = fragment.onCreateAnimation(transitionStyle, enter); + Animation animObj = fragment.onCreateAnimation(transitionStyle, enter, + fragment.mNextAnim); if (animObj != null) { return animObj; } + if (fragment.mNextAnim != 0) { + Animation anim = AnimationUtils.loadAnimation(mActivity, fragment.mNextAnim); + if (anim != null) { + return anim; + } + } + if (transit == 0) { return null; } @@ -352,6 +138,7 @@ public class FragmentManager { if (f.mState < newState) { switch (f.mState) { case Fragment.INITIALIZING: + if (DEBUG) Log.v(TAG, "moveto CREATED: " + f); f.mActivity = mActivity; f.mCalled = false; f.onAttach(mActivity); @@ -378,10 +165,12 @@ public class FragmentManager { if (f.mView != null) { f.mView.setSaveFromParentEnabled(false); f.restoreViewState(); + if (f.mHidden) f.mView.setVisibility(View.GONE); } } case Fragment.CREATED: if (newState > Fragment.CREATED) { + if (DEBUG) Log.v(TAG, "moveto CONTENT: " + f); if (!f.mFromLayout) { ViewGroup container = null; if (f.mContainerId != 0) { @@ -406,6 +195,7 @@ public class FragmentManager { container.addView(f.mView); f.restoreViewState(); } + if (f.mHidden) f.mView.setVisibility(View.GONE); } } @@ -419,6 +209,7 @@ public class FragmentManager { } case Fragment.CONTENT: if (newState > Fragment.CONTENT) { + if (DEBUG) Log.v(TAG, "moveto STARTED: " + f); f.mCalled = false; f.onStart(); if (!f.mCalled) { @@ -428,6 +219,7 @@ public class FragmentManager { } case Fragment.STARTED: if (newState > Fragment.STARTED) { + if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f); f.mCalled = false; f.onResume(); if (!f.mCalled) { @@ -440,6 +232,7 @@ public class FragmentManager { switch (f.mState) { case Fragment.RESUMED: if (newState < Fragment.RESUMED) { + if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f); f.mCalled = false; f.onPause(); if (!f.mCalled) { @@ -449,6 +242,7 @@ public class FragmentManager { } case Fragment.STARTED: if (newState < Fragment.STARTED) { + if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f); f.mCalled = false; f.onStop(); if (!f.mCalled) { @@ -458,6 +252,7 @@ public class FragmentManager { } case Fragment.CONTENT: if (newState < Fragment.CONTENT) { + if (DEBUG) Log.v(TAG, "movefrom CONTENT: " + f); if (f.mView != null) { // Need to save the current view state if not // done already. @@ -480,6 +275,7 @@ public class FragmentManager { } case Fragment.CREATED: if (newState < Fragment.CREATED) { + if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f); if (!f.mRetaining) { f.mCalled = false; f.onDestroy(); @@ -559,6 +355,7 @@ public class FragmentManager { } public void addFragment(Fragment fragment, boolean moveToStateNow) { + if (DEBUG) Log.v(TAG, "add: " + fragment); if (mAdded == null) { mAdded = new ArrayList<Fragment>(); } @@ -571,6 +368,7 @@ public class FragmentManager { } public void removeFragment(Fragment fragment, int transition, int transitionStyle) { + if (DEBUG) Log.v(TAG, "remove: " + fragment); mAdded.remove(fragment); final boolean inactive = fragment.mBackStackNesting <= 0; if (inactive) { @@ -581,8 +379,48 @@ public class FragmentManager { transition, transitionStyle); } + public void hideFragment(Fragment fragment, int transition, int transitionStyle) { + if (DEBUG) Log.v(TAG, "hide: " + fragment); + if (!fragment.mHidden) { + fragment.mHidden = true; + if (fragment.mView != null) { + Animation anim = loadAnimation(fragment, transition, false, + transitionStyle); + if (anim != null) { + fragment.mView.setAnimation(anim); + } + fragment.mView.setVisibility(View.GONE); + } + fragment.onHiddenChanged(true); + } + } + + public void showFragment(Fragment fragment, int transition, int transitionStyle) { + if (DEBUG) Log.v(TAG, "show: " + fragment); + if (fragment.mHidden) { + fragment.mHidden = false; + if (fragment.mView != null) { + Animation anim = loadAnimation(fragment, transition, true, + transitionStyle); + if (anim != null) { + fragment.mView.setAnimation(anim); + } + fragment.mView.setVisibility(View.VISIBLE); + } + fragment.onHiddenChanged(false); + } + } + public Fragment findFragmentById(int id) { if (mActive != null) { + // First look through added fragments. + for (int i=mAdded.size()-1; i>=0; i--) { + Fragment f = mAdded.get(i); + if (f != null && f.mFragmentId == id) { + return f; + } + } + // Now for any known fragment. for (int i=mActive.size()-1; i>=0; i--) { Fragment f = mActive.get(i); if (f != null && f.mFragmentId == id) { @@ -595,6 +433,14 @@ public class FragmentManager { public Fragment findFragmentByTag(String tag) { if (mActive != null && tag != null) { + // First look through added fragments. + for (int i=mAdded.size()-1; i>=0; i--) { + Fragment f = mAdded.get(i); + if (f != null && tag.equals(f.mTag)) { + return f; + } + } + // Now for any known fragment. for (int i=mActive.size()-1; i>=0; i--) { Fragment f = mActive.get(i); if (f != null && tag.equals(f.mTag)) { diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java index a28530f..840f274 100644 --- a/core/java/android/app/FragmentTransaction.java +++ b/core/java/android/app/FragmentTransaction.java @@ -4,13 +4,90 @@ package android.app; * API for performing a set of Fragment operations. */ public interface FragmentTransaction { + /** + * Calls {@link #add(int, Fragment, String)} with a 0 containerViewId. + */ public FragmentTransaction add(Fragment fragment, String tag); - public FragmentTransaction add(Fragment fragment, int containerViewId); - public FragmentTransaction replace(Fragment fragment, int containerViewId); + + /** + * Calls {@link #add(int, Fragment, String)} with a null tag. + */ + public FragmentTransaction add(int containerViewId, Fragment fragment); + + /** + * Add a fragment to the activity state. This fragment may optionally + * also have its view (if {@link Fragment#onCreateView Fragment.onCreateView} + * returns non-null) into a container view of the activity. + * + * @param containerViewId Optional identifier of the container this fragment is + * to be placed in. If 0, it will not be placed in a container. + * @param fragment The fragment to be added. This fragment must not already + * be added to the activity. + * @param tag Optional tag name for the fragment, to later retrieve the + * fragment with {@link Activity#findFragmentByTag(String) + * Activity.findFragmentByTag(String)}. + * + * @return Returns the same FragmentTransaction instance. + */ + public FragmentTransaction add(int containerViewId, Fragment fragment, String tag); + + /** + * Calls {@link #replace(int, Fragment, String)} with a null tag. + */ + public FragmentTransaction replace(int containerViewId, Fragment fragment); + + /** + * Replace an existing fragment that was added to a container. This is + * essentially the same as calling {@link #remove(Fragment)} for all + * currently added fragments that were added with the same containerViewId + * and then {@link #add(int, Fragment, String)} with the same arguments + * given here. + * + * @param containerViewId Identifier of the container whose fragment(s) are + * to be replaced. + * @param fragment The new fragment to place in the container. + * @param tag Optional tag name for the fragment, to later retrieve the + * fragment with {@link Activity#findFragmentByTag(String) + * Activity.findFragmentByTag(String)}. + * + * @return Returns the same FragmentTransaction instance. + */ + public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag); + + /** + * Remove an existing fragment. If it was added to a container, its view + * is also removed from that container. + * + * @param fragment The fragment to be removed. + * + * @return Returns the same FragmentTransaction instance. + */ public FragmentTransaction remove(Fragment fragment); /** - * Bit mask that is set for all enter transition. + * Hides an existing fragment. This is only relevant for fragments whose + * views have been added to a container, as this will cause the view to + * be hidden. + * + * @param fragment The fragment to be hidden. + * + * @return Returns the same FragmentTransaction instance. + */ + public FragmentTransaction hide(Fragment fragment); + + /** + * Hides a previously hidden fragment. This is only relevant for fragments whose + * views have been added to a container, as this will cause the view to + * be shown. + * + * @param fragment The fragment to be shown. + * + * @return Returns the same FragmentTransaction instance. + */ + public FragmentTransaction show(Fragment fragment); + + /** + * Bit mask that is set for all enter transitions. */ public final int TRANSIT_ENTER_MASK = 0x1000; @@ -64,6 +141,8 @@ public interface FragmentTransaction { * previous activity, and both are on top of he wallpaper. */ public final int TRANSIT_WALLPAPER_INTRA_CLOSE = 15 | TRANSIT_EXIT_MASK; + public FragmentTransaction setCustomAnimations(int enter, int exit); + public FragmentTransaction setTransition(int transit); public FragmentTransaction setTransitionStyle(int styleRes); |
