Fragment(三)例子
转载请注明:http://blog.csdn.net/liaoqianchuan00/article/details/24271579
翻译自http://developer.android.com/guide/components/fragments.html
例子
这里有一个例子用到了连个Fragment。一个Fragment用来显示莎士比亚剧的名字,另外一个显示这个剧的简介。这个例子也演示了怎么根据不同的屏幕来创建不同的layout。
Main Activity用平常的方式在onCreate中设置了layout:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_layout);
}
下面是我们用到的fragment_layout.xml
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"android:layout_height="match_parent">
<fragmentclass="com.example.android.apis.app.FragmentLayout$TitlesFragment"
android:id="@+id/titles"android:layout_weight="1"
android:layout_width="0px" android:layout_height="match_parent"/>
<FrameLayout android:id="@+id/details"android:layout_weight="1"
android:layout_width="0px"android:layout_height="match_parent"
android:background="?android:attr/detailsElementBackground" />
</LinearLayout>
使用这个layout,系统会在Activity读取Layout的时候实例化TitleFragment(显示剧目列表),而右边的FrameLayout则先保持为空。在用户从剧目列表中选择一个剧目之前,显示剧目信息的Fragment不会被放置到FrameLayout中去。
但是,并不是所有的屏幕都能同时显示这两个Fragment。所以,上面的layout只适用于宽屏模式,所以将他放置到res/layout-land/fragment_layout.xml.
因此,当在竖屏模式下的时候,系统使用res/layout/fragment_layout.xml下的文件:
<FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"android:layout_height="match_parent">
<fragment class="com.example.android.apis.app.FragmentLayout$TitlesFragment"
android:id="@+id/titles"
android:layout_width="match_parent"android:layout_height="match_parent" />
</FrameLayout>
这个Layout中只包含了TitlesFragment。这就意味着,在竖屏模式下,只会显示剧目列表。所以当用户点击其中一项的时候,应用程序会启动一个新的Activity来显示这个剧目的简介,而不是加载一个Fragment进来。
接下来你会看到我们是怎么来实现这些Fragment的。首先是TitlesFragment,用来显示莎士比亚剧目列表。这个Fragment继承自ListFragment,通过它来处理很多List View的工作。
像你看到的,当用户点击列表中的一项的时候,有两种可能得处理方式,可能是创建和显示一个新的Fragment(添加Fragment到FrameLayout中去),或者是启动一个新的Activity(新的Fragment会在这里面显示)。
public static class TitlesFragment extendsListFragment {
boolean mDualPane;
int mCurCheckPosition = 0;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Populate list with our static array of titles.
setListAdapter(newArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_activated_1, Shakespeare.TITLES));
// Check to see if we have a frame in which toembed 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 checkedposition.
mCurCheckPosition =savedInstanceState.getInt("curChoice", 0);
}
if (mDualPane) {
// In dual-pane mode, the list viewhighlights the selected item.
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
// Make sure our UI is in the correctstate.
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, orstarting a
* whole new activity in which it is displayed.
*/
void showDetails(int index) {
mCurCheckPosition = index;
if (mDualPane) {
// We can display everything in-placewith fragments, so update
// the list to highlight the selecteditem and show the data.
getListView().setItemChecked(index,true);
// Check what fragment is currentlyshown, replace if needed.
DetailsFragment details =(DetailsFragment)
getFragmentManager().findFragmentById(R.id.details);
if (details == null ||details.getShownIndex() != index) {
// Make new fragment toshow this selection.
details =DetailsFragment.newInstance(index);
// Execute atransaction, replacing any existing fragment
// with this one insidethe frame.
FragmentTransaction ft= getFragmentManager().beginTransaction();
if (index == 0) {
ft.replace(R.id.details, details);
} else {
ft.replace(R.id.a_item, details);
}
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
} else {
// Otherwise we need to launch a newactivity to display
// the dialog fragment with selectedtext.
Intent intent = new Intent();
intent.setClass(getActivity(),DetailsActivity.class);
intent.putExtra("index",index);
startActivity(intent);
}
}
}
第二个Fragment显示了这个剧目的简介信息:
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, ViewGroupcontainer,
Bundle savedInstanceState) {
if (container == null) {
// We have different layouts, and inone of them this
// fragment's containing framedoesn't exist. The fragment
// may still be created from itssaved state, but there is
// no reason to try to create itsview hierarchy because it
// won't be displayed. Note thisis not needed -- we could
// just run the code below, where wewould create and return
// the view hierarchy; it would justnever 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;
}
}
回忆之前的TitlesFragment,当用户点击列表项的时候,如果layout中没有包含R.id.details视图(即DetailsFragment放置的ViewGroup),应用程序就会启动一个DetailsActivity Activity来显示剧目简介。
这里是DetailsActivity的代码,只是很简单的嵌入了一个DetailsFragment来显示剧目简介(竖屏情况下用到)。
public static class DetailsActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getResources().getConfiguration().orientation
==Configuration.ORIENTATION_LANDSCAPE) {
// If the screen is now in landscapemode, we can show the
// dialog in-line with the list so wedon't need this activity.
finish();
return;
}
if (savedInstanceState == null) {
// During initial setup, plug in thedetails fragment.
DetailsFragment details = newDetailsFragment();
details.setArguments(getIntent().getExtras());
getFragmentManager().beginTransaction().add(android.R.id.content,details).commit();
}
}
}
我们发现如果在横屏状态下这个Activity会自动Finish,这样main Activity就能显示DetailsFragment和TitlesFragment了。这会发生在用户在最开始的时候显示DetailsActivity的时候是竖屏的,但是后来切换到了横屏(会重新创建当前的Activity)。