Android两级导航菜单栏的实现--FragmentTabHost+自定义二级导航菜单栏
前两篇博文分别采用 FragmentTabHost嵌套FragmentTabHost和FragmentTabHost+PagerSlidingTabStrip 与ViewPager的方式实现了子Tab导航菜单栏的效果,虽是好用,但有时候却不灵活。
本篇中将要实现自定义Tab导航菜单栏效果。
如果你对FragmentTabHost和Fragment还不熟悉,一定要先看前面的博文。
仍然先看看效果图
重写fragment_message1.xml
- <?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:background="#F5F7FA"
- android:orientation="vertical" >
- <include layout="@layout/top_sub_tab" />
- <FrameLayout
- android:id="@+id/id_content"
- android:layout_width="fill_parent"
- android:layout_height="0dp"
- android:layout_weight="1" >
- </FrameLayout>
- </LinearLayout>
顶部的Tab导航为自定义top_sub_tab.xml
当然,你可以随心所欲的打造出符合业务需要的样式
- <?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="40dp"
- android:background="#eee"
- android:orientation="vertical" >
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="37dp"
- android:orientation="horizontal" >
- <LinearLayout
- android:id="@+id/lin_sub1"
- android:layout_width="3dp"
- android:orientation="horizontal"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:gravity="center" >
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="新闻"
- android:textColor="#008000" />
- </LinearLayout>
- <LinearLayout
- android:id="@+id/lin_sub2"
- android:layout_width="3dp"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:gravity="center" >
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="#000000"
- android:text="财经" />
- </LinearLayout>
- <LinearLayout
- android:id="@+id/lin_sub3"
- android:layout_width="3dp"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:gravity="center" >
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="#000000"
- android:text="旅游" />
- </LinearLayout>
- </LinearLayout>
- <ImageView
- android:id="@+id/imv_tabline"
- android:layout_width="100dp"
- android:layout_height="3dp"
- android:background="#FF8D42" />
- </LinearLayout>
重写 FragmentMessage
- public class FragmentMessage extends Fragment implements OnClickListener {
- private static String TAG = FragmentMessage.class.getName();
- private LinearLayout lin_sub1, lin_sub2, lin_sub3;
- private Fragment subFragment1;
- private Fragment subFragment2;
- private Fragment subFragment3;
- private ImageView mTabline;
- private int mScreen1_3;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Bundle bundle = getArguments();
- if (null != bundle) {
- //
- }
- }
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- T.showShort(getActivity(), "FragmentMessage==onCreateView");
- View view = inflater.inflate(R.layout.fragment_message1, null);
- initView(view);
- setLinstener();
- initData();
- return view;
- }
- private void initView(View view) {
- lin_sub1 = (LinearLayout) view.findViewById(R.id.lin_sub1);
- lin_sub2 = (LinearLayout) view.findViewById(R.id.lin_sub2);
- lin_sub3 = (LinearLayout) view.findViewById(R.id.lin_sub3);
- mTabline = (ImageView) view.findViewById(R.id.imv_tabline);
- }
- protected void initData() {
- // Display display = getWindow().getWindowManager().getDefaultDisplay();
- Display display = getActivity().getWindowManager().getDefaultDisplay();
- DisplayMetrics outMetrics = new DisplayMetrics();
- display.getMetrics(outMetrics);
- mScreen1_3 = outMetrics.widthPixels / 3;
- LayoutParams lp = (LayoutParams) mTabline.getLayoutParams();
- lp.width = mScreen1_3;
- mTabline.setLayoutParams(lp);
- //初次显示设置
- setSubFragment(0);
- setmTabline(0);
- }
- protected void setLinstener() {
- lin_sub1.setOnClickListener(this);
- lin_sub2.setOnClickListener(this);
- lin_sub3.setOnClickListener(this);
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.lin_sub1:
- setSubFragment(0);
- setmTabline(0);
- break;
- case R.id.lin_sub2:
- setSubFragment(1);
- setmTabline(1);
- break;
- case R.id.lin_sub3:
- setSubFragment(2);
- setmTabline(2);
- break;
- default:
- break;
- }
- }
- public void setmTabline(int i) {
- LinearLayout.LayoutParams lp = (android.widget.LinearLayout.LayoutParams) mTabline
- .getLayoutParams();
- lp.leftMargin = i * mScreen1_3;
- mTabline.setLayoutParams(lp);
- }
- public void setSubFragment(int i){
- FragmentTransaction transaction =getFragmentManager().beginTransaction();
- if(0 == i ){
- subFragment1 = (subFragment1 == null ? new SubFragment1():subFragment1);
- transaction.replace(R.id.id_content,subFragment1);
- // transaction.addToBackStack(null);
- transaction.commit();
- }else if(1 == i ){
- subFragment2 = (subFragment2 == null ? new SubFragment2():subFragment2);
- transaction.replace(R.id.id_content,subFragment2);
- // transaction.addToBackStack(null);
- transaction.commit();
- }else if(2 == i ){
- subFragment3 = (subFragment3 == null ? new SubFragment3():subFragment3);
- transaction.replace(R.id.id_content,subFragment3);
- // transaction.addToBackStack(null);
- transaction.commit();
- }
- }
- }
再添加 SubFragment1(这里只给出一个,其它类似)
- public class SubFragment1 extends Fragment {
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- T.showShort(getActivity(), "SubFragment1==onCreateView");
- TextView tv = new TextView(getActivity());
- tv.setTextSize(25);
- tv.setBackgroundColor(Color.parseColor("#FFA07A"));
- tv.setText("新闻");
- tv.setGravity(Gravity.CENTER);
- return tv;
- }
- }
好了,代码就这么简单……你会发现每次切换二级Tab导航菜单栏的时候,子Fragment会重新绘制,只需再稍微改造一下就OK了
- /*
- * 显示subFragment,subFragment不会重复onCreateView
- */
- public void showSubFragment(int i) {
- FragmentTransaction transaction = getFragmentManager()
- .beginTransaction();
- hideSubFragment(transaction);
- if (0 == i) {
- subFragment1 = (subFragment1 == null ? new SubFragment1()
- : subFragment1);
- if(!subFragment1.isAdded()){
- transaction.add(R.id.id_content, subFragment1);
- }
- // transaction.addToBackStack(null);
- transaction.show(subFragment1);
- transaction.commit();
- } else if (1 == i) {
- subFragment2 = (subFragment2 == null ? new SubFragment2()
- : subFragment2);
- if(!subFragment2.isAdded()){
- transaction.add(R.id.id_content, subFragment2);
- }
- // transaction.addToBackStack(null);
- transaction.show(subFragment2);
- transaction.commit();
- } else if (2 == i) {
- subFragment3 = (subFragment3 == null ? new SubFragment3()
- : subFragment3);
- if(!subFragment3.isAdded()){
- transaction.add(R.id.id_content, subFragment3);
- }
- // transaction.addToBackStack(null);
- transaction.show(subFragment3);
- transaction.commit();
- }
- }
- public void hideSubFragment(FragmentTransaction transaction) {
- if (subFragment1 != null) {
- transaction.hide(subFragment1);
- }
- if (subFragment2 != null) {
- transaction.hide(subFragment2);
- }
- if (subFragment3 != null) {
- transaction.hide(subFragment3);
- }
- }
几点注意的地方:
1 在transaction.add()方法时候,先判断subFragment1.isAdded(),避免该异常:java.lang.IllegalStateException: Fragment already added:
2 FragmentTransaction事务 只能执行一次commit()操作,所以定义成局部变量。
3 transaction.replace()时有一个移除操作和一个添加操作,即先remove()再add(),remove()的时候Fragment实例已经被销毁,所以在方式一种每次切换子Tab导航菜单栏,subFragment都会执行OncreateView();
4 hide()和show()方法,看字面意义就理解了。hide()只是隐藏,不会销毁,而show()就是把隐藏的显示出来。
关于Android Tab导航菜单栏--FragmentTabHost+Fragment的博客就到这里了。小生不权威,肯定有很多疏漏和出错的地方,想好好玩Android,看谷歌官方文档和Android源码才是王道。
小生这里只是写的一些超级基础的Demo,仅仅是提供思路,在实际项目开发中的情况复杂的多。
但愿小生所做的事对别人有所帮助,就算莫大的荣幸了。
Demo下载地址(子Fragment会重复onCreateView):http://download.csdn.net/detail/yalinfendou/8543999
Demo下载地址(子Fragment不会重复onCreateView):http://download.csdn.net/detail/yalinfendou/8544017

浙公网安备 33010602011771号