OSDN Git Service

Some cleanup of fragment API demos:
authorDianne Hackborn <hackbod@google.com>
Tue, 4 Jan 2011 19:35:55 +0000 (11:35 -0800)
committerDianne Hackborn <hackbod@google.com>
Tue, 4 Jan 2011 19:39:22 +0000 (11:39 -0800)
- Rename FragmentAnim to FragmentHideShow, and tweak it to look
  less stupid.
- Reworking FragmentLayout to better represent a typical way to
  use fragments.
- Tweak various UI elements.

Change-Id: I3f4861c33bafafd27108fe0e4193e0ac7711f69e

14 files changed:
samples/ApiDemos/AndroidManifest.xml
samples/ApiDemos/res/layout-land/fragment_layout.xml
samples/ApiDemos/res/layout/fragment_context_menu.xml
samples/ApiDemos/res/layout/fragment_dialog.xml
samples/ApiDemos/res/layout/fragment_dialog_or_activity.xml
samples/ApiDemos/res/layout/fragment_hide_show.xml [moved from samples/ApiDemos/res/layout/fragment_anim.xml with 78% similarity]
samples/ApiDemos/res/layout/fragment_menu.xml
samples/ApiDemos/res/layout/fragment_retain_instance.xml
samples/ApiDemos/res/layout/hello_world.xml
samples/ApiDemos/res/layout/receive_result.xml
samples/ApiDemos/res/values/strings.xml
samples/ApiDemos/src/com/example/android/apis/app/FragmentHideShow.java [moved from samples/ApiDemos/src/com/example/android/apis/app/FragmentAnim.java with 83% similarity]
samples/ApiDemos/src/com/example/android/apis/app/FragmentLayout.java
samples/ApiDemos/src/com/example/android/apis/app/FragmentStack.java

index 21a85e0..d73fa39 100644 (file)
             </intent-filter>
         </activity>
 
-        <activity android:name=".app.SendResult">
+        <activity android:name=".app.SendResult"
+                android:theme="@android:style/Theme.Holo.DialogWhenLarge">
         </activity>
 
         <activity android:name=".app.Forwarding" android:label="@string/activity_forwarding">
             </intent-filter>
         </activity>
 
-        <activity android:name=".app.FragmentAnim"
-                android:label="@string/fragment_anim">
+        <activity android:name=".app.FragmentHideShow"
+                android:label="@string/fragment_hide_show"
+                android:windowSoftInputMode="stateUnchanged">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.SAMPLE_CODE" />
index 5c512f0..a057bf8 100644 (file)
@@ -26,8 +26,7 @@
             android:id="@+id/titles" android:layout_weight="1"
             android:layout_width="0px" android:layout_height="match_parent" />
 
-    <fragment class="com.example.android.apis.app.FragmentLayout$DetailsFragment"
-            android:id="@+id/details" android:layout_weight="1"
+    <FrameLayout android:id="@+id/details" android:layout_weight="1"
             android:layout_width="0px" android:layout_height="match_parent" />
     
 </LinearLayout>
index 8f2c044..b5dac8e 100644 (file)
@@ -24,6 +24,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
+        android:textAppearance="?android:attr/textAppearanceMedium"
         android:text="@string/fragment_context_menu_msg" />
 
     <Button android:id="@+id/long_press"
index e03f64f..f9dec59 100644 (file)
@@ -27,6 +27,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="1"
             android:layout_gravity="center_vertical|center_horizontal"
+            android:textAppearance="?android:attr/textAppearanceMedium"
             android:gravity="top|center_horizontal" />
 
     <Button android:id="@+id/show"
index eb95e14..295f017 100644 (file)
@@ -28,6 +28,7 @@
             android:layout_weight="0"
             android:layout_gravity="center_vertical|center_horizontal"
             android:gravity="top|center_horizontal"
+            android:textAppearance="?android:attr/textAppearanceMedium"
             android:text="@string/fragment_dialog_or_activity_msg" />
 
     <Button android:id="@+id/show_dialog"
@@ -47,6 +48,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="0"
             android:layout_gravity="center_vertical|center_horizontal"
+            android:textAppearance="?android:attr/textAppearanceMedium"
             android:text="@string/fragment_dialog_or_activity_inline" />
 
     <FrameLayout
@@ -4,9 +4,9 @@
      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.
     android:gravity="center_horizontal"
     android:layout_width="match_parent" android:layout_height="match_parent">
 
+    <TextView android:layout_width="match_parent" android:layout_height="wrap_content"
+        android:gravity="center_vertical|center_horizontal"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:text="Demonstration of hiding and showing fragments." />
+
     <LinearLayout android:orientation="horizontal" android:padding="4dip"
         android:gravity="center_vertical" android:layout_weight="1"
-        android:layout_width="wrap_content" android:layout_height="wrap_content">
+        android:layout_width="match_parent" android:layout_height="wrap_content">
+
+        <Button android:id="@+id/frag1hide"
+            android:layout_width="wrap_content" android:layout_height="wrap_content"
+            android:text="Hide" />
 
-        <fragment android:name="com.example.android.apis.app.FragmentAnim$FirstFragment"
+        <fragment android:name="com.example.android.apis.app.FragmentHideShow$FirstFragment"
                 android:id="@+id/fragment1" android:layout_weight="1"
                 android:layout_width="0px" android:layout_height="wrap_content" />
 
-        <Button android:id="@+id/frag1hide"
-            android:layout_width="wrap_content" android:layout_height="wrap_content"
-            android:text="Hide">
-        </Button>
-    
     </LinearLayout>
-    
+
     <LinearLayout android:orientation="horizontal" android:padding="4dip"
         android:gravity="center_vertical" android:layout_weight="1"
-        android:layout_width="wrap_content" android:layout_height="wrap_content">
+        android:layout_width="match_parent" android:layout_height="wrap_content">
+
+        <Button android:id="@+id/frag2hide"
+            android:layout_width="wrap_content" android:layout_height="wrap_content"
+            android:text="Hide" />
 
-        <fragment android:name="com.example.android.apis.app.FragmentAnim$SecondFragment"
+        <fragment android:name="com.example.android.apis.app.FragmentHideShow$SecondFragment"
                 android:id="@+id/fragment2" android:layout_weight="1"
                 android:layout_width="0px" android:layout_height="wrap_content" />
 
-        <Button android:id="@+id/frag2hide"
-            android:layout_width="wrap_content" android:layout_height="wrap_content"
-            android:text="Hide">
-        </Button>
-    
     </LinearLayout>
-    
+
 </LinearLayout>
index b2d3c52..7f0278c 100644 (file)
@@ -24,6 +24,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
+        android:textAppearance="?android:attr/textAppearanceMedium"
         android:text="@string/fragment_menu_msg" />
 
     <CheckBox android:id="@+id/menu1"
index e9a9a43..0dc3985 100644 (file)
@@ -24,6 +24,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
+        android:textAppearance="?android:attr/textAppearanceMedium"
         android:text="@string/fragment_retain_instance_msg" />
 
     <ProgressBar android:id="@+id/progress_horizontal"
index 0282076..3d90a33 100644 (file)
@@ -22,4 +22,5 @@
 <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text"
     android:layout_width="match_parent" android:layout_height="match_parent"
     android:gravity="center_vertical|center_horizontal"
+    android:textAppearance="?android:attr/textAppearanceMedium"
     android:text="@string/hello_world"/>
index a894612..5deb2ac 100644 (file)
         android:layout_width="match_parent" android:layout_height="wrap_content"
         android:layout_weight="0"
         android:paddingBottom="4dip"
+        android:textAppearance="?android:attr/textAppearanceMedium"
         android:text="@string/receive_result_instructions"/>
 
     <TextView android:id="@+id/results"
         android:layout_width="match_parent" android:layout_height="10dip"
         android:layout_weight="1"
         android:paddingBottom="4dip"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:textColor="#000"
         android:background="@drawable/green">
     </TextView>
 
index 766830d..ae041a6 100644 (file)
 
     <string name="fragment_alert_dialog">App/Fragment/Alert Dialog</string>
 
-    <string name="fragment_anim">App/Fragment/Anim</string>
+    <string name="fragment_hide_show">App/Fragment/Hide and Show</string>
 
     <string name="fragment_context_menu">App/Fragment/Context Menu</string>
     <string name="fragment_context_menu_msg">Fragment populating a context
@@ -20,45 +20,46 @@ import com.example.android.apis.R;
 
 import android.app.Activity;
 import android.app.Fragment;
+import android.app.FragmentManager;
 import android.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.view.animation.AnimationUtils;
 import android.widget.Button;
 import android.widget.TextView;
 
 /**
- * Demonstration of animations when changing fragment states.
+ * Demonstration of hiding and showing fragments.
  */
-public class FragmentAnim extends Activity {
+public class FragmentHideShow extends Activity {
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        setContentView(R.layout.fragment_anim);
+        setContentView(R.layout.fragment_hide_show);
 
-        addShowHideListener(R.id.frag1hide, findFragmentById(R.id.fragment1));
-        addShowHideListener(R.id.frag2hide, findFragmentById(R.id.fragment2));
+        // The content view embeds two fragments; now retrieve them and attach
+        // their "hide" button.
+        FragmentManager fm = getFragmentManager();
+        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 = openFragmentTransaction();
+                FragmentTransaction ft = getFragmentManager().openTransaction();
                 ft.setCustomAnimations(android.R.anim.animator_fade_in,
                         android.R.anim.animator_fade_out);
                 if (fragment.isHidden()) {
-                    button.setAnimation(AnimationUtils.loadAnimation(
-                            FragmentAnim.this, android.R.anim.slide_in_left));
                     ft.show(fragment);
+                    button.setText("Hide");
                 } else {
-                    button.setAnimation(AnimationUtils.loadAnimation(
-                            FragmentAnim.this, android.R.anim.slide_out_right));
                     ft.hide(fragment);
+                    button.setText("Show");
                 }
                 ft.commit();
             }
index a63685e..f959d00 100644 (file)
@@ -21,11 +21,11 @@ import com.example.android.apis.Shakespeare;
 
 import android.app.Activity;
 import android.app.Fragment;
+import android.app.FragmentTransaction;
 import android.app.ListFragment;
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.os.Bundle;
-import android.util.Log;
 import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -73,17 +73,23 @@ public class FragmentLayout extends Activity {
             if (savedInstanceState == null) {
                 // During initial setup, plug in the details fragment.
                 DetailsFragment details = new DetailsFragment();
+                details.setArguments(getIntent().getExtras());
                 getFragmentManager().openTransaction().add(android.R.id.content, details).commit();
-                details.setText(getIntent().getIntExtra("text", -1));
             }
         }
     }
 //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 {
-        DetailsFragment mDetails;
+        boolean mDualPane;
         int mCurCheckPosition = 0;
+        int mShownCheckPosition = -1;
 
         @Override
         public void onActivityCreated(Bundle savedInstanceState) {
@@ -93,17 +99,22 @@ public class FragmentLayout extends Activity {
             setListAdapter(new ArrayAdapter<String>(getActivity(),
                     android.R.layout.simple_list_item_activated_1, Shakespeare.TITLES));
 
-            // Restore last state for checked position.
+            // 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);
+                mShownCheckPosition = savedInstanceState.getInt("shownChoice", -1);
             }
 
-            // If we are showing details in the screen, set up the list to highlight.
-            mDetails = (DetailsFragment)getFragmentManager().findFragmentById(R.id.details);
-            if (mDetails != null && mDetails.isInLayout()) {
+            if (mDualPane) {
+                // In dual-pane mode, the list view highlights the selected item.
                 getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
-                getListView().setItemChecked(mCurCheckPosition, true);
-                mDetails.setText(mCurCheckPosition);
+                // Make sure our UI is in the correct state.
+                showDetails(mCurCheckPosition);
             }
         }
 
@@ -111,67 +122,97 @@ public class FragmentLayout extends Activity {
         public void onSaveInstanceState(Bundle outState) {
             super.onSaveInstanceState(outState);
             outState.putInt("curChoice", mCurCheckPosition);
+            outState.putInt("shownChoice", mShownCheckPosition);
         }
 
         @Override
         public void onListItemClick(ListView l, View v, int position, long id) {
-            mCurCheckPosition = position;
+            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);
+
+                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);
+
+                    // Execute a transaction, replacing any existing fragment
+                    // with this one inside the frame.
+                    FragmentTransaction ft = getFragmentManager().openTransaction();
+                    ft.replace(R.id.details, df);
+                    ft.setTransition(index > mCurCheckPosition
+                            ? FragmentTransaction.TRANSIT_FRAGMENT_NEXT
+                            : FragmentTransaction.TRANSIT_FRAGMENT_PREV);
+                    ft.commit();
+                    mShownCheckPosition = index;
+                }
 
-            if (mDetails != null && mDetails.isVisible()) {
-                // If the activity has a fragment to display the dialog,
-                // point it to what the user has selected.
-                mDetails.setText(position);
-                getListView().setItemChecked(position, true);
             } 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("text", position);
+                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 {
-        int mDisplayedText = -1;
-        TextView mText;
-
-        public void setText(int id) {
-            mDisplayedText = id;
-            if (mText != null && id >= 0) {
-                mText.setText(Shakespeare.DIALOGUE[id]);
-            }
-        }
-
-        @Override
-        public void onCreate(Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            if (savedInstanceState != null) {
-                mDisplayedText = savedInstanceState.getInt("text", -1);
-            }
-        }
-
-        @Override
-        public void onSaveInstanceState(Bundle outState) {
-            super.onSaveInstanceState(outState);
-            outState.putInt("text", mDisplayedText);
+        /**
+         * 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;
         }
 
         @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());
-            mText = new TextView(getActivity());
+            TextView text = new TextView(getActivity());
             int padding = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                     4, getActivity().getResources().getDisplayMetrics());
-            mText.setPadding(padding, padding, padding, padding);
-            scroller.addView(mText);
-            if (mDisplayedText >= 0) {
-                mText.setText(Shakespeare.DIALOGUE[mDisplayedText]);
-            }
+            text.setPadding(padding, padding, padding, padding);
+            scroller.addView(text);
+            text.setText(Shakespeare.DIALOGUE[getArguments().getInt("index", 0)]);
             return scroller;
         }
     }
index 2aa9a12..6710a2d 100644 (file)
@@ -116,6 +116,7 @@ public class FragmentStack extends Activity {
             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;
         }
     }