Some cleanup of fragment API demos:

- 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
This commit is contained in:
Dianne Hackborn
2011-01-04 11:35:55 -08:00
parent d7394da1a0
commit 9d247ad58b
14 changed files with 136 additions and 79 deletions

View File

@@ -174,7 +174,8 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".app.SendResult"> <activity android:name=".app.SendResult"
android:theme="@android:style/Theme.Holo.DialogWhenLarge">
</activity> </activity>
<activity android:name=".app.Forwarding" android:label="@string/activity_forwarding"> <activity android:name=".app.Forwarding" android:label="@string/activity_forwarding">
@@ -250,8 +251,9 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".app.FragmentAnim" <activity android:name=".app.FragmentHideShow"
android:label="@string/fragment_anim"> android:label="@string/fragment_hide_show"
android:windowSoftInputMode="stateUnchanged">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.SAMPLE_CODE" /> <category android:name="android.intent.category.SAMPLE_CODE" />

View File

@@ -26,8 +26,7 @@
android:id="@+id/titles" android:layout_weight="1" android:id="@+id/titles" android:layout_weight="1"
android:layout_width="0px" android:layout_height="match_parent" /> android:layout_width="0px" android:layout_height="match_parent" />
<fragment class="com.example.android.apis.app.FragmentLayout$DetailsFragment" <FrameLayout android:id="@+id/details" android:layout_weight="1"
android:id="@+id/details" android:layout_weight="1"
android:layout_width="0px" android:layout_height="match_parent" /> android:layout_width="0px" android:layout_height="match_parent" />
</LinearLayout> </LinearLayout>

View File

@@ -24,6 +24,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/fragment_context_menu_msg" /> android:text="@string/fragment_context_menu_msg" />
<Button android:id="@+id/long_press" <Button android:id="@+id/long_press"

View File

@@ -27,6 +27,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:layout_gravity="center_vertical|center_horizontal" android:layout_gravity="center_vertical|center_horizontal"
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="top|center_horizontal" /> android:gravity="top|center_horizontal" />
<Button android:id="@+id/show" <Button android:id="@+id/show"

View File

@@ -28,6 +28,7 @@
android:layout_weight="0" android:layout_weight="0"
android:layout_gravity="center_vertical|center_horizontal" android:layout_gravity="center_vertical|center_horizontal"
android:gravity="top|center_horizontal" android:gravity="top|center_horizontal"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/fragment_dialog_or_activity_msg" /> android:text="@string/fragment_dialog_or_activity_msg" />
<Button android:id="@+id/show_dialog" <Button android:id="@+id/show_dialog"
@@ -47,6 +48,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="0" android:layout_weight="0"
android:layout_gravity="center_vertical|center_horizontal" android:layout_gravity="center_vertical|center_horizontal"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/fragment_dialog_or_activity_inline" /> android:text="@string/fragment_dialog_or_activity_inline" />
<FrameLayout <FrameLayout

View File

@@ -4,9 +4,9 @@
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -21,34 +21,37 @@
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:layout_width="match_parent" android:layout_height="match_parent"> 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" <LinearLayout android:orientation="horizontal" android:padding="4dip"
android:gravity="center_vertical" android:layout_weight="1" 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">
<fragment android:name="com.example.android.apis.app.FragmentAnim$FirstFragment"
android:id="@+id/fragment1" android:layout_weight="1"
android:layout_width="0px" android:layout_height="wrap_content" />
<Button android:id="@+id/frag1hide" <Button android:id="@+id/frag1hide"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="Hide"> android:text="Hide" />
</Button>
<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" />
</LinearLayout> </LinearLayout>
<LinearLayout android:orientation="horizontal" android:padding="4dip" <LinearLayout android:orientation="horizontal" android:padding="4dip"
android:gravity="center_vertical" android:layout_weight="1" 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">
<fragment android:name="com.example.android.apis.app.FragmentAnim$SecondFragment"
android:id="@+id/fragment2" android:layout_weight="1"
android:layout_width="0px" android:layout_height="wrap_content" />
<Button android:id="@+id/frag2hide" <Button android:id="@+id/frag2hide"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="Hide"> android:text="Hide" />
</Button>
<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" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@@ -24,6 +24,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/fragment_menu_msg" /> android:text="@string/fragment_menu_msg" />
<CheckBox android:id="@+id/menu1" <CheckBox android:id="@+id/menu1"

View File

@@ -24,6 +24,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/fragment_retain_instance_msg" /> android:text="@string/fragment_retain_instance_msg" />
<ProgressBar android:id="@+id/progress_horizontal" <ProgressBar android:id="@+id/progress_horizontal"

View File

@@ -22,4 +22,5 @@
<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text" <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:layout_width="match_parent" android:layout_height="match_parent"
android:gravity="center_vertical|center_horizontal" android:gravity="center_vertical|center_horizontal"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/hello_world"/> android:text="@string/hello_world"/>

View File

@@ -27,12 +27,15 @@
android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_weight="0" android:layout_weight="0"
android:paddingBottom="4dip" android:paddingBottom="4dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/receive_result_instructions"/> android:text="@string/receive_result_instructions"/>
<TextView android:id="@+id/results" <TextView android:id="@+id/results"
android:layout_width="match_parent" android:layout_height="10dip" android:layout_width="match_parent" android:layout_height="10dip"
android:layout_weight="1" android:layout_weight="1"
android:paddingBottom="4dip" android:paddingBottom="4dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#000"
android:background="@drawable/green"> android:background="@drawable/green">
</TextView> </TextView>

View File

@@ -108,7 +108,7 @@
<string name="fragment_alert_dialog">App/Fragment/Alert Dialog</string> <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">App/Fragment/Context Menu</string>
<string name="fragment_context_menu_msg">Fragment populating a context <string name="fragment_context_menu_msg">Fragment populating a context

View File

@@ -20,45 +20,46 @@ import com.example.android.apis.R;
import android.app.Activity; import android.app.Activity;
import android.app.Fragment; import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction; import android.app.FragmentTransaction;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.animation.AnimationUtils;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView; 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 @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_anim); setContentView(R.layout.fragment_hide_show);
addShowHideListener(R.id.frag1hide, findFragmentById(R.id.fragment1)); // The content view embeds two fragments; now retrieve them and attach
addShowHideListener(R.id.frag2hide, findFragmentById(R.id.fragment2)); // 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) { void addShowHideListener(int buttonId, final Fragment fragment) {
final Button button = (Button)findViewById(buttonId); final Button button = (Button)findViewById(buttonId);
button.setOnClickListener(new OnClickListener() { button.setOnClickListener(new OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
FragmentTransaction ft = openFragmentTransaction(); FragmentTransaction ft = getFragmentManager().openTransaction();
ft.setCustomAnimations(android.R.anim.animator_fade_in, ft.setCustomAnimations(android.R.anim.animator_fade_in,
android.R.anim.animator_fade_out); android.R.anim.animator_fade_out);
if (fragment.isHidden()) { if (fragment.isHidden()) {
button.setAnimation(AnimationUtils.loadAnimation(
FragmentAnim.this, android.R.anim.slide_in_left));
ft.show(fragment); ft.show(fragment);
button.setText("Hide");
} else { } else {
button.setAnimation(AnimationUtils.loadAnimation(
FragmentAnim.this, android.R.anim.slide_out_right));
ft.hide(fragment); ft.hide(fragment);
button.setText("Show");
} }
ft.commit(); ft.commit();
} }

View File

@@ -21,11 +21,11 @@ import com.example.android.apis.Shakespeare;
import android.app.Activity; import android.app.Activity;
import android.app.Fragment; import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.ListFragment; import android.app.ListFragment;
import android.content.Intent; import android.content.Intent;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@@ -73,17 +73,23 @@ public class FragmentLayout extends Activity {
if (savedInstanceState == null) { if (savedInstanceState == null) {
// During initial setup, plug in the details fragment. // During initial setup, plug in the details fragment.
DetailsFragment details = new DetailsFragment(); DetailsFragment details = new DetailsFragment();
details.setArguments(getIntent().getExtras());
getFragmentManager().openTransaction().add(android.R.id.content, details).commit(); getFragmentManager().openTransaction().add(android.R.id.content, details).commit();
details.setText(getIntent().getIntExtra("text", -1));
} }
} }
} }
//END_INCLUDE(details_activity) //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) //BEGIN_INCLUDE(titles)
public static class TitlesFragment extends ListFragment { public static class TitlesFragment extends ListFragment {
DetailsFragment mDetails; boolean mDualPane;
int mCurCheckPosition = 0; int mCurCheckPosition = 0;
int mShownCheckPosition = -1;
@Override @Override
public void onActivityCreated(Bundle savedInstanceState) { public void onActivityCreated(Bundle savedInstanceState) {
@@ -93,17 +99,22 @@ public class FragmentLayout extends Activity {
setListAdapter(new ArrayAdapter<String>(getActivity(), setListAdapter(new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_activated_1, Shakespeare.TITLES)); 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) { if (savedInstanceState != null) {
// Restore last state for checked position.
mCurCheckPosition = savedInstanceState.getInt("curChoice", 0); mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
mShownCheckPosition = savedInstanceState.getInt("shownChoice", -1);
} }
// If we are showing details in the screen, set up the list to highlight. if (mDualPane) {
mDetails = (DetailsFragment)getFragmentManager().findFragmentById(R.id.details); // In dual-pane mode, the list view highlights the selected item.
if (mDetails != null && mDetails.isInLayout()) {
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
getListView().setItemChecked(mCurCheckPosition, true); // Make sure our UI is in the correct state.
mDetails.setText(mCurCheckPosition); showDetails(mCurCheckPosition);
} }
} }
@@ -111,67 +122,97 @@ public class FragmentLayout extends Activity {
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
outState.putInt("curChoice", mCurCheckPosition); outState.putInt("curChoice", mCurCheckPosition);
outState.putInt("shownChoice", mShownCheckPosition);
} }
@Override @Override
public void onListItemClick(ListView l, View v, int position, long id) { 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 { } else {
// Otherwise we need to launch a new activity to display // Otherwise we need to launch a new activity to display
// the dialog fragment with selected text. // the dialog fragment with selected text.
Intent intent = new Intent(); Intent intent = new Intent();
intent.setClass(getActivity(), DetailsActivity.class); intent.setClass(getActivity(), DetailsActivity.class);
intent.putExtra("text", position); intent.putExtra("index", index);
startActivity(intent); startActivity(intent);
} }
} }
} }
//END_INCLUDE(titles) //END_INCLUDE(titles)
/**
* This is the secondary fragment, displaying the details of a particular
* item.
*/
//BEGIN_INCLUDE(details) //BEGIN_INCLUDE(details)
public static class DetailsFragment extends Fragment { public static class DetailsFragment extends Fragment {
int mDisplayedText = -1; /**
TextView mText; * Create a new instance of DetailsFragment, initialized to
* show the text at 'index'.
*/
public static DetailsFragment newInstance(int index) {
DetailsFragment f = new DetailsFragment();
public void setText(int id) { // Supply index input as an argument.
mDisplayedText = id; Bundle args = new Bundle();
if (mText != null && id >= 0) { args.putInt("index", index);
mText.setText(Shakespeare.DIALOGUE[id]); f.setArguments(args);
}
}
@Override return f;
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);
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { 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()); ScrollView scroller = new ScrollView(getActivity());
mText = new TextView(getActivity()); TextView text = new TextView(getActivity());
int padding = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, int padding = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
4, getActivity().getResources().getDisplayMetrics()); 4, getActivity().getResources().getDisplayMetrics());
mText.setPadding(padding, padding, padding, padding); text.setPadding(padding, padding, padding, padding);
scroller.addView(mText); scroller.addView(text);
if (mDisplayedText >= 0) { text.setText(Shakespeare.DIALOGUE[getArguments().getInt("index", 0)]);
mText.setText(Shakespeare.DIALOGUE[mDisplayedText]);
}
return scroller; return scroller;
} }
} }

View File

@@ -116,6 +116,7 @@ public class FragmentStack extends Activity {
View v = inflater.inflate(R.layout.hello_world, container, false); View v = inflater.inflate(R.layout.hello_world, container, false);
View tv = v.findViewById(R.id.text); View tv = v.findViewById(R.id.text);
((TextView)tv).setText("Fragment #" + mNum); ((TextView)tv).setText("Fragment #" + mNum);
tv.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.gallery_thumb));
return v; return v;
} }
} }