工程結構 html
TabAFm到TabEFm都是Fragment,而且每一個Fragment對應一個佈局文件。java
TabAFm.java android
package com.yydcdut.tabhoststudy; import android.app.Activity; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class TabAFm extends Fragment { @Override public void onAttach(Activity activity) { super.onAttach(activity); System.out.println("AAAAAAAAAA____onAttach"); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); System.out.println("AAAAAAAAAA____onCreate"); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { System.out.println("AAAAAAAAAA____onCreateView"); return inflater.inflate(R.layout.tab_a, container, false); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); System.out.println("AAAAAAAAAA____onActivityCreated"); } @Override public void onStart() { super.onStart(); System.out.println("AAAAAAAAAA____onStart"); } @Override public void onResume() { super.onResume(); System.out.println("AAAAAAAAAA____onResume"); } @Override public void onPause() { super.onPause(); System.out.println("AAAAAAAAAA____onPause"); } @Override public void onStop() { super.onStop(); System.out.println("AAAAAAAAAA____onStop"); } @Override public void onDestroyView() { super.onDestroyView(); System.out.println("AAAAAAAAAA____onDestroyView"); } @Override public void onDestroy() { super.onDestroy(); System.out.println("AAAAAAAAAA____onDestroy"); } @Override public void onDetach() { super.onDetach(); System.out.println("AAAAAAAAAA____onDetach"); } }
如上述代碼所示,TabAFm是一個Fragment,對應的佈局文件是tab_a.xml,並實現了他的全部的生命週期回調函數並打印,便於調試。tab_a.xml佈局中有個EditText,其餘的Fragment大同小異,這裏就不貼出代碼了app
MainActivity ide
package com.yydcdut.tabhoststudy; import java.util.ArrayList; import java.util.List; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.view.ViewPager; import android.widget.RadioGroup; public class MainActivity extends FragmentActivity { private RadioGroup rgs; public List<Fragment> fragments = new ArrayList<Fragment>(); public String hello = "hello "; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); fragments.add(new TabAFm()); fragments.add(new TabBFm()); fragments.add(new TabCFm()); fragments.add(new TabDFm()); fragments.add(new TabEFm()); rgs = (RadioGroup) findViewById(R.id.tabs_rg); FragmentTabAdapter2 tabAdapter = new FragmentTabAdapter2(this, fragments, R.id.tab_content, rgs); tabAdapter.setOnRgsExtraCheckedChangedListener(new FragmentTabAdapter2.OnRgsExtraCheckedChangedListener(){ @Override public void OnRgsExtraCheckedChanged(RadioGroup radioGroup, int checkedId, int index) { System.out.println("Extra---- " + index + " checked!!! "); } }); } }
MainActivity上述代碼所示函數
MainActivity是包含Fragment的Activity(也就是這裏的5個Fragment)佈局
他繼承了FragmentActivity(由於我這裏用的是android-support-v4.jar)學習
用一個List<Fragment>去維護5個Fragment,也就是5個tab動畫
main佈局 this
有一個id爲tab_content的FrameLayout,用來存放要顯示的Fragment。底部有一個RadioGroup,用於tab的切換
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@android:color/white" android:orientation="vertical" > <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <FrameLayout android:id="@+id/tab_content" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1.0" android:background="#77557799" /> <RadioGroup android:id="@+id/tabs_rg" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal" android:paddingBottom="7dp" android:paddingTop="7dp" > <RadioButton android:id="@+id/tab_rb_a" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1.0" android:background="@drawable/selector_tab" android:button="@null" android:checked="true" android:drawableTop="@drawable/tablatestalert" android:gravity="center" android:singleLine="true" android:text="Tab1" android:textColor="#000000" android:textSize="13sp" /> <RadioButton android:id="@+id/tab_rb_b" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1.0" android:background="@drawable/selector_tab" android:button="@null" android:drawableTop="@drawable/tabsearch" android:gravity="center" android:singleLine="true" android:text="Tab2" android:textColor="#000000" android:textSize="13sp" /> <RadioButton android:id="@+id/tab_rb_c" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1.0" android:background="@drawable/selector_tab" android:button="@null" android:drawableTop="@drawable/tabrecommd" android:gravity="center" android:singleLine="true" android:text="Tab3" android:textColor="#000000" android:textSize="13sp" /> <RadioButton android:id="@+id/tab_rb_d" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1.0" android:background="@drawable/selector_tab" android:button="@null" android:drawableTop="@drawable/tabconfigicon" android:gravity="center" android:singleLine="true" android:text="Tab4" android:textColor="#000000" android:textSize="13sp" /> <RadioButton android:id="@+id/tab_rb_e" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1.0" android:background="@drawable/selector_tab" android:button="@null" android:drawableTop="@drawable/tababoutus" android:gravity="center" android:singleLine="true" android:text="Tab5" android:textColor="#000000" android:textSize="13sp" /> </RadioGroup> </LinearLayout> </LinearLayout>
如今回到MainActivity中,下面這個FragmentTabAdapter類是關鍵,是我本身編寫的用於綁定和處理fragments和RadioGroup之間的邏輯關係
FragmentTabAdapter2 tabAdapter = new FragmentTabAdapter2(this, fragments, R.id.tab_content, rgs);
FragmentTabAdapter2
package com.yydcdut.tabhoststudy; import java.util.List; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentTransaction; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; public class FragmentTabAdapter2 { private List<Fragment> fragments; // 一個tab頁面對應一個Fragment private RadioGroup rgs; // 用於切換tab private FragmentActivity fragmentActivity; // Fragment所屬的Activity private int fragmentContentId; // Activity中所要被替換的區域的id private int currentTab; // 當前Tab頁面索引 private OnRgsExtraCheckedChangedListener onRgsExtraCheckedChangedListener; // 用於讓調用者在切換tab時候增長新的功能 /** * 構造函數 * * @param fragmentActivity * @param fragments * @param fragmentContentId * @param rgs */ public FragmentTabAdapter2(FragmentActivity fragmentActivity, List<Fragment> fragments, int fragmentContentId, RadioGroup rgs) { this.fragments = fragments; this.rgs = rgs; this.fragmentActivity = fragmentActivity; this.fragmentContentId = fragmentContentId; // 默認顯示第一頁 FragmentTransaction ft = fragmentActivity.getSupportFragmentManager() .beginTransaction(); ft.add(fragmentContentId, fragments.get(0)); ft.commit(); // 設置監聽事件 MyCheckedChangeListener myCheckedChangeListener = new MyCheckedChangeListener(); rgs.setOnCheckedChangeListener(myCheckedChangeListener); } /** * 監聽器內部類 * * @author sansung * */ class MyCheckedChangeListener implements OnCheckedChangeListener { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { for (int i = 0; i < rgs.getChildCount(); i++) { if (rgs.getChildAt(i).getId() == checkedId) { Fragment fragment = fragments.get(i); FragmentTransaction ft = obtainFragmentTransaction(i); getCurrentFragment().onPause(); // 暫停當前tab // getCurrentFragment().onStop(); // 暫停當前tab if (fragment.isAdded()) { // fragment.onStart(); // 啓動目標tab的onStart() fragment.onResume(); // 啓動目標tab的onResume() } else { ft.add(fragmentContentId, fragment); } showTab(i); // 顯示目標tab ft.commit(); // 若是設置了切換tab額外功能功能接口 if (null != onRgsExtraCheckedChangedListener) { onRgsExtraCheckedChangedListener .OnRgsExtraCheckedChanged(group, checkedId, i); } } } } } /** * 切換tab * * @param idx */ private void showTab(int idx) { for (int i = 0; i < fragments.size(); i++) { Fragment fragment = fragments.get(i); FragmentTransaction ft = obtainFragmentTransaction(idx); if (idx == i) { ft.show(fragment); } else { ft.hide(fragment); } ft.commit(); } currentTab = idx; // 更新目標tab爲當前tab } /** * 獲取一個帶動畫的FragmentTransaction * * @param index * @return */ private FragmentTransaction obtainFragmentTransaction(int index) { FragmentTransaction ft = fragmentActivity.getSupportFragmentManager() .beginTransaction(); // 設置切換動畫 if (index > currentTab) { ft.setCustomAnimations(R.anim.slide_left_in, R.anim.slide_left_out); } else { ft.setCustomAnimations(R.anim.slide_right_in, R.anim.slide_right_out); } return ft; } public int getCurrentTab() { return currentTab; } public Fragment getCurrentFragment() { return fragments.get(currentTab); } public OnRgsExtraCheckedChangedListener getOnRgsExtraCheckedChangedListener() { return onRgsExtraCheckedChangedListener; } public void setOnRgsExtraCheckedChangedListener( OnRgsExtraCheckedChangedListener onRgsExtraCheckedChangedListener) { this.onRgsExtraCheckedChangedListener = onRgsExtraCheckedChangedListener; } /** * 切換tab額外功能功能接口 */ static class OnRgsExtraCheckedChangedListener { public void OnRgsExtraCheckedChanged(RadioGroup radioGroup, int checkedId, int index) { } } }
這裏解決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中:
@Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); System.out.println("BBBBBBBBBBB____onActivityCreated"); this.getView().findViewById(R.id.clickme).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 得到綁定的FragmentActivity MainActivity activity = ((MainActivity)getActivity()); // 得到TabAFm的控件 EditText editText = (EditText) activity.fragments.get(0).getView().findViewById(R.id.edit); Toast.makeText(activity, activity.hello + editText.getText(), Toast.LENGTH_SHORT).show(); } }); }
// 得到綁定的FragmentActivity MainActivity activity = ((MainActivity)getActivity());
經過getActivity()便可獲得Fragment所在的FragmentActivity
我是天王蓋地虎的分割線
源代碼:http://pan.baidu.com/s/1dD1Qx01
tabhost學習.zip
參考:http://www.cnblogs.com/tiantianbyconan/p/3360938.html