diff options
| -rw-r--r-- | api/current.xml | 246 | ||||
| -rw-r--r-- | core/java/android/app/Activity.java | 43 | ||||
| -rw-r--r-- | core/java/android/app/BackStackEntry.java | 25 | ||||
| -rw-r--r-- | core/java/android/app/DialogFragment.java | 277 | ||||
| -rw-r--r-- | core/java/android/app/FragmentManager.java | 92 | ||||
| -rw-r--r-- | core/java/android/app/FragmentTransaction.java | 12 | ||||
| -rw-r--r-- | core/java/android/app/ListFragment.java | 24 | ||||
| -rw-r--r-- | core/res/res/values/public.xml | 1 | ||||
| -rw-r--r-- | core/res/res/values/themes.xml | 14 |
9 files changed, 715 insertions, 19 deletions
diff --git a/api/current.xml b/api/current.xml index 27ab9f25b632..96ca9e919086 100644 --- a/api/current.xml +++ b/api/current.xml @@ -16410,6 +16410,17 @@ visibility="public" > </field> +<field name="Theme_Dialog_NoFrame" + type="int" + transient="false" + volatile="false" + value="16973972" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="Theme_InputMethod" type="int" transient="false" @@ -21390,8 +21401,36 @@ deprecated="not deprecated" visibility="public" > +</method> +<method name="popBackStack" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> <parameter name="name" type="java.lang.String"> </parameter> +<parameter name="flags" type="int"> +</parameter> +</method> +<method name="popBackStack" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="id" type="int"> +</parameter> +<parameter name="flags" type="int"> +</parameter> </method> <method name="registerForContextMenu" return="void" @@ -25835,6 +25874,211 @@ </parameter> </method> </class> +<class name="DialogFragment" + extends="android.app.Fragment" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<implements name="android.content.DialogInterface.OnCancelListener"> +</implements> +<implements name="android.content.DialogInterface.OnDismissListener"> +</implements> +<constructor name="DialogFragment" + type="android.app.DialogFragment" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</constructor> +<constructor name="DialogFragment" + type="android.app.DialogFragment" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="style" type="int"> +</parameter> +<parameter name="theme" type="int"> +</parameter> +</constructor> +<method name="dismiss" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getCancelable" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getDialog" + return="android.app.Dialog" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getTheme" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="onCancel" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="dialog" type="android.content.DialogInterface"> +</parameter> +</method> +<method name="onCreateDialog" + return="android.app.Dialog" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="savedInstanceState" type="android.os.Bundle"> +</parameter> +</method> +<method name="onDismiss" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="dialog" type="android.content.DialogInterface"> +</parameter> +</method> +<method name="setCancelable" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="cancelable" type="boolean"> +</parameter> +</method> +<method name="show" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="activity" type="android.app.Activity"> +</parameter> +<parameter name="tag" type="java.lang.String"> +</parameter> +</method> +<method name="show" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="activity" type="android.app.Activity"> +</parameter> +<parameter name="transaction" type="android.app.FragmentTransaction"> +</parameter> +<parameter name="tag" type="java.lang.String"> +</parameter> +</method> +<field name="STYLE_NORMAL" + type="int" + transient="false" + volatile="false" + value="0" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="STYLE_NO_FRAME" + type="int" + transient="false" + volatile="false" + value="2" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="STYLE_NO_INPUT" + type="int" + transient="false" + volatile="false" + value="3" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="STYLE_NO_TITLE" + type="int" + transient="false" + volatile="false" + value="1" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +</class> <class name="ExpandableListActivity" extends="android.app.Activity" abstract="false" @@ -26615,7 +26859,7 @@ </parameter> </method> <method name="commit" - return="void" + return="int" abstract="true" native="false" synchronized="false" diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 32982085846b..48d0d81f5c6d 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2054,14 +2054,47 @@ public class Activity extends ContextThemeWrapper } /** + * Flag for {@link #popBackStack(String, int)} + * and {@link #popBackStack(int, int)}: If set, and the name or ID of + * a back stack entry has been supplied, then that entry will also be + * removed. Otherwise, all entries up to but not including that entry + * will be removed + */ + static final int POP_BACK_STACK_INCLUSIVE = 1<<0; + + /** + * Pop the top state off the back stack. Returns true if there was one + * to pop, else false. + */ + public boolean popBackStack() { + return popBackStack(null, 0); + } + + /** * Pop the last fragment transition from the local activity's fragment * back stack. If there is nothing to pop, false is returned. * @param name If non-null, this is the name of a previous back state - * to look for; if found, all states up to (but not including) that - * state will be popped. If null, only the top state is popped. + * to look for; if found, all states up to that state will be popped. The + * {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether + * the named state itself is popped. If null, only the top state is popped. + * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}. + */ + public boolean popBackStack(String name, int flags) { + return mFragments.popBackStackState(mHandler, name, flags); + } + + /** + * Pop all back stack states up to the one with the given identifier. + * @param id Identifier of the stated to be popped. If no identifier exists, + * false is returned. + * The identifier is the number returned by + * {@link FragmentTransaction#commit() FragmentTransaction.commit()}. The + * {@link #POP_BACK_STACK_INCLUSIVE} flag can be used to control whether + * the named state itself is popped. + * @param flags Either 0 or {@link #POP_BACK_STACK_INCLUSIVE}. */ - public boolean popBackStack(String name) { - return mFragments.popBackStackState(mHandler, name); + public boolean popBackStack(int id, int flags) { + return mFragments.popBackStackState(mHandler, id, flags); } /** @@ -2070,7 +2103,7 @@ public class Activity extends ContextThemeWrapper * but you can override this to do whatever you want. */ public void onBackPressed() { - if (!popBackStack(null)) { + if (!popBackStack()) { finish(); } } diff --git a/core/java/android/app/BackStackEntry.java b/core/java/android/app/BackStackEntry.java index c958e2611f1e..729143834091 100644 --- a/core/java/android/app/BackStackEntry.java +++ b/core/java/android/app/BackStackEntry.java @@ -27,6 +27,7 @@ final class BackStackState implements Parcelable { final int mTransition; final int mTransitionStyle; final String mName; + final int mIndex; public BackStackState(FragmentManager fm, BackStackEntry bse) { int numRemoved = 0; @@ -58,6 +59,7 @@ final class BackStackState implements Parcelable { mTransition = bse.mTransition; mTransitionStyle = bse.mTransitionStyle; mName = bse.mName; + mIndex = bse.mIndex; } public BackStackState(Parcel in) { @@ -65,6 +67,7 @@ final class BackStackState implements Parcelable { mTransition = in.readInt(); mTransitionStyle = in.readInt(); mName = in.readString(); + mIndex = in.readInt(); } public BackStackEntry instantiate(FragmentManager fm) { @@ -90,6 +93,7 @@ final class BackStackState implements Parcelable { bse.mTransition = mTransition; bse.mTransitionStyle = mTransitionStyle; bse.mName = mName; + bse.mIndex = mIndex; return bse; } @@ -102,6 +106,7 @@ final class BackStackState implements Parcelable { dest.writeInt(mTransition); dest.writeInt(mTransitionStyle); dest.writeString(mName); + dest.writeInt(mIndex); } public static final Parcelable.Creator<BackStackState> CREATOR @@ -151,6 +156,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable { boolean mAddToBackStack; String mName; boolean mCommitted; + int mIndex; public BackStackEntry(FragmentManager manager) { mManager = manager; @@ -289,16 +295,28 @@ final class BackStackEntry implements FragmentTransaction, Runnable { return this; } - public void commit() { + public int commit() { if (mCommitted) throw new IllegalStateException("commit already called"); if (FragmentManager.DEBUG) Log.v(TAG, "Commit: " + this); mCommitted = true; + if (mAddToBackStack) { + mIndex = mManager.allocBackStackIndex(this); + } else { + mIndex = -1; + } mManager.enqueueAction(this); + return mIndex; } public void run() { if (FragmentManager.DEBUG) Log.v(TAG, "Run: " + this); + if (mAddToBackStack) { + if (mIndex < 0) { + throw new IllegalStateException("addToBackStack() called after commit()"); + } + } + Op op = mHead; while (op != null) { switch (op.cmd) { @@ -450,6 +468,11 @@ final class BackStackEntry implements FragmentTransaction, Runnable { mManager.mActivity.invalidateOptionsMenu(); mManager.mNeedMenuInvalidate = false; } + + if (mIndex >= 0) { + mManager.freeBackStackIndex(mIndex); + mIndex = -1; + } } public String getName() { diff --git a/core/java/android/app/DialogFragment.java b/core/java/android/app/DialogFragment.java new file mode 100644 index 000000000000..391f67282329 --- /dev/null +++ b/core/java/android/app/DialogFragment.java @@ -0,0 +1,277 @@ +/* + * 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.content.DialogInterface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; + +/** + * A fragment that displays a dialog window, floating on top of its + * activity's window. This fragment contains a Dialog object, which it + * displays as appropriate based on the fragment's state. Control of + * the dialog (deciding when to show, hide, dismiss it) should be done through + * the API here, not with direct calls on the dialog. + * + * <p>Implementations should override this class and implement + * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} to supply the + * content of the dialog. Alternatively, they can override + * {@link #onCreateDialog(Bundle)} to create an entirely custom dialog, such + * as an AlertDialog, with its own content. + */ +public class DialogFragment extends Fragment + implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener { + + /** + * Style for {@link #DialogFragment(int, int)} constructor: a basic, + * normal dialog. + */ + public static final int STYLE_NORMAL = 0; + + /** + * Style for {@link #DialogFragment(int, int)} constructor: don't include + * a title area. + */ + public static final int STYLE_NO_TITLE = 1; + + /** + * Style for {@link #DialogFragment(int, int)} constructor: don't draw + * any frame at all; the view hierarchy returned by {@link #onCreateView} + * is entirely responsible for drawing the dialog. + */ + public static final int STYLE_NO_FRAME = 2; + + /** + * Style for {@link #DialogFragment(int, int)} constructor: like + * {@link #STYLE_NO_FRAME}, but also disables all input to the dialog. + * The user can not touch it, and its window will not receive input focus. + */ + public static final int STYLE_NO_INPUT = 3; + + private static final String SAVED_DIALOG_STATE_TAG = "android:savedDialogState"; + private static final String SAVED_STYLE = "android:style"; + private static final String SAVED_THEME = "android:theme"; + private static final String SAVED_CANCELABLE = "android:cancelable"; + private static final String SAVED_BACK_STACK_ID = "android:backStackId"; + + int mStyle = STYLE_NORMAL; + int mTheme = 0; + boolean mCancelable = true; + int mBackStackId = -1; + + Dialog mDialog; + boolean mDestroyed; + + public DialogFragment() { + } + + /** + * Constructor to customize the basic appearance and behavior of the + * fragment's dialog. This can be used for some common dialog behaviors, + * taking care of selecting flags, theme, and other options for you. The + * same effect can be achieve by manually setting Dialog and Window + * attributes yourself. + * + * @param style Selects a standard style: may be {@link #STYLE_NORMAL}, + * {@link #STYLE_NO_TITLE}, {@link #STYLE_NO_FRAME}, or + * {@link #STYLE_NO_INPUT}. + * @param theme Optional custom theme. If 0, an appropriate theme (based + * on the style) will be selected for you. + */ + public DialogFragment(int style, int theme) { + mStyle = style; + if (mStyle == STYLE_NO_FRAME || mStyle == STYLE_NO_INPUT) { + mTheme = android.R.style.Theme_Dialog_NoFrame; + } + if (theme != 0) { + mTheme = theme; + } + } + + /** + * Display the dialog, adding the fragment to the given activity. This + * is a convenience for explicitly creating a transaction, adding the + * fragment to it with the given tag, and committing it. This does + * <em>not</em> add the transaction to the back stack. When the fragment + * is dismissed, a new transaction will be executed to remove it from + * the activity. + * @param activity The activity this fragment will be added to. + * @param tag The tag for this fragment, as per + * {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}. + */ + public void show(Activity activity, String tag) { + FragmentTransaction ft = activity.openFragmentTransaction(); + ft.add(this, tag); + ft.commit(); + } + + /** + * Display the dialog, adding the fragment to the given activity using + * an existing transaction and then committing the transaction. + * @param activity The activity this fragment will be added to. + * @param transaction An existing transaction in which to add the fragment. + * @param tag The tag for this fragment, as per + * {@link FragmentTransaction#add(Fragment, String) FragmentTransaction.add}. + * @return Returns the identifier of the committed transaction, as per + * {@link FragmentTransaction#commit() FragmentTransaction.commit()}. + */ + public int show(Activity activity, FragmentTransaction transaction, String tag) { + transaction.add(this, tag); + mBackStackId = transaction.commit(); + return mBackStackId; + } + + /** + * Dismiss the fragment and its dialog. If the fragment was added to the + * back stack, all back stack state up to and including this entry will + * be popped. Otherwise, a new transaction will be committed to remove + * the fragment. + */ + public void dismiss() { + if (mDialog != null) { + mDialog.dismiss(); + } + if (mBackStackId >= 0) { + getActivity().popBackStack(mBackStackId, Activity.POP_BACK_STACK_INCLUSIVE); + mBackStackId = -1; + } else { + FragmentTransaction ft = getActivity().openFragmentTransaction(); + ft.remove(this); + ft.commit(); + } + } + + public Dialog getDialog() { + return mDialog; + } + + public int getTheme() { + return mTheme; + } + + public void setCancelable(boolean cancelable) { + mCancelable = cancelable; + if (mDialog != null) mDialog.setCancelable(cancelable); + } + + public boolean getCancelable() { + return mCancelable; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (savedInstanceState != null) { + mStyle = savedInstanceState.getInt(SAVED_STYLE, mStyle); + mTheme = savedInstanceState.getInt(SAVED_THEME, mTheme); + mCancelable = savedInstanceState.getBoolean(SAVED_CANCELABLE, mCancelable); + mBackStackId = savedInstanceState.getInt(SAVED_BACK_STACK_ID, mBackStackId); + } + } + + public Dialog onCreateDialog(Bundle savedInstanceState) { + return new Dialog(getActivity(), getTheme()); + } + + public void onCancel(DialogInterface dialog) { + if (mBackStackId >= 0) { + // If this fragment is part of the back stack, then cancelling + // the dialog means popping off the back stack. + getActivity().popBackStack(mBackStackId, Activity.POP_BACK_STACK_INCLUSIVE); + mBackStackId = -1; + } + } + + public void onDismiss(DialogInterface dialog) { + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + mDialog = onCreateDialog(savedInstanceState); + mDestroyed = false; + switch (mStyle) { + case STYLE_NO_INPUT: + mDialog.getWindow().addFlags( + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | + WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); + // fall through... + case STYLE_NO_FRAME: + case STYLE_NO_TITLE: + mDialog.requestWindowFeature(Window.FEATURE_NO_TITLE); + } + View view = getView(); + if (view != null) { + if (view.getParent() != null) { + throw new IllegalStateException("DialogFragment can not be attached to a container view"); + } + mDialog.setContentView(view); + } + mDialog.setOwnerActivity(getActivity()); + mDialog.setCancelable(mCancelable); + mDialog.setOnCancelListener(this); + mDialog.setOnDismissListener(this); + if (savedInstanceState != null) { + Bundle dialogState = savedInstanceState.getBundle(SAVED_DIALOG_STATE_TAG); + if (dialogState != null) { + mDialog.onRestoreInstanceState(dialogState); + } + } + } + + @Override + public void onStart() { + super.onStart(); + mDialog.show(); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + if (mDialog != null) { + Bundle dialogState = mDialog.onSaveInstanceState(); + if (dialogState != null) { + outState.putBundle(SAVED_DIALOG_STATE_TAG, dialogState); + } + } + outState.putInt(SAVED_STYLE, mStyle); + outState.putInt(SAVED_THEME, mTheme); + outState.putBoolean(SAVED_CANCELABLE, mCancelable); + outState.putInt(SAVED_BACK_STACK_ID, mBackStackId); + } + + @Override + public void onStop() { + super.onStop(); + mDialog.hide(); + } + + /** + * Detach from list view. + */ + @Override + public void onDestroyView() { + super.onDestroyView(); + mDestroyed = true; + mDialog.dismiss(); + mDialog = null; + } +} diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 4f3043c40c46..c0e757d1ab0b 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -86,6 +86,10 @@ public class FragmentManager { ArrayList<Integer> mAvailIndices; ArrayList<BackStackEntry> mBackStack; + // Must be accessed while locked. + ArrayList<BackStackEntry> mBackStackIndices; + ArrayList<Integer> mAvailBackStackIndices; + int mCurState = Fragment.INITIALIZING; Activity mActivity; @@ -514,6 +518,62 @@ public class FragmentManager { } } + public int allocBackStackIndex(BackStackEntry bse) { + synchronized (this) { + if (mAvailBackStackIndices == null || mAvailBackStackIndices.size() <= 0) { + if (mBackStackIndices == null) { + mBackStackIndices = new ArrayList<BackStackEntry>(); + } + int index = mBackStackIndices.size(); + if (DEBUG) Log.v(TAG, "Setting back stack index " + index + " to " + bse); + mBackStackIndices.add(bse); + return index; + + } else { + int index = mAvailBackStackIndices.remove(mAvailBackStackIndices.size()-1); + if (DEBUG) Log.v(TAG, "Adding back stack index " + index + " with " + bse); + mBackStackIndices.set(index, bse); + return index; + } + } + } + + public void setBackStackIndex(int index, BackStackEntry bse) { + synchronized (this) { + if (mBackStackIndices == null) { + mBackStackIndices = new ArrayList<BackStackEntry>(); + } + int N = mBackStackIndices.size(); + if (index < N) { + if (DEBUG) Log.v(TAG, "Setting back stack index " + index + " to " + bse); + mBackStackIndices.set(index, bse); + } else { + while (N < index) { + mBackStackIndices.add(null); + if (mAvailBackStackIndices == null) { + mAvailBackStackIndices = new ArrayList<Integer>(); + } + if (DEBUG) Log.v(TAG, "Adding available back stack index " + N); + mAvailBackStackIndices.add(N); + N++; + } + if (DEBUG) Log.v(TAG, "Adding back stack index " + index + " with " + bse); + mBackStackIndices.add(bse); + } + } + } + + public void freeBackStackIndex(int index) { + synchronized (this) { + mBackStackIndices.set(index, null); + if (mAvailBackStackIndices == null) { + mAvailBackStackIndices = new ArrayList<Integer>(); + } + if (DEBUG) Log.v(TAG, "Freeing back stack index " + index); + mAvailBackStackIndices.add(index); + } + } + /** * Only call from main thread! */ @@ -554,11 +614,22 @@ public class FragmentManager { mBackStack.add(state); } - public boolean popBackStackState(Handler handler, String name) { + public boolean popBackStackState(Handler handler, String name, int flags) { + return popBackStackState(handler, name, -1, flags); + } + + public boolean popBackStackState(Handler handler, int id, int flags) { + if (id < 0) { + return false; + } + return popBackStackState(handler, null, id, flags); + } + + boolean popBackStackState(Handler handler, String name, int id, int flags) { if (mBackStack == null) { return false; } - if (name == null) { + if (name == null && id < 0) { int last = mBackStack.size()-1; if (last < 0) { return false; @@ -576,11 +647,21 @@ public class FragmentManager { int index = mBackStack.size()-1; while (index >= 0) { BackStackEntry bss = mBackStack.get(index); - if (name.equals(bss.getName())) { + if (name != null && name.equals(bss.getName())) { + break; + } + if (id >= 0 && id == bss.mIndex) { break; } + index--; } - if (index < 0 || index == mBackStack.size()-1) { + if (index < 0) { + return false; + } + if ((flags&Activity.POP_BACK_STACK_INCLUSIVE) != 0) { + index--; + } + if (index == mBackStack.size()-1) { return false; } final ArrayList<BackStackEntry> states @@ -772,6 +853,9 @@ public class FragmentManager { for (int i=0; i<fms.mBackStack.length; i++) { BackStackEntry bse = fms.mBackStack[i].instantiate(this); mBackStack.add(bse); + if (bse.mIndex >= 0) { + setBackStackIndex(bse.mIndex, bse); + } } } else { mBackStack = null; diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java index 840f274f5ec6..65cf85cff724 100644 --- a/core/java/android/app/FragmentTransaction.java +++ b/core/java/android/app/FragmentTransaction.java @@ -147,5 +147,15 @@ public interface FragmentTransaction { public FragmentTransaction setTransitionStyle(int styleRes); public FragmentTransaction addToBackStack(String name); - public void commit(); + + /** + * Schedules a commit of this transaction. Note that the commit does + * not happen immediately; it will be scheduled as work on the main thread + * to be done the next time that thread is ready. + * + * @return Returns the identifier of this transaction's back stack entry, + * if {@link #addToBackStack(String)} had been called. Otherwise, returns + * a negative number. + */ + public int commit(); } diff --git a/core/java/android/app/ListFragment.java b/core/java/android/app/ListFragment.java index 73ef8690c6fe..6e2f4b6b54d3 100644 --- a/core/java/android/app/ListFragment.java +++ b/core/java/android/app/ListFragment.java @@ -28,10 +28,10 @@ import android.widget.ListView; import android.widget.TextView; /** - * An fragment that displays a list of items by binding to a data source such as + * A fragment that displays a list of items by binding to a data source such as * an array or Cursor, and exposes event handlers when the user selects an item. * <p> - * ListActivity hosts a {@link android.widget.ListView ListView} object that can + * ListFragment hosts a {@link android.widget.ListView ListView} object that can * be bound to different data sources, typically either an array or a Cursor * holding query results. Binding, screen layout, and row layout are discussed * in the following sections. @@ -39,10 +39,10 @@ import android.widget.TextView; * <strong>Screen Layout</strong> * </p> * <p> - * ListActivity has a default layout that consists of a single list view. + * ListFragment has a default layout that consists of a single list view. * However, if you desire, you can customize the fragment layout by returning * your own view hierarchy from {@link #onCreateView}. - * To do this, your view hierarchy MUST contain a ListView object with the + * To do this, your view hierarchy <em>must</em> contain a ListView object with the * id "@android:id/list" (or {@link android.R.id#list} if it's in code) * <p> * Optionally, your view hierarchy can contain another view object of any type to @@ -50,7 +50,7 @@ import android.widget.TextView; * id "android:empty". Note that when an empty view is present, the list view * will be hidden when there is no data to display. * <p> - * The following code demonstrates an (ugly) custom lisy layout. It has a list + * The following code demonstrates an (ugly) custom list layout. It has a list * with a green background, and an alternate red "no data" message. * </p> * @@ -134,6 +134,13 @@ import android.widget.TextView; * and {@link android.widget.SimpleCursorAdapter SimpleCursorAdapter} for Cursor * query results. * </p> + * <p> + * You <b>must</b> use + * {@link #setListAdapter(ListAdapter) ListFragment.setListAdapter()} to + * associate the list with an adapter. Do not directly call + * {@link ListView#setAdapter(ListAdapter) ListView.setAdapter()} or else + * important initialization will be skipped. + * </p> * * @see #setListAdapter * @see android.widget.ListView @@ -160,6 +167,7 @@ public class ListFragment extends Fragment { TextView mStandardEmptyView; View mProgressContainer; View mListContainer; + boolean mSetEmptyText; boolean mListShown; public ListFragment() { @@ -280,7 +288,11 @@ public class ListFragment extends Fragment { if (mStandardEmptyView == null) { throw new IllegalStateException("Can't be used with a custom content view"); } - mList.setEmptyView(mStandardEmptyView); + mStandardEmptyView.setText(text); + if (!mSetEmptyText) { + mList.setEmptyView(mStandardEmptyView); + mSetEmptyText = true; + } } /** diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index d0be554efeb0..34dd46c57f4d 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1314,6 +1314,7 @@ <public type="style" name="Theme.WithActionBar" /> <public type="style" name="Widget.Spinner.DropDown" /> <public type="style" name="Widget.ActionButton" /> + <public type="style" name="Theme.Dialog.NoFrame" /> <!-- Standard content view for a {@link android.app.ListFragment}. If you are implementing a subclass of ListFragment with your diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index 2dfe9ab3b6f2..bce0e02f67bb 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -426,13 +426,25 @@ <item name="textAppearanceSmallInverse">@android:style/TextAppearance.Small.Inverse</item> </style> + <!-- Variation of Theme.Dialog that does not include a frame (or background). + The view hierarchy of the dialog is responsible for drawing all of + its pixels. --> + <style name="Theme.Dialog.NoFrame"> + <item name="windowBackground">@android:color/transparent</item> + <item name="android:windowFrame">@null</item> + <item name="windowContentOverlay">@null</item> + <item name="android:windowAnimationStyle">@null</item> + <item name="android:backgroundDimEnabled">false</item> + <item name="android:windowIsTranslucent">true</item> + <item name="android:windowNoTitle">true</item> + </style> + <!-- Default theme for alert dialog windows, which is used by the {@link android.app.AlertDialog} class. This is basically a dialog but sets the background to empty so it can do two-tone backgrounds. --> <style name="Theme.Dialog.Alert"> <item name="windowBackground">@android:color/transparent</item> <item name="windowTitleStyle">@android:style/DialogWindowTitle</item> - <item name="windowIsFloating">true</item> <item name="windowContentOverlay">@null</item> </style> |