一、简介
1.定义:碎片。API11(3.0)之后才出现的,低版本想要使用的话,需要继承FragmentActivity类。
2.生命周期:有自己独立的生命周期,但是依赖于Activity的生命周期。一旦所依赖的Activtiy被杀死,所有相关的Fragment都会被杀死。添加Fragment时的生命周期:onAttach()–>onCreate()–>onCreateView()–>onActivityCreated()–>onStart()–>onResume()。Fragment被移除销毁时的生命周期:onPause()–>onStop–>onDestroyView()–>onDestroy()–>onDetach()。切换Fragment时的生命周期:onPause()–>onStop–>onDestroyView()。
多个Fragment之间切换的生命周期如下:
第一个Fragment被加载
-----Fragment1->>onAttach
-----Fragment1->>onCreate
-----Fragment1->>onCreateView
-----Fragment1->>onActivityCreated
-----Fragment1->>onStart
-----Fragment1->>onResume
第二个Fragment进来
-----Fragment1->>onPause
-----Fragment1->>onStop
-----Fragment1->>onDestroyView
-----Fragment2->>onAttach
-----Fragment2->>onCreate
-----Fragment2->>onCreateView
-----Fragment2->>onActivityCreated
-----Fragment2->>onStart
-----Fragment2->>onResume
第三个Fragment进来
-----Fragment2->>onPause
-----Fragment2->>onStop
-----Fragment2->>onDestroyView
-----Fragment3->>onAttach
-----Fragment3->>onCreate
-----Fragment3->>onCreateView
-----Fragment3->>onActivityCreated
-----Fragment3->>onStart
-----Fragment3->>onResume
回退到第二个Fragment
-----Fragment3->>onPause
-----Fragment3->>onStop
-----Fragment3->>onDestroyView
-----Fragment2->>onCreateView
-----Fragment2->>onActivityCreated
-----Fragment2->>onStart
-----Fragment2->>onResume
3.相关方法与相关类
FragmentManager
getFragmentManager(),getSupportFragmentManager()
findFragmentByTag() , findFragmentById() [在xml文件中定义了frament标签的id]
beginTransaction()【开启一个事务,可以在事务一次add多个fragment,或者replace一个fragment】
FragmentTransaction
replace(),add(),addToBackStack()
remove()
commit()
transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out)【设置各种切换动画】
二、Fragment的使用场景
1.结合Activity使用
- Fragment可以在xml文件中用fragment标签添加在一个activity中,也可以在代码中add。
- 涉及到Activity与Fragment之间数据交互,Fragment之间数据交互。
2.结合ActionBar使用
3.结合ViewPager使用
- PagerAdapter
- FragmentPagerAdapter
- FragmentStatePagerAdapter
我们还可以通过ViewPager来管理Fragment,通过Adapter添加多个Fragment,然后通过setcurrentitem进行切换。我们同样可以通过setArguments向Fragment传递数据。
4.结合
5.ListFragment
6.DialogFragment
7.PreferenceFragment
三、示例代码
1.结合activity使用
数据传递:
①Activity向Fragment传递数据:setArgument()/getArgument();
②Fragment之间数据传递:
示例一:Activity向Fragment传递数据
一个Activity可以结合一个或者多个Fragment使用,如果显示的数据之间有共性,可以共用Fragment。
布局文件activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context=".MainActivity" >
<LinearLayout
android:id="@+id/left"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#CCCCCC"
android:orientation="vertical" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="男鞋" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="女鞋" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="男装" />
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="女装" />
</LinearLayout>
<FrameLayout
android:id="@+id/center"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" >
</FrameLayout>
</LinearLayout>
public class MainActivity extends Activity implements OnClickListener {
private FragmentManager manager;
private FragmentTransaction transaction;
private Button button1, button2, button3, button4;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
manager = getFragmentManager();
button1 = (Button) this.findViewById(R.id.button1);
button1.setOnClickListener(this);
button2 = (Button) this.findViewById(R.id.button2);
button2.setOnClickListener(this);
button3 = (Button) this.findViewById(R.id.button3);
button3.setOnClickListener(this);
button4 = (Button) this.findViewById(R.id.button4);
button4.setOnClickListener(this);
//默认自动触发一次
button1.performClick();
}
/**
* Fragment之间传递数据。
* @note 传递数据必须在add/replace之前。
* @note 如果展示的数据结构相同,使用同一个Fragment来接收不同的数据参数;否则可以新建多个Fragment
*/
@Override
public void onClick(View v) {
transaction = manager.beginTransaction();
Bundle bundle = new Bundle();
Fragment1 fragment1 = new Fragment1();
switch (v.getId()) {
case R.id.button1:
bundle.putString("category_id", "12");
break;
case R.id.button2:
bundle.putString("category_id", "13");
break;
case R.id.button3:
bundle.putString("category_id", "14");
break;
case R.id.button4:
bundle.putString("category_id", "15");
break;
}
transaction.replace(R.id.center, fragment1, "fragment1");
//transaction.addToBackStack("fragment1");// 添加到Activity管理的回退栈中。
fragment1.setArguments(bundle);
transaction.commit();
}
}
上面讲解了如何在Activity中向Fragment传递数据。下面示例讲解如何在Fragment之间进行数据传递。
示例二:Fragment之间数据传递
public class MainActivity extends Activity {
private FragmentManager manager;
private FragmentTransaction transaction;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
manager = getFragmentManager();
transaction = manager.beginTransaction();
LeftFragment leftFragment = new LeftFragment();
RightFragment rightFragment = new RightFragment();
// replace 是先remove掉相同id的所有fragment,然后在add当前的这个fragment。大部分情况:两者相同
transaction.add(R.id.left, leftFragment, "left");
transaction.add(R.id.right, rightFragment, "right");
transaction.commit();
}
}
在LeftFragment 中获得RightFragment中某个控件的值。通过getActivity获得Activity中某个控件的值。
public class LeftFragment extends Fragment {
private Button button;
private FragmentManager manager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
manager = getFragmentManager();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.left, null);
button = (Button) view.findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
RightFragment rightFragment = (RightFragment) manager
.findFragmentByTag("right");
String msg = ((EditText) rightFragment.getView()
.findViewById(R.id.editText1)).getText().toString();
Toast.makeText(getActivity(), "-right->>" + msg, 0).show();
Log.i("-->", getActivity().toString());
if(getActivity() instanceof MainActivity){
MainActivity main = (MainActivity) getActivity();
TextView tv = (TextView) main.findViewById(R.id.tv);
Log.i("-->", tv.getText().toString());
}
}
});
return view;
}
@Override
public void onPause() {
super.onPause();
}
}
示例三:在activity中获得fragment中某个控件的值
MainActivity .java
public class MainActivity extends Activity {
private FragmentManager manager;
private FragmentTransaction transaction;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) this.findViewById(R.id.button);
// 添加
manager = getFragmentManager();
transaction = manager.beginTransaction();
transaction.add(R.id.left, new LeftFragment(), "left");
transaction.commit();
// 在activity中获得fragment控件的值,使用回调
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//通过tag找到要操作的fragment
LeftFragment leftFragment = (LeftFragment) manager.findFragmentByTag("left");
leftFragment.getEditText(new CallBack() {
@Override
public void getResult(String result) {
Toast.makeText(MainActivity.this, "-->>" + result, 1).show();
}
});
}
});
}
}
LeftFragment.java
public class LeftFragment extends Fragment {
private Button button;
private EditText editText;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.left, null);
editText = (EditText) view.findViewById(R.id.editText1);
button = (Button) view.findViewById(R.id.button1);
//在fragment中获得activity控件的值
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EditText editText = (EditText) getActivity().findViewById(R.id.editText2);
Toast.makeText(getActivity(), "-->>" + editText.getText().toString(), 1).show();
}
});
return view;
}
@Override
public void onPause() {
super.onPause();
}
/**
* 对外提供的方法,用于在Activity中获得fragment中的值
* @param callBack
*/
public void getEditText(CallBack callBack) {
String msg = editText.getText().toString();
callBack.getResult(msg);
}
public interface CallBack {
public void getResult(String result);
}
}
2.结合ActionBar使用
public class MainActivity extends Activity {
private ActionBar actionBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
actionBar = getActionBar();
// 设置ActionBar的导航模式
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
//隐藏标题栏
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowHomeEnabled(false);
//添加tabs
actionBar.addTab(actionBar.newTab().setText("系统管理")
.setIcon(getResources().getDrawable(R.drawable.alarm))
.setTabListener(new MyTabListener()).setTag(1));
actionBar.addTab(actionBar.newTab().setText("用户管理")
.setIcon(getResources().getDrawable(R.drawable.sys))
.setTabListener(new MyTabListener()).setTag(2));
actionBar.addTab(actionBar.newTab().setText("产品管理")
.setIcon(getResources().getDrawable(R.drawable.user))
.setTabListener(new MyTabListener()).setTag(3));
}
public class MyTabListener implements ActionBar.TabListener {
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
int tag = Integer.parseInt(tab.getTag().toString());
switch (tag) {
case 1:
ft.replace(R.id.main, new FragmentA(), "fragment1");
break;
case 2:
ft.replace(R.id.main, new FragmentB(), "fragment2");
break;
case 3:
ft.replace(R.id.main, new FragmentC(), "fragment3");
break;
}
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
}
}
3.结合ViewPager的使用
使用ViewPager,首先需要一个集合,可以是List,List,List,然后使用一个数据适配器将数据适配给ViewPager。ViewPager自带提供了三个适配器,根据情况决定使用哪一个。PagerAdapter适用于View的集合;FragmentPagerAdapter 适用于Fragment的集合,且页面无需缓存;FragmentStatePagerAdapter 适用于Fragment的集合,且需要缓存页面。
①PagerAdapter
MainActivity.java
public class MainActivity extends Activity {
private ViewPager viewPager;
// 表示ViewPager显示的内容
private List<View> content;
// 表示ViewPager显示的标题
private List<String> title;
private LayoutInflater inflater;
private myPageAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
adapter = new myPageAdapter();
viewPager.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
private void init() {
viewPager = (ViewPager) this.findViewById(R.id.viewpager);
//初始化数据
inflater = LayoutInflater.from(this);
content = new ArrayList<View>();
title = new ArrayList<String>();
View firstView = inflater.inflate(R.layout.first, null);
View secondView = inflater.inflate(R.layout.second, null);
View threeView = inflater.inflate(R.layout.three, null);
content.add(firstView);
content.add(secondView);
content.add(threeView);
title.add("体育");
title.add("娱乐");
title.add("新闻");
}
public class myPageAdapter extends PagerAdapter {
//初始化每个item
@Override
public Object instantiateItem(ViewGroup container, int position) {
((ViewPager) container).addView(content.get(position));
return content.get(position);
}
@Override
public CharSequence getPageTitle(int position) {
return title.get(position);
}
@Override
public int getCount() {
return content.size();
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView(content.get(position));
}
}
}
activity_main.xml
根据情况决定是否增加Title,一般app的导航界面,不需要Title,使用几张图片就可以实现了。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<!-- 看做一个普通的控件 -->
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center" >
<android.support.v4.view.PagerTitleStrip
android:id="@+id/pagertitle"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:background="@android:color/darker_gray"
android:layout_gravity="top" >
</android.support.v4.view.PagerTitleStrip>
</android.support.v4.view.ViewPager>
</RelativeLayout>
②FragmentPagerAdapter
ViewPager的使用都是一样的,区别只是适配器的实现方式不同。
public class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return list.get(position);
}
@Override
public int getCount() {
return list.size();
}
}
③FragmentStatePagerAdapter
该适配器使用和之前的类似。如果Fragment的数量比较多,一般超过5个以上,还是推进使用缓存的机制,对当前访问的fragment的左右fragment进行缓存。示例结果:
public class MainActivity extends FragmentActivity implements OnClickListener {
private ViewPager viewPager;
static final int NUM_ITEMS = 10;// 定义一共有10页
private MyAdapter adapter;
private Button go_first;
private Button go_last;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
viewPager.setAdapter(adapter);
}
private void init() {
viewPager = (ViewPager) this.findViewById(R.id.pager);
adapter = new MyAdapter(getSupportFragmentManager());
go_first = (Button) this.findViewById(R.id.goto_first);
go_last = (Button) this.findViewById(R.id.goto_last);
go_first.setOnClickListener(this);
go_last.setOnClickListener(this);
}
//跳转到首页和尾页
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.goto_first:
viewPager.setCurrentItem(0);
break;
case R.id.goto_last:
viewPager.setCurrentItem(NUM_ITEMS -1);
break;
}
}
public static class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int arg0) {
return ArrayListFragment.getIntances(arg0);
}
@Override
public int getCount() {
return NUM_ITEMS;
}
}
public static class ArrayListFragment extends ListFragment {
int num;
static ArrayListFragment getIntances(int num) {
ArrayListFragment listFragment = new ArrayListFragment();
Bundle bundle = new Bundle();
bundle.putInt("num", num);
listFragment.setArguments(bundle);
return listFragment;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, getData()));
}
public List<String> getData() {
List<String> list = new ArrayList<String>();
for (int i = 0; i < 20; i++) {
list.add("jack" + i);
}
return list;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
System.out.println("------>>" + num);
num = (getArguments() != null ? getArguments().getInt("num") : 1);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_pager_list, null);
TextView textView = (TextView) view.findViewById(R.id.text);
textView.setText("Fragment #" + num);
return view;
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
Log.i("FragmentList", "Item clicked: " + id);
}
}
}