summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2010-05-19 19:14:57 -0700
committerDianne Hackborn <hackbod@google.com>2010-05-19 19:25:38 -0700
commit5ae74d6e89a30e79ea85c487b32223ef55314985 (patch)
tree5c56a1ec314090d3117fbb84e43c567cd320ceef /core/java
parent6cf8b9a3eaf2c625395b5fe524976334f63667bb (diff)
downloadframeworks_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.java3
-rw-r--r--core/java/android/app/BackStackEntry.java379
-rw-r--r--core/java/android/app/Fragment.java89
-rw-r--r--core/java/android/app/FragmentManager.java302
-rw-r--r--core/java/android/app/FragmentTransaction.java85
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);