以下内容为原创,转载请注明:http://www.cnblogs.com/tiantianbyconan/p/3360938.html

如新浪微博下面的标签切换功能,我以前也写过一篇博文(http://www.cnblogs.com/tiantianbyconan/archive/2012/02/24/2366237.html),可以实现,用的是TabHost。但是android发展比较迅速,TabHost这玩意现在已经被弃用了,虽说用现在也能用,但是被弃用的东西还是少用为妙。

官方有个FragmentTabHost这么一个替代品,于是试了一下,发现每次切换tab,都会调用onCreateView()方法,控件被重新加载,也就是说你从tab1切换到别的tab后,再切换回来,tab1的状态并没有保存,重新加载了控件。

搞了半天,暂时没有好的解决办法(有朋友知道解决办法的话,希望联系我,赐教下哈)

于是,怒了,自己实现一个吧- -

 

先来看看整个demo的结构:

TabAFm到TabEFm都是Fragment,并且每个Fragment对应一个布局文件。

TabAFm.java:

 1 package com.wangjie.fragmenttabhost; 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 }
View Code

如上述代码所示,TabAFm是一个Fragment,对应的布局文件是tab_a.xml,并实现了他的所有的生命周期回调函数并打印,便于调试

tab_a.xml布局中有个EditText

其他的Fragment大同小异,这里就不贴出代码了

 

现在来看MainActivity:

 1 package com.wangjie.fragmenttabhost; 2  3 import android.os.Bundle; 4 import android.support.v4.app.Fragment; 5 import android.support.v4.app.FragmentActivity; 6 import android.widget.RadioGroup; 7  8 import java.util.ArrayList; 9 import java.util.List;10 11 public class MainActivity extends FragmentActivity {12     /**13      * Called when the activity is first created.14      */15     private RadioGroup rgs;16     public List fragments = new ArrayList();17 18     public String hello = "hello ";19 20     @Override21     public void onCreate(Bundle savedInstanceState) {22         super.onCreate(savedInstanceState);23         setContentView(R.layout.main);24 25         fragments.add(new TabAFm());26         fragments.add(new TabBFm());27         fragments.add(new TabCFm());28         fragments.add(new TabDFm());29         fragments.add(new TabEFm());30 31 32         rgs = (RadioGroup) findViewById(R.id.tabs_rg);33 34         FragmentTabAdapter tabAdapter = new FragmentTabAdapter(this, fragments, R.id.tab_content, rgs);35         tabAdapter.setOnRgsExtraCheckedChangedListener(new FragmentTabAdapter.OnRgsExtraCheckedChangedListener(){36             @Override37             public void OnRgsExtraCheckedChanged(RadioGroup radioGroup, int checkedId, int index) {38                 System.out.println("Extra---- " + index + " checked!!! ");39             }40         });41 42     }43 44 }
View Code

MainActivity上述代码所示

MainActivity是包含Fragment的Activity(也就是这里的5个Fragment)

他继承了FragmentActivity(因为我这里用的是android-support-v4.jar)

用一个List去维护5个Fragment,也就是5个tab

main布局中有一个id为tab_content的FrameLayout,用来存放要显示的Fragment。底部有一个RadioGroup,用于tab的切换,如下:

  1 <?xml version="1.0" encoding="utf-8"?>  2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  3               android:orientation="vertical"  4               android:layout_width="fill_parent"  5               android:layout_height="fill_parent"  6               android:background="@android:color/white"  7         >  8     <LinearLayout  9             android:layout_width="fill_parent" 10             android:layout_height="fill_parent" 11             android:orientation="vertical" 12         > 13  14     <FrameLayout 15             android:id="@+id/tab_content" 16             android:layout_width="fill_parent" 17             android:layout_height="0dp" 18             android:layout_weight="1.0" 19             android:background="#77557799" 20             /> 21  22     <RadioGroup 23             android:id="@+id/tabs_rg" 24             android:layout_width="fill_parent" 25             android:layout_height="wrap_content" 26             android:orientation="horizontal" 27             android:gravity="center" 28             android:paddingTop="7dp" 29             android:paddingBottom="7dp" 30             > 31         <RadioButton 32                 android:id="@+id/tab_rb_a" 33                 android:layout_width="0dp" 34                 android:layout_height="wrap_content" 35                 android:drawableTop="@drawable/tablatestalert" 36                 android:button="@null" 37                 android:text="Tab1" 38                 android:textColor="#000000" 39                 android:textSize="13sp" 40                 android:layout_weight="1.0" 41                 android:gravity="center" 42                 android:singleLine="true" 43                 android:checked="true" 44                 android:background="@drawable/selector_tab" 45                 /> 46         <RadioButton 47                 android:id="@+id/tab_rb_b" 48                 android:layout_width="0dp" 49                 android:layout_height="wrap_content" 50                 android:drawableTop="@drawable/tabsearch" 51                 android:button="@null" 52                 android:text="Tab2" 53                 android:textColor="#000000" 54                 android:textSize="13sp" 55                 android:layout_weight="1.0" 56                 android:gravity="center" 57                 android:singleLine="true" 58                 android:background="@drawable/selector_tab" 59                 /> 60         <RadioButton 61                 android:id="@+id/tab_rb_c" 62                 android:layout_width="0dp" 63                 android:layout_height="wrap_content" 64                 android:drawableTop="@drawable/tabrecommd" 65                 android:button="@null" 66                 android:text="Tab3" 67                 android:textColor="#000000" 68                 android:textSize="13sp" 69                 android:layout_weight="1.0" 70                 android:gravity="center" 71                 android:singleLine="true" 72                 android:background="@drawable/selector_tab" 73                 /> 74         <RadioButton 75                 android:id="@+id/tab_rb_d" 76                 android:layout_width="0dp" 77                 android:layout_height="wrap_content" 78                 android:drawableTop="@drawable/tabconfigicon" 79                 android:button="@null" 80                 android:text="Tab4" 81                 android:textColor="#000000" 82                 android:textSize="13sp" 83                 android:layout_weight="1.0" 84                 android:gravity="center" 85                 android:singleLine="true" 86                 android:background="@drawable/selector_tab" 87                 /> 88         <RadioButton 89                 android:id="@+id/tab_rb_e" 90                 android:layout_width="0dp" 91                 android:layout_height="wrap_content" 92                 android:drawableTop="@drawable/tababoutus" 93                 android:button="@null" 94                 android:text="Tab5" 95                 android:textColor="#000000" 96                 android:textSize="13sp" 97                 android:layout_weight="1.0" 98                 android:gravity="center" 99                 android:singleLine="true"100                 android:background="@drawable/selector_tab"101                 />102 103     RadioGroup>104     LinearLayout>105 LinearLayout>
View Code

现在回到MainActivity中,下面这个FragmentTabAdapter类是关键,是我自己编写的用于绑定和处理fragments和RadioGroup之间的逻辑关系

FragmentTabAdapter tabAdapter = new FragmentTabAdapter(this, fragments, R.id.tab_content, rgs);

 

现在看下FragmentTabAdapter:

  1 package com.wangjie.fragmenttabhost;  2   3 import android.support.v4.app.Fragment;  4 import android.support.v4.app.FragmentActivity;  5 import android.support.v4.app.FragmentTransaction;  6 import android.widget.RadioGroup;  7   8 import java.util.List;  9  10 /** 11  * Created with IntelliJ IDEA. 12  * Author: wangjie  email:tiantian.china.2@gmail.com 13  * Date: 13-10-10 14  * Time: 上午9:25 15  */ 16 public class FragmentTabAdapter implements RadioGroup.OnCheckedChangeListener{ 17     private List fragments; // 一个tab页面对应一个Fragment 18     private RadioGroup rgs; // 用于切换tab 19     private FragmentActivity fragmentActivity; // Fragment所属的Activity 20     private int fragmentContentId; // Activity中所要被替换的区域的id 21  22     private int currentTab; // 当前Tab页面索引 23  24     private OnRgsExtraCheckedChangedListener onRgsExtraCheckedChangedListener; // 用于让调用者在切换tab时候增加新的功能 25  26     public FragmentTabAdapter(FragmentActivity fragmentActivity, List fragments, int fragmentContentId, RadioGroup rgs) { 27         this.fragments = fragments; 28         this.rgs = rgs; 29         this.fragmentActivity = fragmentActivity; 30         this.fragmentContentId = fragmentContentId; 31  32         // 默认显示第一页 33         FragmentTransaction ft = fragmentActivity.getSupportFragmentManager().beginTransaction(); 34         ft.add(fragmentContentId, fragments.get(0)); 35         ft.commit(); 36  37         rgs.setOnCheckedChangeListener(this); 38  39  40     } 41  42     @Override 43     public void onCheckedChanged(RadioGroup radioGroup, int checkedId) { 44         for(int i = 0; i < rgs.getChildCount(); i++){ 45             if(rgs.getChildAt(i).getId() == checkedId){ 46                 Fragment fragment = fragments.get(i); 47                 FragmentTransaction ft = obtainFragmentTransaction(i); 48  49                 getCurrentFragment().onPause(); // 暂停当前tab 50 //                getCurrentFragment().onStop(); // 暂停当前tab 51  52                 if(fragment.isAdded()){ 53 //                    fragment.onStart(); // 启动目标tab的onStart() 54                     fragment.onResume(); // 启动目标tab的onResume() 55                 }else{ 56                     ft.add(fragmentContentId, fragment); 57                 } 58                 showTab(i); // 显示目标tab 59                 ft.commit(); 60  61                 // 如果设置了切换tab额外功能功能接口 62                 if(null != onRgsExtraCheckedChangedListener){ 63                     onRgsExtraCheckedChangedListener.OnRgsExtraCheckedChanged(radioGroup, checkedId, i); 64                 } 65  66             } 67         } 68  69     } 70  71     /** 72      * 切换tab 73      * @param idx 74      */ 75     private void showTab(int idx){ 76         for(int i = 0; i < fragments.size(); i++){ 77             Fragment fragment = fragments.get(i); 78             FragmentTransaction ft = obtainFragmentTransaction(idx); 79  80             if(idx == i){ 81                 ft.show(fragment); 82             }else{ 83                 ft.hide(fragment); 84             } 85             ft.commit(); 86         } 87         currentTab = idx; // 更新目标tab为当前tab 88     } 89  90     /** 91      * 获取一个带动画的FragmentTransaction 92      * @param index 93      * @return 94      */ 95     private FragmentTransaction obtainFragmentTransaction(int index){ 96         FragmentTransaction ft = fragmentActivity.getSupportFragmentManager().beginTransaction(); 97         // 设置切换动画 98         if(index > currentTab){ 99             ft.setCustomAnimations(R.anim.slide_left_in, R.anim.slide_left_out);100         }else{101             ft.setCustomAnimations(R.anim.slide_right_in, R.anim.slide_right_out);102         }103         return ft;104     }105 106     public int getCurrentTab() {107         return currentTab;108     }109 110     public Fragment getCurrentFragment(){111         return fragments.get(currentTab);112     }113 114     public OnRgsExtraCheckedChangedListener getOnRgsExtraCheckedChangedListener() {115         return onRgsExtraCheckedChangedListener;116     }117 118     public void setOnRgsExtraCheckedChangedListener(OnRgsExtraCheckedChangedListener onRgsExtraCheckedChangedListener) {119         this.onRgsExtraCheckedChangedListener = onRgsExtraCheckedChangedListener;120     }121 122     /**123      *  切换tab额外功能功能接口124      */125     static class OnRgsExtraCheckedChangedListener{126         public void OnRgsExtraCheckedChanged(RadioGroup radioGroup, int checkedId, int index){127 128         }129     }130 131 }
View Code

这里解决Fragment切换重新加载布局的办法,用的是把几个Fragment全部Add,然后根据要显示的哪个Fragment设置show或者hide

效果输出:

10-10 11:55:41.168: INFO/System.out(18368): AAAAAAAAAA____onAttach      // 第一次进入,显示TabA
10-10 11:55:41.168: INFO/System.out(18368): AAAAAAAAAA____onCreate
10-10 11:55:41.168: INFO/System.out(18368): AAAAAAAAAA____onCreateView
10-10 11:55:41.175: INFO/System.out(18368): AAAAAAAAAA____onActivityCreated
10-10 11:55:41.179: INFO/System.out(18368): AAAAAAAAAA____onStart
10-10 11:55:41.179: INFO/System.out(18368): AAAAAAAAAA____onResume
10-10 11:55:44.980: INFO/System.out(18368): AAAAAAAAAA____onPause      // 从TabA切换到TabB(TabA调用onPause)
10-10 11:55:44.980: INFO/System.out(18368): Extra---- 1 checked!!!
10-10 11:55:44.996: INFO/System.out(18368): BBBBBBBBBBB____onAttach
10-10 11:55:44.996: INFO/System.out(18368): BBBBBBBBBBB____onCreate
10-10 11:55:44.996: INFO/System.out(18368): BBBBBBBBBBB____onCreateView
10-10 11:55:45.004: INFO/System.out(18368): BBBBBBBBBBB____onActivityCreated
10-10 11:55:45.004: INFO/System.out(18368): BBBBBBBBBBB____onStart
10-10 11:55:45.004: INFO/System.out(18368): BBBBBBBBBBB____onResume
10-10 11:55:52.062: INFO/System.out(18368): BBBBBBBBBBB____onPause      // 从TabB切换到TabC(TabB调用onPause)
10-10 11:55:52.062: INFO/System.out(18368): Extra---- 2 checked!!!
10-10 11:55:52.082: INFO/System.out(18368): CCCCCCCCCC____onAttach
10-10 11:55:52.082: INFO/System.out(18368): CCCCCCCCCC____onCreate
10-10 11:55:52.086: INFO/System.out(18368): CCCCCCCCCC____onCreateView
10-10 11:55:52.090: INFO/System.out(18368): CCCCCCCCCC____onActivityCreated
10-10 11:55:52.090: INFO/System.out(18368): CCCCCCCCCC____onStart
10-10 11:55:52.090: INFO/System.out(18368): CCCCCCCCCC____onResume
10-10 11:56:06.535: INFO/System.out(18368): CCCCCCCCCC____onPause      // 从TabC切换到TabB(TabC调用onPause)
10-10 11:56:06.535: INFO/System.out(18368): BBBBBBBBBBB____onResume    // 从TabC切换到TabB(TabB调用onResume)
10-10 11:56:06.535: INFO/System.out(18368): Extra---- 1 checked!!!

 

好了,到此为止,我们已经用Fragment实现了类似TabHost的功能了,下面来看下各个Fragment之间的通信

现在的情况是TabAFm中有个EditText,TabBFm中有个Button,MainActivity中有个变量“hello”

要做的是,切换到TabA,输入“I'm TabA”,切换到B,点击Button后,Toast显示“hello I'm TabA”

MainActivity中没什么好说的,就一个hello变量:

public String hello = "hello ";

TabAFm在布局文件tab_a.xml中加个EditText,设置个id就可以了

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     }
View Code
// 获得绑定的FragmentActivityMainActivity activity = ((MainActivity)getActivity());

通过getActivity()即可得到Fragment所在的FragmentActivity

 

最终效果图:

demo下载地址:http://pan.baidu.com/s/1wxsIX

更多相关文章

  1. android viewflipper和tabhost效率对比
  2. Android(安卓)ListView存在多个item样式的处理方法
  3. 跟我学android-使用Eclipse开发第一个Android应用(三)
  4. Android(安卓)解决ListView里面多套布局多个EditText数据混乱问
  5. changeConfig配置 以及对activity生命周期的影响
  6. UI 布局
  7. Android之Adapter用法总结(转载)
  8. Android(安卓)学习入门最佳Demo--自定义View 属性,RelativeLayout
  9. Android(安卓)5.X新特性

随机推荐

  1. 【Android】Android(安卓)监听apk安装替
  2. Android中关于线程使用的几点注意事项
  3. Android(安卓)TextView实现滚动跑马灯效
  4. Android(安卓)Animation学习笔记
  5. Android(安卓)toolbar与actionbar区别
  6. Android层次化安全架构及核心组件概览
  7. 使用Android(安卓)adb命令来启动Android
  8. Android热修复技术链接收集
  9. Android(安卓)渗透测试学习手册 第二章
  10. 新书内容连载(3):Android(安卓)SDK中常用命