【转】Android使用Fragment来实现ViewPager的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
来源:互联网 发布:知乎 东南亚女人 编辑:程序博客网 时间:2024/04/29 20:21
以下内容为原创,转载请注明:http://www.cnblogs.com/tiantianbyconan/p/3364728.html
我前两天写过一篇博客《Android使用Fragment来实现TabHost的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信》(http://www.cnblogs.com/tiantianbyconan/p/3360938.html),实现了Tab切换时保留当前Fragment状态,并在切换前自动回调onPause()方法,在切换后自动调用onResume(),这样就做到了跟TahHost一样的功能。
今天来实现下ViewPager的功能,google提供了一个FragmentPagerAdapter这么一个适配器,蛋疼的是,碰到了跟上次类似的问题。比如ViewPager有5个page,刚打开的时候,会加载page1和page2,我们手动切换到page2的时候,会加载page3,切换到page3的时候,加载page4的同时会destory掉page1,所以,还是面临同样的问题,page的状态无法保存,于是,咱还是自己来实现下好了,自己动手,丰衣足食嘛!(同样 有朋友知道解决办法的话,希望联系我,赐教下哈)
先来看下整个demo的结构,跟上次实现TabHost的例子差不多:
TabAFm到TabEFm都是Fragment,并且每个Fragment对应一个布局文件。
TabAFm.java:
1 package com.wangjie.fragmentviewpagertest; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.support.v4.app.Fragment; 6 import android.view.LayoutInflater; 7 import android.view.View; 8 import android.view.ViewGroup; 9 10 /**11 * Created with IntelliJ IDEA.12 * Author: wangjie email:tiantian.china.2@gmail.com13 * Date: 13-6-1414 * Time: 下午2:3915 */16 public class TabAFm extends Fragment{17 @Override18 public void onAttach(Activity activity) {19 super.onAttach(activity);20 System.out.println("AAAAAAAAAA____onAttach");21 }22 23 @Override24 public void onCreate(Bundle savedInstanceState) {25 super.onCreate(savedInstanceState);26 System.out.println("AAAAAAAAAA____onCreate");27 }28 29 @Override30 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {31 System.out.println("AAAAAAAAAA____onCreateView");32 return inflater.inflate(R.layout.tab_a, container, false);33 }34 35 @Override36 public void onActivityCreated(Bundle savedInstanceState) {37 super.onActivityCreated(savedInstanceState);38 System.out.println("AAAAAAAAAA____onActivityCreated");39 }40 41 @Override42 public void onStart() {43 super.onStart();44 System.out.println("AAAAAAAAAA____onStart");45 }46 47 @Override48 public void onResume() {49 super.onResume();50 System.out.println("AAAAAAAAAA____onResume");51 }52 53 @Override54 public void onPause() {55 super.onPause();56 System.out.println("AAAAAAAAAA____onPause");57 }58 59 @Override60 public void onStop() {61 super.onStop();62 System.out.println("AAAAAAAAAA____onStop");63 }64 65 @Override66 public void onDestroyView() {67 super.onDestroyView();68 System.out.println("AAAAAAAAAA____onDestroyView");69 }70 71 @Override72 public void onDestroy() {73 super.onDestroy();74 System.out.println("AAAAAAAAAA____onDestroy");75 }76 77 @Override78 public void onDetach() {79 super.onDetach();80 System.out.println("AAAAAAAAAA____onDetach");81 }82 }
如上述代码所示,TabAFm是一个Fragment,对应的布局文件是tab_a.xml,并实现了他的所有的生命周期回调函数并打印,便于调试
tab_a.xml布局中有个EditText
其他的Fragment大同小异,这里就不贴出代码了
现在来看MainActivity:
MainActivity上述代码所示
MainActivity是包含Fragment的Activity(也就是这里的5个Fragment)
他继承了FragmentActivity(因为我这里用的是android-support-v4.jar)
用一个List<Fragment>去维护5个Fragment,也就是5个page。
MainActivity的布局很简单,就一个ViewPager,main.xml如下:
现在回到MainActivity中,下面这个FragmentViewPagerAdapter类是关键,是我自己编写的用于绑定和处理fragments和ViewPager之间的逻辑关系
FragmentViewPagerAdapter adapter = new FragmentViewPagerAdapter(this.getSupportFragmentManager(), viewPager,fragments);
现在看下FragmentViewPagerAdapter:
1 package com.wangjie.fragmentviewpagertest; 2 3 import android.support.v4.app.Fragment; 4 import android.support.v4.app.FragmentManager; 5 import android.support.v4.app.FragmentTransaction; 6 import android.support.v4.view.PagerAdapter; 7 import android.support.v4.view.ViewPager; 8 import android.view.View; 9 import android.view.ViewGroup; 10 11 import java.util.List; 12 13 /** 14 * 为ViewPager添加布局(Fragment),绑定和处理fragments和viewpager之间的逻辑关系 15 * 16 * Created with IntelliJ IDEA. 17 * Author: wangjie email:tiantian.china.2@gmail.com 18 * Date: 13-10-11 19 * Time: 下午3:03 20 */ 21 public class FragmentViewPagerAdapter extends PagerAdapter implements ViewPager.OnPageChangeListener{ 22 private List<Fragment> fragments; // 每个Fragment对应一个Page 23 private FragmentManager fragmentManager; 24 private ViewPager viewPager; // viewPager对象 25 private int currentPageIndex = 0; // 当前page索引(切换之前) 26 27 private OnExtraPageChangeListener onExtraPageChangeListener; // ViewPager切换页面时的额外功能添加接口 28 29 public FragmentViewPagerAdapter(FragmentManager fragmentManager, ViewPager viewPager , List<Fragment> fragments) { 30 this.fragments = fragments; 31 this.fragmentManager = fragmentManager; 32 this.viewPager = viewPager; 33 this.viewPager.setAdapter(this); 34 this.viewPager.setOnPageChangeListener(this); 35 } 36 37 @Override 38 public int getCount() { 39 return fragments.size(); 40 } 41 42 @Override 43 public boolean isViewFromObject(View view, Object o) { 44 return view == o; 45 } 46 47 @Override 48 public void destroyItem(ViewGroup container, int position, Object object) { 49 container.removeView(fragments.get(position).getView()); // 移出viewpager两边之外的page布局 50 } 51 52 @Override 53 public Object instantiateItem(ViewGroup container, int position) { 54 Fragment fragment = fragments.get(position); 55 if(!fragment.isAdded()){ // 如果fragment还没有added 56 FragmentTransaction ft = fragmentManager.beginTransaction(); 57 ft.add(fragment, fragment.getClass().getSimpleName()); 58 ft.commit(); 59 /** 60 * 在用FragmentTransaction.commit()方法提交FragmentTransaction对象后 61 * 会在进程的主线程中,用异步的方式来执行。 62 * 如果想要立即执行这个等待中的操作,就要调用这个方法(只能在主线程中调用)。 63 * 要注意的是,所有的回调和相关的行为都会在这个调用中被执行完成,因此要仔细确认这个方法的调用位置。 64 */ 65 fragmentManager.executePendingTransactions(); 66 } 67 68 if(fragment.getView().getParent() == null){ 69 container.addView(fragment.getView()); // 为viewpager增加布局 70 } 71 72 return fragment.getView(); 73 } 74 75 /** 76 * 当前page索引(切换之前) 77 * @return 78 */ 79 public int getCurrentPageIndex() { 80 return currentPageIndex; 81 } 82 83 public OnExtraPageChangeListener getOnExtraPageChangeListener() { 84 return onExtraPageChangeListener; 85 } 86 87 /** 88 * 设置页面切换额外功能监听器 89 * @param onExtraPageChangeListener 90 */ 91 public void setOnExtraPageChangeListener(OnExtraPageChangeListener onExtraPageChangeListener) { 92 this.onExtraPageChangeListener = onExtraPageChangeListener; 93 } 94 95 @Override 96 public void onPageScrolled(int i, float v, int i2) { 97 if(null != onExtraPageChangeListener){ // 如果设置了额外功能接口 98 onExtraPageChangeListener.onExtraPageScrolled(i, v, i2); 99 }100 }101 102 @Override103 public void onPageSelected(int i) {104 fragments.get(currentPageIndex).onPause(); // 调用切换前Fargment的onPause()105 // fragments.get(currentPageIndex).onStop(); // 调用切换前Fargment的onStop()106 if(fragments.get(i).isAdded()){107 // fragments.get(i).onStart(); // 调用切换后Fargment的onStart()108 fragments.get(i).onResume(); // 调用切换后Fargment的onResume()109 }110 currentPageIndex = i;111 112 if(null != onExtraPageChangeListener){ // 如果设置了额外功能接口113 onExtraPageChangeListener.onExtraPageSelected(i);114 }115 116 }117 118 @Override119 public void onPageScrollStateChanged(int i) {120 if(null != onExtraPageChangeListener){ // 如果设置了额外功能接口121 onExtraPageChangeListener.onExtraPageScrollStateChanged(i);122 }123 }124 125 126 /**127 * page切换额外功能接口128 */129 static class OnExtraPageChangeListener{130 public void onExtraPageScrolled(int i, float v, int i2){}131 public void onExtraPageSelected(int i){}132 public void onExtraPageScrollStateChanged(int i){}133 }134 135 136 }
这里解决Fragment切换重新加载布局的办法,用的是把几个Fragment全部Add,然后根据要显示的哪个Fragment就把哪个Fragment的View给添加到“ViewGroup container”上去。
效果输出:
// 以下打开程序后,加载PageA和PageB
10-12 09:42:46.671: INFO/System.out(27248): AAAAAAAAAA____onAttach
10-12 09:42:46.671: INFO/System.out(27248): AAAAAAAAAA____onCreate
10-12 09:42:46.671: INFO/System.out(27248): AAAAAAAAAA____onCreateView
10-12 09:42:46.761: INFO/System.out(27248): AAAAAAAAAA____onActivityCreated
10-12 09:42:46.765: INFO/System.out(27248): AAAAAAAAAA____onStart
10-12 09:42:46.765: INFO/System.out(27248): AAAAAAAAAA____onResume
10-12 09:42:46.847: INFO/System.out(27248): BBBBBBBBBBB____onAttach
10-12 09:42:46.847: INFO/System.out(27248): BBBBBBBBBBB____onCreate
10-12 09:42:46.851: INFO/System.out(27248): BBBBBBBBBBB____onCreateView
10-12 09:42:46.867: INFO/System.out(27248): BBBBBBBBBBB____onActivityCreated
10-12 09:42:46.867: INFO/System.out(27248): BBBBBBBBBBB____onStart
10-12 09:42:46.867: INFO/System.out(27248): BBBBBBBBBBB____onResume
// 以下切换到PageB
10-12 09:42:57.285: INFO/System.out(27248): AAAAAAAAAA____onPause // 切换到PageB前会调用PageA的onPause()方法
10-12 09:42:57.285: INFO/System.out(27248): BBBBBBBBBBB____onResume // 切换到PageB后会调用PageB的onResume()方法
10-12 09:42:57.285: INFO/System.out(27248): Extra...i: 1 // 切换页面时会调用切换额外功能接口(用户可以自己写需要的逻辑)
10-12 09:42:57.582: INFO/System.out(27248): CCCCCCCCCC____onAttach // 切换到PageB后会加载PageC
10-12 09:42:57.586: INFO/System.out(27248): CCCCCCCCCC____onCreate
10-12 09:42:57.586: INFO/System.out(27248): CCCCCCCCCC____onCreateView
10-12 09:42:57.675: INFO/System.out(27248): CCCCCCCCCC____onActivityCreated
10-12 09:42:57.675: INFO/System.out(27248): CCCCCCCCCC____onStart
10-12 09:42:57.675: INFO/System.out(27248): CCCCCCCCCC____onResume
// 以下切换到PageC
10-12 09:43:18.261: INFO/System.out(27248): BBBBBBBBBBB____onPause // 切换到PageC前会调用PageB的onPause()方法
10-12 09:43:18.261: INFO/System.out(27248): CCCCCCCCCC____onResume // 切换到PageC后会调用PageC的onResume()方法
10-12 09:43:18.261: INFO/System.out(27248): Extra...i: 2 // 切换页面时会调用切换额外功能接口(用户可以自己写需要的逻辑)
10-12 09:43:18.726: INFO/System.out(27248): DDDDDDDDD____onAttach // 切换到PageC后会加载PageD
10-12 09:43:18.726: INFO/System.out(27248): DDDDDDDDD____onCreate
10-12 09:43:18.726: INFO/System.out(27248): DDDDDDDDD____onCreateView
10-12 09:43:18.738: INFO/System.out(27248): DDDDDDDDD____onActivityCreated
10-12 09:43:18.738: INFO/System.out(27248): DDDDDDDDD____onStart
10-12 09:43:18.742: INFO/System.out(27248): DDDDDDDDD____onResume
// 以下切换到PageB
10-12 09:43:20.742: INFO/System.out(27248): CCCCCCCCCC____onPause // 切换到PageB前会调用PageC的onPause()方法
10-12 09:43:20.742: INFO/System.out(27248): BBBBBBBBBBB____onResume // 切换到PageB后会调用PageB的onResume()方法
10-12 09:43:20.746: INFO/System.out(27248): Extra...i: 1 // 切换页面时会调用切换额外功能接口(用户可以自己写需要的逻辑)
好了,到此为止,我们已经用Fragment实现了ViewPager的功能了,同样,下面来看下各个Fragment之间的通信
现在的情况是TabAFm中有个EditText,TabBFm中有个Button,MainActivity中有个变量“hello”
要做的是,切换到A,输入“I'm PageA”,切换到B,点击Button后,Toast显示“hello I'm PageA”
MainActivity中没什么好说的,就一个hello变量:
public String hello = "hello ";
TabBFm中:
1 @Override 2 public void onActivityCreated(Bundle savedInstanceState) { 3 super.onActivityCreated(savedInstanceState); 4 System.out.println("BBBBBBBBBBB____onActivityCreated"); 5 this.getView().findViewById(R.id.clickme).setOnClickListener(new View.OnClickListener() { 6 @Override 7 public void onClick(View view) { 8 // 获得绑定的FragmentActivity 9 MainActivity activity = ((MainActivity)getActivity());10 // 获得TabAFm的控件11 EditText editText = (EditText) activity.fragments.get(0).getView().findViewById(R.id.edit);12 13 Toast.makeText(activity, activity.hello + editText.getText(), Toast.LENGTH_SHORT).show();14 }15 });16 }
最终效果图:
demo下载:http://pan.baidu.com/s/1stGQ7
- 【转】Android使用Fragment来实现ViewPager的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
- Android使用Fragment来实现ViewPager的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
- Android使用Fragment来实现ViewPager的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
- Android使用Fragment来实现ViewPager的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
- Android使用Fragment来实现ViewPager的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
- Android使用Fragment来实现TabHost的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
- Android使用Fragment来实现TabHost的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
- Android使用Fragment来实现TabHost的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
- Android使用Fragment来实现TabHost的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
- Android使用Fragment来实现TabHost的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
- Android使用Fragment来实现TabHost的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
- Android使用Fragment来实现TabHost的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
- Android使用Fragment来实现TabHost的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
- Android使用Fragment来实现TabHost的功能(解决切换Fragment状态不保存)
- 解决切换Fragment状态不保存 以及各个Fragment之间的通信
- 使用ViewPager的功能(解决切换Fragment状态不保存)
- android fragment+ FragmentTabHost+viewpager 切换状态不保存的问题
- Android viewpager + fragment实现fragment之间的切换
- cocos2d-x集成sharesdk做微信分享android,ios
- 跨平台移植 linux<—>windows
- cocos2d-html5学习笔记(一)--游戏入口
- tky项目第④⑤个半月总结——Shuttle ESB的研究
- AIX 6.1 安装lsof
- 【转】Android使用Fragment来实现ViewPager的功能(解决切换Fragment状态不保存)以及各个Fragment之间的通信
- 异常
- XMLHelper.cs
- java自定义注解
- cocos2d-html5学习笔记(二)——cocos2d中的layer
- javascript splice
- jsonCpp 解析报错 "Bad escape sequence in string"
- cocos2d-html5学习笔记(三)--cocos2d中的坐标系统
- JQuery处理json与ajax返回JSON实例