New sample code for fragment support library.

Also tweak a few things to make the demos run on Donut.

Change-Id: I298fdf8fb0f12ee6db10e66657a22e19a527811a
diff --git a/samples/ApiDemos/src/com/example/android/apis/ApiDemos.java b/samples/ApiDemos/src/com/example/android/apis/ApiDemos.java
index 39f24b6..ffce027 100644
--- a/samples/ApiDemos/src/com/example/android/apis/ApiDemos.java
+++ b/samples/ApiDemos/src/com/example/android/apis/ApiDemos.java
@@ -65,11 +65,13 @@
             return myData;
 
         String[] prefixPath;
+        String prefixWithSlash = prefix;
         
         if (prefix.equals("")) {
             prefixPath = null;
         } else {
             prefixPath = prefix.split("/");
+            prefixWithSlash = prefix + "/";
         }
         
         int len = list.size();
@@ -83,7 +85,7 @@
                     ? labelSeq.toString()
                     : info.activityInfo.name;
             
-            if (prefix.length() == 0 || label.startsWith(prefix)) {
+            if (prefixWithSlash.length() == 0 || label.startsWith(prefixWithSlash)) {
                 
                 String[] labelPath = label.split("/");
 
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/FragmentAlertDialogSupport.java b/samples/ApiDemos/src/com/example/android/apis/app/FragmentAlertDialogSupport.java
new file mode 100644
index 0000000..84e0ef6
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentAlertDialogSupport.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.app;
+
+import com.example.android.apis.R;
+
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.FragmentActivity;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+
+/**
+ * Demonstrates how to show an AlertDialog that is managed by a Fragment.
+ */
+public class FragmentAlertDialogSupport extends FragmentActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.fragment_dialog);
+
+        View tv = findViewById(R.id.text);
+        ((TextView)tv).setText("Example of displaying an alert dialog with a DialogFragment");
+
+        // Watch for button clicks.
+        Button button = (Button)findViewById(R.id.show);
+        button.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                showDialog();
+            }
+        });
+    }
+
+//BEGIN_INCLUDE(activity)
+    void showDialog() {
+        DialogFragment newFragment = MyAlertDialogFragment.newInstance(
+                R.string.alert_dialog_two_buttons_title);
+        newFragment.show(getSupportFragmentManager(), "dialog");
+    }
+
+    public void doPositiveClick() {
+        // Do stuff here.
+        Log.i("FragmentAlertDialog", "Positive click!");
+    }
+
+    public void doNegativeClick() {
+        // Do stuff here.
+        Log.i("FragmentAlertDialog", "Negative click!");
+    }
+//END_INCLUDE(activity)
+
+//BEGIN_INCLUDE(dialog)
+    public static class MyAlertDialogFragment extends DialogFragment {
+
+        public static MyAlertDialogFragment newInstance(int title) {
+            MyAlertDialogFragment frag = new MyAlertDialogFragment();
+            Bundle args = new Bundle();
+            args.putInt("title", title);
+            frag.setArguments(args);
+            return frag;
+        }
+
+        @Override
+        public Dialog onCreateDialog(Bundle savedInstanceState) {
+            int title = getArguments().getInt("title");
+
+            return new AlertDialog.Builder(getActivity())
+                    .setIcon(R.drawable.alert_dialog_icon)
+                    .setTitle(title)
+                    .setPositiveButton(R.string.alert_dialog_ok,
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int whichButton) {
+                                ((FragmentAlertDialogSupport)getActivity()).doPositiveClick();
+                            }
+                        }
+                    )
+                    .setNegativeButton(R.string.alert_dialog_cancel,
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int whichButton) {
+                                ((FragmentAlertDialogSupport)getActivity()).doNegativeClick();
+                            }
+                        }
+                    )
+                    .create();
+        }
+    }
+//END_INCLUDE(dialog)
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/FragmentContextMenuSupport.java b/samples/ApiDemos/src/com/example/android/apis/app/FragmentContextMenuSupport.java
new file mode 100644
index 0000000..3b4af5f
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentContextMenuSupport.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.app;
+
+import com.example.android.apis.R;
+
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.ContextMenu;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ContextMenu.ContextMenuInfo;
+
+/**
+ * Demonstration of displaying a context menu from a fragment.
+ */
+public class FragmentContextMenuSupport extends FragmentActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Create the list fragment and add it as our sole content.
+        ContextMenuFragment content = new ContextMenuFragment();
+        getSupportFragmentManager().beginTransaction().add(
+                android.R.id.content, content).commit();
+    }
+
+    public static class ContextMenuFragment extends Fragment {
+
+        @Override
+        public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                Bundle savedInstanceState) {
+            View root = inflater.inflate(R.layout.fragment_context_menu, container, false);
+            registerForContextMenu(root.findViewById(R.id.long_press));
+            return root;
+        }
+
+        @Override
+        public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
+            super.onCreateContextMenu(menu, v, menuInfo);
+            menu.add(Menu.NONE, R.id.a_item, Menu.NONE, "Menu A");
+            menu.add(Menu.NONE, R.id.b_item, Menu.NONE, "Menu B");
+        }
+
+        @Override
+        public boolean onContextItemSelected(MenuItem item) {
+            switch (item.getItemId()) {
+                case R.id.a_item:
+                    Log.i("ContextMenu", "Item 1a was chosen");
+                    return true;
+                case R.id.b_item:
+                    Log.i("ContextMenu", "Item 1b was chosen");
+                    return true;
+            }
+            return super.onContextItemSelected(item);
+        }
+    }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialogOrActivitySupport.java b/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialogOrActivitySupport.java
new file mode 100644
index 0000000..20e4569
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialogOrActivitySupport.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.app;
+
+import com.example.android.apis.R;
+
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentTransaction;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+
+public class FragmentDialogOrActivitySupport extends FragmentActivity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.fragment_dialog_or_activity);
+
+        if (savedInstanceState == null) {
+            // First-time init; create fragment to embed in activity.
+//BEGIN_INCLUDE(embed)
+            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+            DialogFragment newFragment = MyDialogFragment.newInstance();
+            ft.add(R.id.embedded, newFragment);
+            ft.commit();
+//END_INCLUDE(embed)
+        }
+
+        // Watch for button clicks.
+        Button button = (Button)findViewById(R.id.show_dialog);
+        button.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                showDialog();
+            }
+        });
+    }
+
+//BEGIN_INCLUDE(show_dialog)
+    void showDialog() {
+        // Create the fragment and show it as a dialog.
+        DialogFragment newFragment = MyDialogFragment.newInstance();
+        newFragment.show(getSupportFragmentManager(), "dialog");
+    }
+//END_INCLUDE(show_dialog)
+
+//BEGIN_INCLUDE(dialog)
+    public static class MyDialogFragment extends DialogFragment {
+        static MyDialogFragment newInstance() {
+            return new MyDialogFragment();
+        }
+
+        @Override
+        public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                Bundle savedInstanceState) {
+            View v = inflater.inflate(R.layout.hello_world, container, false);
+            View tv = v.findViewById(R.id.text);
+            ((TextView)tv).setText("This is an instance of MyDialogFragment");
+            return v;
+        }
+    }
+//END_INCLUDE(dialog)
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialogSupport.java b/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialogSupport.java
new file mode 100644
index 0000000..9b93d48
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentDialogSupport.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.app;
+
+import com.example.android.apis.R;
+
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentTransaction;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+public class FragmentDialogSupport extends FragmentActivity {
+    int mStackLevel = 0;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.fragment_dialog);
+
+        View tv = findViewById(R.id.text);
+        ((TextView)tv).setText("Example of displaying dialogs with a DialogFragment.  "
+                + "Press the show button below to see the first dialog; pressing "
+                + "successive show buttons will display other dialog styles as a "
+                + "stack, with dismissing or back going to the previous dialog.");
+
+        // Watch for button clicks.
+        Button button = (Button)findViewById(R.id.show);
+        button.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                showDialog();
+            }
+        });
+
+        if (savedInstanceState != null) {
+            mStackLevel = savedInstanceState.getInt("level");
+        }
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putInt("level", mStackLevel);
+    }
+
+//BEGIN_INCLUDE(add_dialog)
+    void showDialog() {
+        mStackLevel++;
+
+        // DialogFragment.show() will take care of adding the fragment
+        // in a transaction.  We also want to remove any currently showing
+        // dialog, so make our own transaction and take care of that here.
+        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+        Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
+        if (prev != null) {
+            ft.remove(prev);
+        }
+        ft.addToBackStack(null);
+
+        // Create and show the dialog.
+        DialogFragment newFragment = MyDialogFragment.newInstance(mStackLevel);
+        newFragment.show(ft, "dialog");
+    }
+//END_INCLUDE(add_dialog)
+
+    static String getNameForNum(int num) {
+        switch ((num-1)%6) {
+            case 1: return "STYLE_NO_TITLE";
+            case 2: return "STYLE_NO_FRAME";
+            case 3: return "STYLE_NO_INPUT (this window can't receive input, so "
+                    + "you will need to press the bottom show button)";
+            case 4: return "STYLE_NORMAL with dark fullscreen theme";
+            case 5: return "STYLE_NORMAL with light theme";
+            case 6: return "STYLE_NO_TITLE with light theme";
+            case 7: return "STYLE_NO_FRAME with light theme";
+            case 8: return "STYLE_NORMAL with light fullscreen theme";
+        }
+        return "STYLE_NORMAL";
+    }
+
+//BEGIN_INCLUDE(dialog)
+    public static class MyDialogFragment extends DialogFragment {
+        int mNum;
+
+        /**
+         * Create a new instance of MyDialogFragment, providing "num"
+         * as an argument.
+         */
+        static MyDialogFragment newInstance(int num) {
+            MyDialogFragment f = new MyDialogFragment();
+
+            // Supply num input as an argument.
+            Bundle args = new Bundle();
+            args.putInt("num", num);
+            f.setArguments(args);
+
+            return f;
+        }
+
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            mNum = getArguments().getInt("num");
+
+            // Pick a style based on the num.
+            int style = DialogFragment.STYLE_NORMAL, theme = 0;
+            switch ((mNum-1)%6) {
+                case 1: style = DialogFragment.STYLE_NO_TITLE; break;
+                case 2: style = DialogFragment.STYLE_NO_FRAME; break;
+                case 3: style = DialogFragment.STYLE_NO_INPUT; break;
+                case 4: style = DialogFragment.STYLE_NORMAL; break;
+                case 5: style = DialogFragment.STYLE_NO_TITLE; break;
+                case 6: style = DialogFragment.STYLE_NO_FRAME; break;
+                case 7: style = DialogFragment.STYLE_NORMAL; break;
+            }
+            switch ((mNum-1)%6) {
+                case 2: theme = android.R.style.Theme_Panel; break;
+                case 4: theme = android.R.style.Theme; break;
+                case 5: theme = android.R.style.Theme_Light; break;
+                case 6: theme = android.R.style.Theme_Light_Panel; break;
+                case 7: theme = android.R.style.Theme_Light; break;
+            }
+            setStyle(style, theme);
+        }
+
+        @Override
+        public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                Bundle savedInstanceState) {
+            View v = inflater.inflate(R.layout.fragment_dialog, container, false);
+            View tv = v.findViewById(R.id.text);
+            ((TextView)tv).setText("Dialog #" + mNum + ": using style "
+                    + getNameForNum(mNum));
+
+            // Watch for button clicks.
+            Button button = (Button)v.findViewById(R.id.show);
+            button.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    // When button is clicked, call up to owning activity.
+                    ((FragmentDialogSupport)getActivity()).showDialog();
+                }
+            });
+
+            return v;
+        }
+    }
+//END_INCLUDE(dialog)
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/FragmentHideShowSupport.java b/samples/ApiDemos/src/com/example/android/apis/app/FragmentHideShowSupport.java
new file mode 100644
index 0000000..bd5161d
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentHideShowSupport.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.app;
+
+import com.example.android.apis.R;
+
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+
+/**
+ * Demonstration of hiding and showing fragments.
+ */
+public class FragmentHideShowSupport extends FragmentActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.fragment_hide_show_support);
+
+        // The content view embeds two fragments; now retrieve them and attach
+        // their "hide" button.
+        FragmentManager fm = getSupportFragmentManager();
+        addShowHideListener(R.id.frag1hide, fm.findFragmentById(R.id.fragment1));
+        addShowHideListener(R.id.frag2hide, fm.findFragmentById(R.id.fragment2));
+    }
+
+    void addShowHideListener(int buttonId, final Fragment fragment) {
+        final Button button = (Button)findViewById(buttonId);
+        button.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+                ft.setCustomAnimations(android.R.anim.fade_in,
+                        android.R.anim.fade_out);
+                if (fragment.isHidden()) {
+                    ft.show(fragment);
+                    button.setText("Hide");
+                } else {
+                    ft.hide(fragment);
+                    button.setText("Show");
+                }
+                ft.commit();
+            }
+        });
+    }
+
+    public static class FirstFragment extends Fragment {
+        TextView mTextView;
+
+        @Override
+        public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                Bundle savedInstanceState) {
+            View v = inflater.inflate(R.layout.labeled_text_edit, container, false);
+            View tv = v.findViewById(R.id.msg);
+            ((TextView)tv).setText("The fragment saves and restores this text.");
+
+            // Retrieve the text editor, and restore the last saved state if needed.
+            mTextView = (TextView)v.findViewById(R.id.saved);
+            if (savedInstanceState != null) {
+                mTextView.setText(savedInstanceState.getCharSequence("text"));
+            }
+            return v;
+        }
+
+        @Override
+        public void onSaveInstanceState(Bundle outState) {
+            super.onSaveInstanceState(outState);
+
+            // Remember the current text, to restore if we later restart.
+            outState.putCharSequence("text", mTextView.getText());
+        }
+    }
+
+    public static class SecondFragment extends Fragment {
+
+        @Override
+        public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                Bundle savedInstanceState) {
+            View v = inflater.inflate(R.layout.labeled_text_edit, container, false);
+            View tv = v.findViewById(R.id.msg);
+            ((TextView)tv).setText("The TextView saves and restores this text.");
+
+            // Retrieve the text editor and tell it to save and restore its state.
+            // Note that you will often set this in the layout XML, but since
+            // we are sharing our layout with the other fragment we will customize
+            // it here.
+            ((TextView)v.findViewById(R.id.saved)).setSaveEnabled(true);
+            return v;
+        }
+    }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java b/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
index 81853a2..730f4d4 100644
--- a/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
@@ -89,7 +89,6 @@
     public static class TitlesFragment extends ListFragment {
         boolean mDualPane;
         int mCurCheckPosition = 0;
-        int mShownCheckPosition = -1;
 
         @Override
         public void onActivityCreated(Bundle savedInstanceState) {
@@ -107,7 +106,6 @@
             if (savedInstanceState != null) {
                 // Restore last state for checked position.
                 mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
-                mShownCheckPosition = savedInstanceState.getInt("shownChoice", -1);
             }
 
             if (mDualPane) {
@@ -122,7 +120,6 @@
         public void onSaveInstanceState(Bundle outState) {
             super.onSaveInstanceState(outState);
             outState.putInt("curChoice", mCurCheckPosition);
-            outState.putInt("shownChoice", mShownCheckPosition);
         }
 
         @Override
@@ -143,18 +140,19 @@
                 // the list to highlight the selected item and show the data.
                 getListView().setItemChecked(index, true);
 
-                if (mShownCheckPosition != mCurCheckPosition) {
-                    // If we are not currently showing a fragment for the new
-                    // position, we need to create and install a new one.
-                    DetailsFragment df = DetailsFragment.newInstance(index);
+                // Check what fragment is currently shown, replace if needed.
+                DetailsFragment details = (DetailsFragment)
+                        getFragmentManager().findFragmentById(R.id.details);
+                if (details == null || details.getShownIndex() != index) {
+                    // Make new fragment to show this selection.
+                    details = DetailsFragment.newInstance(index);
 
                     // Execute a transaction, replacing any existing fragment
                     // with this one inside the frame.
                     FragmentTransaction ft = getFragmentManager().beginTransaction();
-                    ft.replace(R.id.details, df);
+                    ft.replace(R.id.details, details);
                     ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                     ft.commit();
-                    mShownCheckPosition = index;
                 }
 
             } else {
@@ -190,6 +188,10 @@
             return f;
         }
 
+        public int getShownIndex() {
+            return getArguments().getInt("index", 0);
+        }
+
         @Override
         public View onCreateView(LayoutInflater inflater, ViewGroup container,
                 Bundle savedInstanceState) {
@@ -210,7 +212,7 @@
                     4, getActivity().getResources().getDisplayMetrics());
             text.setPadding(padding, padding, padding, padding);
             scroller.addView(text);
-            text.setText(Shakespeare.DIALOGUE[getArguments().getInt("index", 0)]);
+            text.setText(Shakespeare.DIALOGUE[getShownIndex()]);
             return scroller;
         }
     }
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayoutSupport.java b/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayoutSupport.java
new file mode 100644
index 0000000..b6aa7ee
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentLayoutSupport.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.app;
+
+import com.example.android.apis.R;
+import com.example.android.apis.Shakespeare;
+
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v4.app.ListFragment;
+
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+/**
+ * Demonstration of using fragments to implement different activity layouts.
+ * This sample provides a different layout (and activity flow) when run in
+ * landscape.
+ */
+public class FragmentLayoutSupport extends FragmentActivity {
+
+//BEGIN_INCLUDE(main)
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.fragment_layout_support);
+    }
+//END_INCLUDE(main)
+
+    /**
+     * This is a secondary activity, to show what the user has selected
+     * when the screen is not large enough to show it all in one activity.
+     */
+//BEGIN_INCLUDE(details_activity)
+    public static class DetailsActivity extends FragmentActivity {
+
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+
+            if (getResources().getConfiguration().orientation
+                    == Configuration.ORIENTATION_LANDSCAPE) {
+                // If the screen is now in landscape mode, we can show the
+                // dialog in-line with the list so we don't need this activity.
+                finish();
+                return;
+            }
+
+            if (savedInstanceState == null) {
+                // During initial setup, plug in the details fragment.
+                DetailsFragment details = new DetailsFragment();
+                details.setArguments(getIntent().getExtras());
+                getSupportFragmentManager().beginTransaction().add(
+                        android.R.id.content, details).commit();
+            }
+        }
+    }
+//END_INCLUDE(details_activity)
+
+    /**
+     * This is the "top-level" fragment, showing a list of items that the
+     * user can pick.  Upon picking an item, it takes care of displaying the
+     * data to the user as appropriate based on the currrent UI layout.
+     */
+//BEGIN_INCLUDE(titles)
+    public static class TitlesFragment extends ListFragment {
+        boolean mDualPane;
+        int mCurCheckPosition = 0;
+
+        @Override
+        public void onActivityCreated(Bundle savedInstanceState) {
+            super.onActivityCreated(savedInstanceState);
+
+            // Populate list with our static array of titles.
+            setListAdapter(new ArrayAdapter<String>(getActivity(),
+                    R.layout.simple_list_item_checkable_1,
+                    android.R.id.text1, Shakespeare.TITLES));
+
+            // Check to see if we have a frame in which to embed the details
+            // fragment directly in the containing UI.
+            View detailsFrame = getActivity().findViewById(R.id.details);
+            mDualPane = detailsFrame != null && detailsFrame.getVisibility() == View.VISIBLE;
+
+            if (savedInstanceState != null) {
+                // Restore last state for checked position.
+                mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
+            }
+
+            if (mDualPane) {
+                // In dual-pane mode, the list view highlights the selected item.
+                getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+                // Make sure our UI is in the correct state.
+                showDetails(mCurCheckPosition);
+            }
+        }
+
+        @Override
+        public void onSaveInstanceState(Bundle outState) {
+            super.onSaveInstanceState(outState);
+            outState.putInt("curChoice", mCurCheckPosition);
+        }
+
+        @Override
+        public void onListItemClick(ListView l, View v, int position, long id) {
+            showDetails(position);
+        }
+
+        /**
+         * Helper function to show the details of a selected item, either by
+         * displaying a fragment in-place in the current UI, or starting a
+         * whole new activity in which it is displayed.
+         */
+        void showDetails(int index) {
+            mCurCheckPosition = index;
+
+            if (mDualPane) {
+                // We can display everything in-place with fragments, so update
+                // the list to highlight the selected item and show the data.
+                getListView().setItemChecked(index, true);
+
+                // Check what fragment is currently shown, replace if needed.
+                DetailsFragment details = (DetailsFragment)
+                        getFragmentManager().findFragmentById(R.id.details);
+                if (details == null || details.getShownIndex() != index) {
+                    // Make new fragment to show this selection.
+                    details = DetailsFragment.newInstance(index);
+
+                    // Execute a transaction, replacing any existing fragment
+                    // with this one inside the frame.
+                    FragmentTransaction ft = getFragmentManager().beginTransaction();
+                    ft.replace(R.id.details, details);
+                    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
+                    ft.commit();
+                }
+
+            } else {
+                // Otherwise we need to launch a new activity to display
+                // the dialog fragment with selected text.
+                Intent intent = new Intent();
+                intent.setClass(getActivity(), DetailsActivity.class);
+                intent.putExtra("index", index);
+                startActivity(intent);
+            }
+        }
+    }
+//END_INCLUDE(titles)
+
+    /**
+     * This is the secondary fragment, displaying the details of a particular
+     * item.
+     */
+//BEGIN_INCLUDE(details)
+    public static class DetailsFragment extends Fragment {
+        /**
+         * Create a new instance of DetailsFragment, initialized to
+         * show the text at 'index'.
+         */
+        public static DetailsFragment newInstance(int index) {
+            DetailsFragment f = new DetailsFragment();
+
+            // Supply index input as an argument.
+            Bundle args = new Bundle();
+            args.putInt("index", index);
+            f.setArguments(args);
+
+            return f;
+        }
+
+        public int getShownIndex() {
+            return getArguments().getInt("index", 0);
+        }
+
+        @Override
+        public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                Bundle savedInstanceState) {
+            if (container == null) {
+                // We have different layouts, and in one of them this
+                // fragment's containing frame doesn't exist.  The fragment
+                // may still be created from its saved state, but there is
+                // no reason to try to create its view hierarchy because it
+                // won't be displayed.  Note this is not needed -- we could
+                // just run the code below, where we would create and return
+                // the view hierarchy; it would just never be used.
+                return null;
+            }
+
+            ScrollView scroller = new ScrollView(getActivity());
+            TextView text = new TextView(getActivity());
+            int padding = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+                    4, getActivity().getResources().getDisplayMetrics());
+            text.setPadding(padding, padding, padding, padding);
+            scroller.addView(text);
+            text.setText(Shakespeare.DIALOGUE[getShownIndex()]);
+            return scroller;
+        }
+    }
+//END_INCLUDE(details)
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/FragmentListArraySupport.java b/samples/ApiDemos/src/com/example/android/apis/app/FragmentListArraySupport.java
new file mode 100644
index 0000000..aa3df32
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentListArraySupport.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.app;
+
+import com.example.android.apis.Shakespeare;
+
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.ListFragment;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+/**
+ * Demonstration of using ListFragment to show a list of items
+ * from a canned array.
+ */
+public class FragmentListArraySupport extends FragmentActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Create the list fragment and add it as our sole content.
+        if (getSupportFragmentManager().findFragmentById(android.R.id.content) == null) {
+            ArrayListFragment list = new ArrayListFragment();
+            getSupportFragmentManager().beginTransaction().add(android.R.id.content, list).commit();
+        }
+    }
+
+    public static class ArrayListFragment extends ListFragment {
+
+        @Override
+        public void onActivityCreated(Bundle savedInstanceState) {
+            super.onActivityCreated(savedInstanceState);
+            setListAdapter(new ArrayAdapter<String>(getActivity(),
+                    android.R.layout.simple_list_item_1, Shakespeare.TITLES));
+        }
+
+        @Override
+        public void onListItemClick(ListView l, View v, int position, long id) {
+            Log.i("FragmentList", "Item clicked: " + id);
+        }
+    }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/FragmentListCursorLoaderSupport.java b/samples/ApiDemos/src/com/example/android/apis/app/FragmentListCursorLoaderSupport.java
new file mode 100644
index 0000000..35a2f35
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentListCursorLoaderSupport.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.app;
+
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.ListFragment;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.support.v4.widget.SimpleCursorAdapter;
+
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.ContactsContract.Contacts;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ListView;
+
+/**
+ * Demonstration of more complex use if a ListFragment, including showing
+ * an empty view and loading progress.
+ */
+public class FragmentListCursorLoaderSupport extends FragmentActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        FragmentManager fm = getSupportFragmentManager();
+
+        // Create the list fragment and add it as our sole content.
+        if (fm.findFragmentById(android.R.id.content) == null) {
+            CursorLoaderListFragment list = new CursorLoaderListFragment();
+            fm.beginTransaction().add(android.R.id.content, list).commit();
+        }
+    }
+
+//BEGIN_INCLUDE(fragment_cursor)
+    public static class CursorLoaderListFragment extends ListFragment
+            implements LoaderManager.LoaderCallbacks<Cursor> {
+
+        // This is the Adapter being used to display the list's data.
+        SimpleCursorAdapter mAdapter;
+
+        // If non-null, this is the current filter the user has provided.
+        String mCurFilter;
+
+        @Override public void onActivityCreated(Bundle savedInstanceState) {
+            super.onActivityCreated(savedInstanceState);
+
+            // Give some text to display if there is no data.  In a real
+            // application this would come from a resource.
+            setEmptyText("No phone numbers");
+
+            // We have a menu item to show in action bar.
+            setHasOptionsMenu(true);
+
+            // Create an empty adapter we will use to display the loaded data.
+            mAdapter = new SimpleCursorAdapter(getActivity(),
+                    android.R.layout.simple_list_item_2, null,
+                    new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
+                    new int[] { android.R.id.text1, android.R.id.text2 }, 0);
+            setListAdapter(mAdapter);
+
+            // Prepare the loader.  Either re-connect with an existing one,
+            // or start a new one.
+            getLoaderManager().initLoader(0, null, this);
+        }
+
+        @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+            // Place an action bar item for searching.
+            //MenuItem item = menu.add("Search");
+            //item.setIcon(android.R.drawable.ic_menu_search);
+            //item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+            //SearchView sv = new SearchView(getActivity());
+            //sv.setOnQueryTextListener(this);
+            //item.setActionView(sv);
+        }
+
+        public boolean onQueryTextChange(String newText) {
+            // Called when the action bar search text has changed.  Update
+            // the search filter, and restart the loader to do a new query
+            // with this filter.
+            mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
+            getLoaderManager().restartLoader(0, null, this);
+            return true;
+        }
+
+        @Override public void onListItemClick(ListView l, View v, int position, long id) {
+            // Insert desired behavior here.
+            Log.i("FragmentComplexList", "Item clicked: " + id);
+        }
+
+        // These are the Contacts rows that we will retrieve.
+        static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
+            Contacts._ID,
+            Contacts.DISPLAY_NAME,
+            Contacts.CONTACT_STATUS,
+            Contacts.CONTACT_PRESENCE,
+            Contacts.PHOTO_ID,
+            Contacts.LOOKUP_KEY,
+        };
+
+        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+            // This is called when a new Loader needs to be created.  This
+            // sample only has one Loader, so we don't care about the ID.
+            // First, pick the base URI to use depending on whether we are
+            // currently filtering.
+            Uri baseUri;
+            if (mCurFilter != null) {
+                baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
+                        Uri.encode(mCurFilter));
+            } else {
+                baseUri = Contacts.CONTENT_URI;
+            }
+
+            // Now create and return a CursorLoader that will take care of
+            // creating a Cursor for the data being displayed.
+            String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
+                    + Contacts.HAS_PHONE_NUMBER + "=1) AND ("
+                    + Contacts.DISPLAY_NAME + " != '' ))";
+            return new CursorLoader(getActivity(), baseUri,
+                    CONTACTS_SUMMARY_PROJECTION, select, null,
+                    Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
+        }
+
+        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+            // Swap the new cursor in.  (The framework will take care of closing the
+            // old cursor once we return.)
+            mAdapter.swapCursor(data);
+        }
+
+        public void onLoaderReset(Loader<Cursor> loader) {
+            // This is called when the last Cursor provided to onLoadFinished()
+            // above is about to be closed.  We need to make sure we are no
+            // longer using it.
+            mAdapter.swapCursor(null);
+        }
+    }
+//END_INCLUDE(fragment_cursor)
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/FragmentMenu.java b/samples/ApiDemos/src/com/example/android/apis/app/FragmentMenu.java
index fa54359..8f588d1 100644
--- a/samples/ApiDemos/src/com/example/android/apis/app/FragmentMenu.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentMenu.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package com.example.android.apis.app;
 
 import com.example.android.apis.R;
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/FragmentMenuSupport.java b/samples/ApiDemos/src/com/example/android/apis/app/FragmentMenuSupport.java
new file mode 100644
index 0000000..05d94ca
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentMenuSupport.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.app;
+
+import com.example.android.apis.R;
+
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v4.view.MenuCompat;
+
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.CheckBox;
+
+/**
+ * Demonstrates how fragments can participate in the options menu.
+ */
+public class FragmentMenuSupport extends FragmentActivity {
+    Fragment mFragment1;
+    Fragment mFragment2;
+    CheckBox mCheckBox1;
+    CheckBox mCheckBox2;
+
+    // Update fragment visibility when check boxes are changed.
+    final OnClickListener mClickListener = new OnClickListener() {
+        public void onClick(View v) {
+            updateFragmentVisibility();
+        }
+    };
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.fragment_menu);
+
+        // Make sure the two menu fragments are created.
+        FragmentManager fm = getSupportFragmentManager();
+        FragmentTransaction ft = fm.beginTransaction();
+        mFragment1 = fm.findFragmentByTag("f1");
+        if (mFragment1 == null) {
+            mFragment1 = new MenuFragment();
+            ft.add(mFragment1, "f1");
+        }
+        mFragment2 = fm.findFragmentByTag("f2");
+        if (mFragment2 == null) {
+            mFragment2 = new Menu2Fragment();
+            ft.add(mFragment2, "f2");
+        }
+        ft.commit();
+
+        // Watch check box clicks.
+        mCheckBox1 = (CheckBox)findViewById(R.id.menu1);
+        mCheckBox1.setOnClickListener(mClickListener);
+        mCheckBox2 = (CheckBox)findViewById(R.id.menu2);
+        mCheckBox2.setOnClickListener(mClickListener);
+
+        // Make sure fragments start out with correct visibility.
+        updateFragmentVisibility();
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Bundle savedInstanceState) {
+        super.onRestoreInstanceState(savedInstanceState);
+        // Make sure fragments are updated after check box view state is restored.
+        updateFragmentVisibility();
+    }
+
+    // Update fragment visibility based on current check box state.
+    void updateFragmentVisibility() {
+        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+        if (mCheckBox1.isChecked()) ft.show(mFragment1);
+        else ft.hide(mFragment1);
+        if (mCheckBox2.isChecked()) ft.show(mFragment2);
+        else ft.hide(mFragment2);
+        ft.commit();
+    }
+
+    /**
+     * A fragment that displays a menu.  This fragment happens to not
+     * have a UI (it does not implement onCreateView), but it could also
+     * have one if it wanted.
+     */
+    public static class MenuFragment extends Fragment {
+
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            setHasOptionsMenu(true);
+        }
+
+        @Override
+        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+            MenuItem item;
+            item = menu.add("Menu 1a");
+            MenuCompat.setShowAsAction(item, MenuItem.SHOW_AS_ACTION_IF_ROOM);
+            item = menu.add("Menu 1b");
+            MenuCompat.setShowAsAction(item, MenuItem.SHOW_AS_ACTION_IF_ROOM);
+        }
+    }
+
+    /**
+     * Second fragment with a menu.
+     */
+    public static class Menu2Fragment extends Fragment {
+
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            setHasOptionsMenu(true);
+        }
+
+        @Override
+        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+            MenuItem item;
+            item = menu.add("Menu 2");
+            MenuCompat.setShowAsAction(item, MenuItem.SHOW_AS_ACTION_IF_ROOM);
+        }
+    }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/FragmentReceiveResult.java b/samples/ApiDemos/src/com/example/android/apis/app/FragmentReceiveResult.java
index fad77ff..f207cf9 100644
--- a/samples/ApiDemos/src/com/example/android/apis/app/FragmentReceiveResult.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentReceiveResult.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package com.example.android.apis.app;
 
 import com.example.android.apis.R;
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/FragmentReceiveResultSupport.java b/samples/ApiDemos/src/com/example/android/apis/app/FragmentReceiveResultSupport.java
new file mode 100644
index 0000000..3a3a34a
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentReceiveResultSupport.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.app;
+
+import com.example.android.apis.R;
+
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentTransaction;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.Editable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+public class FragmentReceiveResultSupport extends FragmentActivity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT);
+        FrameLayout frame = new FrameLayout(this);
+        frame.setId(R.id.simple_fragment);
+        setContentView(frame, lp);
+
+        if (savedInstanceState == null) {
+            // Do first time initialization -- add fragment.
+            Fragment newFragment = new ReceiveResultFragment();
+            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+            ft.add(R.id.simple_fragment, newFragment).commit();
+        }
+    }
+
+    public static class ReceiveResultFragment extends Fragment {
+        // Definition of the one requestCode we use for receiving resuls.
+        static final private int GET_CODE = 0;
+
+        private TextView mResults;
+
+        private OnClickListener mGetListener = new OnClickListener() {
+            public void onClick(View v) {
+                // Start the activity whose result we want to retrieve.  The
+                // result will come back with request code GET_CODE.
+                Intent intent = new Intent(getActivity(), SendResult.class);
+                startActivityForResult(intent, GET_CODE);
+            }
+        };
+
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+        }
+
+        @Override
+        public void onSaveInstanceState(Bundle outState) {
+            super.onSaveInstanceState(outState);
+        }
+
+        @Override
+        public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                Bundle savedInstanceState) {
+            View v = inflater.inflate(R.layout.receive_result, container, false);
+
+            // Retrieve the TextView widget that will display results.
+            mResults = (TextView)v.findViewById(R.id.results);
+
+            // This allows us to later extend the text buffer.
+            mResults.setText(mResults.getText(), TextView.BufferType.EDITABLE);
+
+            // Watch for button clicks.
+            Button getButton = (Button)v.findViewById(R.id.get);
+            getButton.setOnClickListener(mGetListener);
+
+            return v;
+        }
+
+        /**
+         * This method is called when the sending activity has finished, with the
+         * result it supplied.
+         */
+        @Override
+        public void onActivityResult(int requestCode, int resultCode, Intent data) {
+            // You can use the requestCode to select between multiple child
+            // activities you may have started.  Here there is only one thing
+            // we launch.
+            if (requestCode == GET_CODE) {
+
+                // We will be adding to our text.
+                Editable text = (Editable)mResults.getText();
+
+                // This is a standard resultCode that is sent back if the
+                // activity doesn't supply an explicit result.  It will also
+                // be returned if the activity failed to launch.
+                if (resultCode == RESULT_CANCELED) {
+                    text.append("(cancelled)");
+
+                // Our protocol with the sending activity is that it will send
+                // text in 'data' as its result.
+                } else {
+                    text.append("(okay ");
+                    text.append(Integer.toString(resultCode));
+                    text.append(") ");
+                    if (data != null) {
+                        text.append(data.getAction());
+                    }
+                }
+
+                text.append("\n");
+            }
+        }
+    }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/FragmentRetainInstanceSupport.java b/samples/ApiDemos/src/com/example/android/apis/app/FragmentRetainInstanceSupport.java
new file mode 100644
index 0000000..b83ca44
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentRetainInstanceSupport.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.app;
+
+import com.example.android.apis.R;
+
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.ProgressBar;
+
+/**
+ * This example shows how you can use a Fragment to easily propagate state
+ * (such as threads) across activity instances when an activity needs to be
+ * restarted due to, for example, a configuration change.  This is a lot
+ * easier than using the raw Activity.onRetainNonConfiguratinInstance() API.
+ */
+public class FragmentRetainInstanceSupport extends FragmentActivity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // First time init, create the UI.
+        if (savedInstanceState == null) {
+            getSupportFragmentManager().beginTransaction().add(android.R.id.content,
+                    new UiFragment()).commit();
+        }
+    }
+
+    /**
+     * This is a fragment showing UI that will be updated from work done
+     * in the retained fragment.
+     */
+    public static class UiFragment extends Fragment {
+        RetainedFragment mWorkFragment;
+
+        @Override
+        public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                Bundle savedInstanceState) {
+            View v = inflater.inflate(R.layout.fragment_retain_instance, container, false);
+
+            // Watch for button clicks.
+            Button button = (Button)v.findViewById(R.id.restart);
+            button.setOnClickListener(new OnClickListener() {
+                public void onClick(View v) {
+                    mWorkFragment.restart();
+                }
+            });
+
+            return v;
+        }
+
+        @Override
+        public void onActivityCreated(Bundle savedInstanceState) {
+            super.onActivityCreated(savedInstanceState);
+
+            FragmentManager fm = getFragmentManager();
+
+            // Check to see if we have retained the worker fragment.
+            mWorkFragment = (RetainedFragment)fm.findFragmentByTag("work");
+
+            // If not retained (or first time running), we need to create it.
+            if (mWorkFragment == null) {
+                mWorkFragment = new RetainedFragment();
+                // Tell it who it is working with.
+                mWorkFragment.setTargetFragment(this, 0);
+                fm.beginTransaction().add(mWorkFragment, "work").commit();
+            }
+        }
+
+    }
+
+    /**
+     * This is the Fragment implementation that will be retained across
+     * activity instances.  It represents some ongoing work, here a thread
+     * we have that sits around incrementing a progress indicator.
+     */
+    public static class RetainedFragment extends Fragment {
+        ProgressBar mProgressBar;
+        int mPosition;
+        boolean mReady = false;
+        boolean mQuiting = false;
+
+        /**
+         * This is the thread that will do our work.  It sits in a loop running
+         * the progress up until it has reached the top, then stops and waits.
+         */
+        final Thread mThread = new Thread() {
+            @Override
+            public void run() {
+                // We'll figure the real value out later.
+                int max = 10000;
+
+                // This thread runs almost forever.
+                while (true) {
+
+                    // Update our shared state with the UI.
+                    synchronized (this) {
+                        // Our thread is stopped if the UI is not ready
+                        // or it has completed its work.
+                        while (!mReady || mPosition >= max) {
+                            if (mQuiting) {
+                                return;
+                            }
+                            try {
+                                wait();
+                            } catch (InterruptedException e) {
+                            }
+                        }
+
+                        // Now update the progress.  Note it is important that
+                        // we touch the progress bar with the lock held, so it
+                        // doesn't disappear on us.
+                        mPosition++;
+                        max = mProgressBar.getMax();
+                        mProgressBar.setProgress(mPosition);
+                    }
+
+                    // Normally we would be doing some work, but put a kludge
+                    // here to pretend like we are.
+                    synchronized (this) {
+                        try {
+                            wait(50);
+                        } catch (InterruptedException e) {
+                        }
+                    }
+                }
+            }
+        };
+
+        /**
+         * Fragment initialization.  We way we want to be retained and
+         * start our thread.
+         */
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+
+            // Tell the framework to try to keep this fragment around
+            // during a configuration change.
+            setRetainInstance(true);
+
+            // Start up the worker thread.
+            mThread.start();
+        }
+
+        /**
+         * This is called when the Fragment's Activity is ready to go, after
+         * its content view has been installed; it is called both after
+         * the initial fragment creation and after the fragment is re-attached
+         * to a new activity.
+         */
+        @Override
+        public void onActivityCreated(Bundle savedInstanceState) {
+            super.onActivityCreated(savedInstanceState);
+
+            // Retrieve the progress bar from the target's view hierarchy.
+            mProgressBar = (ProgressBar)getTargetFragment().getView().findViewById(
+                    R.id.progress_horizontal);
+
+            // We are ready for our thread to go.
+            synchronized (mThread) {
+                mReady = true;
+                mThread.notify();
+            }
+        }
+
+        /**
+         * This is called when the fragment is going away.  It is NOT called
+         * when the fragment is being propagated between activity instances.
+         */
+        @Override
+        public void onDestroy() {
+            // Make the thread go away.
+            synchronized (mThread) {
+                mReady = false;
+                mQuiting = true;
+                mThread.notify();
+            }
+
+            super.onDestroy();
+        }
+
+        /**
+         * This is called right before the fragment is detached from its
+         * current activity instance.
+         */
+        @Override
+        public void onDetach() {
+            // This fragment is being detached from its activity.  We need
+            // to make sure its thread is not going to touch any activity
+            // state after returning from this function.
+            synchronized (mThread) {
+                mProgressBar = null;
+                mReady = false;
+                mThread.notify();
+            }
+
+            super.onDetach();
+        }
+
+        /**
+         * API for our UI to restart the progress thread.
+         */
+        public void restart() {
+            synchronized (mThread) {
+                mPosition = 0;
+                mThread.notify();
+            }
+        }
+    }
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/FragmentStack.java b/samples/ApiDemos/src/com/example/android/apis/app/FragmentStack.java
index 000cfa5..891eda4 100644
--- a/samples/ApiDemos/src/com/example/android/apis/app/FragmentStack.java
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentStack.java
@@ -103,7 +103,7 @@
         @Override
         public void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
-            mNum = getArguments().getInt("num");
+            mNum = getArguments() != null ? getArguments().getInt("num") : 1;
         }
 
         /**
diff --git a/samples/ApiDemos/src/com/example/android/apis/app/FragmentStackSupport.java b/samples/ApiDemos/src/com/example/android/apis/app/FragmentStackSupport.java
new file mode 100644
index 0000000..9cc2e04
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/app/FragmentStackSupport.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.app;
+
+import com.example.android.apis.R;
+
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentTransaction;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+
+public class FragmentStackSupport extends FragmentActivity {
+    int mStackLevel = 1;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.fragment_stack);
+
+        // Watch for button clicks.
+        Button button = (Button)findViewById(R.id.new_fragment);
+        button.setOnClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                addFragmentToStack();
+            }
+        });
+
+        if (savedInstanceState == null) {
+            // Do first time initialization -- add initial fragment.
+            Fragment newFragment = CountingFragment.newInstance(mStackLevel);
+            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+            ft.add(R.id.simple_fragment, newFragment).commit();
+        } else {
+            mStackLevel = savedInstanceState.getInt("level");
+        }
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putInt("level", mStackLevel);
+    }
+
+//BEGIN_INCLUDE(add_stack)
+    void addFragmentToStack() {
+        mStackLevel++;
+
+        // Instantiate a new fragment.
+        Fragment newFragment = CountingFragment.newInstance(mStackLevel);
+
+        // Add the fragment to the activity, pushing this transaction
+        // on to the back stack.
+        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+        ft.replace(R.id.simple_fragment, newFragment);
+        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
+        ft.addToBackStack(null);
+        ft.commit();
+    }
+//END_INCLUDE(add_stack)
+
+//BEGIN_INCLUDE(fragment)
+    public static class CountingFragment extends Fragment {
+        int mNum;
+
+        /**
+         * Create a new instance of CountingFragment, providing "num"
+         * as an argument.
+         */
+        static CountingFragment newInstance(int num) {
+            CountingFragment f = new CountingFragment();
+
+            // Supply num input as an argument.
+            Bundle args = new Bundle();
+            args.putInt("num", num);
+            f.setArguments(args);
+
+            return f;
+        }
+
+        /**
+         * When creating, retrieve this instance's number from its arguments.
+         */
+        @Override
+        public void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+            mNum = getArguments() != null ? getArguments().getInt("num") : 1;
+        }
+
+        /**
+         * The Fragment's UI is just a simple text view showing its
+         * instance number.
+         */
+        @Override
+        public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                Bundle savedInstanceState) {
+            View v = inflater.inflate(R.layout.hello_world, container, false);
+            View tv = v.findViewById(R.id.text);
+            ((TextView)tv).setText("Fragment #" + mNum);
+            tv.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.gallery_thumb));
+            return v;
+        }
+    }
+//END_INCLUDE(fragment)
+}
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/CheckableFrameLayout.java b/samples/ApiDemos/src/com/example/android/apis/view/CheckableFrameLayout.java
new file mode 100644
index 0000000..ecb222f
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/CheckableFrameLayout.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.apis.view;
+
+import android.content.Context;
+import android.graphics.drawable.ColorDrawable;
+import android.util.AttributeSet;
+import android.widget.Checkable;
+import android.widget.FrameLayout;
+
+public class CheckableFrameLayout extends FrameLayout implements Checkable {
+    private boolean mChecked;
+
+    public CheckableFrameLayout(Context context) {
+        super(context);
+    }
+
+    public CheckableFrameLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public void setChecked(boolean checked) {
+        mChecked = checked;
+        setBackgroundDrawable(checked ? new ColorDrawable(0xff0000a0) : null);
+    }
+
+    public boolean isChecked() {
+        return mChecked;
+    }
+
+    public void toggle() {
+        setChecked(!mChecked);
+    }
+
+}