基本知识
Fragment可以弥补activity的使用局限:即不能将多个activity界面在一个屏幕上同时显示
Fragment支持在不同的Activity中使用并且可以处理自己的输入事件以及生命周期方法等。可以看做是一个子Activity
Fragment的生命周期方法依赖于Activity的生命周期,例如一个Activity的onPause()的生命周期方法被调用的时候这个Activity中的所有的Fragment的onPause()方法也将被调用。
支持包
3.0以下、1.6及以上版本:
导入android.support.v4.*;
添加SDK下的jar到libs文件夹(/extras/android/support/v4/android-support-v4.jar)
使用Fragment的Activity请继承FragmentActivity而不是Activity
3.0或以上版本:
直接继承Activity
创建含Fragment的Activity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment_main);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
}
其中R.id.container来自R.layout.activity_fragment_main
<FrameLayout
...
android:id="@+id/container"
...
tools:ignore="MergeRootFrame" />
在此Activity没有东西,在layout中设置MergeRootFrame,因此不会显示父Activity
创建Activity后,经过if (savedInstanceState == null)判断是否首次启动,第一个界面直接跳转到一个Fragment。
创建自己的Fragment
public static class MyFragment extends Fragment {
public MyFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.myfragment_main,
container, false);
return rootView;
}
}
添加Fragment到Activity
①直接将上面的代码放在Activity中
②在外部单独一个java文件写好,然后在Activity的layout中添加
其中android:name属性填上自己创建的fragment的完整类名
layout_weight的目的是划分屏幕宽度的权重
看到没?一个是fragment,一个是FrameLayout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<fragment
android:id="@+id/titles"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
class="com.example.myfragment.TitlesFragment" />
<FrameLayout
android:id="@+id/details"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
切换Fragment来显示
FragmentTransaction ft=getFragmentManager().beginTransaction(); ft.replace(R.id.container, new MyFragment());//替换Fragment。如果继续add,则会出现photoshop的层效果 ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);//简单动画 ft.addToBackStack(null); ft.commit();
需要说明的是,如果想按后退键能返回上一个Fragment,则需要addToBackStack();否则不需要这行代码。
Fragment里有setArguments方法传递extras
Activity和Fragment之间的通信
①在Fragment中定义一个接口
②在这个接口中定义一个方法
③在Fragment的onAttach()方法中调用这个接口中的方法
④让Activity实现这个方法来完成Activity和Fragment之间的通信
更简单的方法是在Fragment中使用getActivity()
一个简单的例子
①新建一个Activity
②修改其layout文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:baselineAligned="false"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="@+id/titles"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
class="com.example.play.TitlesFragment" />
<FrameLayout
android:id="@+id/details"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
</LinearLayout>
其中fragment中的TitlesFragment在启动的时候就自己create,FrameLayout在后面代码中放置新的Fragment
③创建TitlesFragment
package com.example.play;
import android.app.ListFragment;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class TitlesFragment extends ListFragment {
private String[] mString = { "0", "1", "2" };
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
Log.i("FragmentList", "Item clicked: " + id);
DetailsFragment detailsFragment = (DetailsFragment) getActivity()
.getFragmentManager().findFragmentById(R.id.details);
detailsFragment = DetailsFragment.newInstance(position);
getActivity().getFragmentManager().beginTransaction()
.replace(R.id.details, detailsFragment).commit();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayAdapter arrayAdapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, mString);
setListAdapter(arrayAdapter);
}
}
④创建DetailsFragment
package com.example.play;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class DetailsFragment extends Fragment {
private static int mIndex;
//Fragment一定要有构造函数,要setArguments
public static DetailsFragment newInstance(int index) {
Log.d("FragmentList", "DetailsFragment newInstance");
mIndex = index;
DetailsFragment details = new DetailsFragment();
Bundle args = new Bundle();
args.putInt("index", index);
details.setArguments(args);
Log.d("FragmentList", "index :"
+ details.getArguments().getInt("index"));
return details;
}
//只要返回view就可以了,layout里的<FrameLayout>是这个view的载体
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
Log.d("FragmentList", "DetailsFragment onCreateView");
if (container == null)
return null;
TextView tv = new TextView(getActivity());
tv.setText("details: " + mIndex);
return tv;
}
}