【移动开发】Android中的底部菜单框架(Fragment)
今天,我将总结一下Android应用中大家经常见到的底部导航栏的几种实现! 一。TabHost + RadioGroup实现方式 在我们平时开发过程中使用的TabHost是在上方,这里我们简单修改了一下<TabHost>的布局,让叶片放到了底部。 main.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 <?xml version= "1.0" encoding= "utf-8" ?> <TabHost xmlns:android= "http://schemas.android.com/apk/res/android" android:id= "@android:id/tabhost" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "horizontal" > <LinearLayout android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "vertical" > <TabWidget android:id= "@android:id/tabs" android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:visibility= "gone" /> <FrameLayout android:id= "@android:id/tabcontent" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:layout_weight= "1.0" /> <RadioGroup android:id= "@+id/radioGroup" android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:layout_gravity= "bottom" android:background= "@drawable/bar" android:gravity= "center_vertical" android:orientation= "horizontal" > <RadioButton android:id= "@+id/rd_home" style= "@style/main_btn_style" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:drawableTop= "@drawable/home_icon" android:text= "主页" /> <RadioButton android:id= "@+id/rd_wt" style= "@style/main_btn_style" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:drawableTop= "@drawable/wb_icon_write_n" android:text= "发表" /> <RadioButton android:id= "@+id/rd_msg" style= "@style/main_btn_style" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:drawableTop= "@drawable/msg_icon" android:text= "信息" /> <RadioButton android:id= "@+id/rd_more" style= "@style/main_btn_style" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:drawableTop= "@drawable/more_icon" android:text= "更多" /> </RadioGroup> </LinearLayout> </TabHost> styles.xml 1 2 3 4 5 6 7 8 9 <style name= "main_btn_style" > <item name= "android:button" >@ null </item> <item name= "android:textSize" >10dp</item> <item name= "android:textColor" >#ffffff</item> <item name= "android:gravity" >center_horizontal</item> <item name= "android:drawablePadding" >4dp</item> <item name= "android:layout_weight" > 1.0 </item> <item name= "android:background" >@drawable/main_btn_bg_d</item> </style> main_btn_bg_d.xml 1 2 3 4 5 <?xml version= "1.0" encoding= "utf-8" ?> <selector xmlns:android= "http://schemas.android.com/apk/res/android" > <item android:drawable= "@drawable/main_btn_bg" android:state_enabled= "true" android:state_pressed= "true" ></item> <item android:drawable= "@drawable/main_btn_bg" android:state_checked= "true" android:state_enabled= "true" ></item> </selector> 这里需要注意的是: 1.main.xml中:TabWidget的id必须是@android:id/tabs,FrameLayout的id必须是 @android:id/tabcontent。 2.把TabWidget的Visibility设置成了gone!也就是默认难看的风格不见了:,取而代之的是5个带风格的单选按钮. MainActivity类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 package com.zhf.android_tabhost; import android.app.TabActivity; import android.content.Intent; import android.os.Bundle; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; import android.widget.TabHost; import android.widget.TabHost.TabSpec; public class MainActivity extends TabActivity { private TabHost tabHost; @Override public void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.main); tabHost = this .getTabHost(); TabSpec homeSpec = tabHost.newTabSpec( "home" ).setIndicator( "home" ).setContent( new Intent( this ,HomeActivity. class )); TabSpec writeSpec = tabHost.newTabSpec( "write" ).setIndicator( "write" ).setContent( new Intent( this ,WriteActivity. class )); TabSpec msgSpec = tabHost.newTabSpec( "msg" ).setIndicator( "msg" ).setContent( new Intent( this ,MsgActivity. class )); TabSpec moreSpec = tabHost.newTabSpec( "more" ).setIndicator( "more" ).setContent( new Intent( this ,MoreActivity. class )); tabHost.addTab(homeSpec); tabHost.addTab(writeSpec); tabHost.addTab(msgSpec); tabHost.addTab(moreSpec); RadioGroup rg = (RadioGroup) this .findViewById(R.id.radioGroup); rg.setOnCheckedChangeListener( new OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { switch (checkedId) { case R.id.rd_home: tabHost.setCurrentTabByTag( "home" ); break ; case R.id.rd_wt: tabHost.setCurrentTabByTag( "write" ); break ; case R.id.rd_msg: tabHost.setCurrentTabByTag( "msg" ); break ; case R.id.rd_more: tabHost.setCurrentTabByTag( "more" ); break ; default : break ; } } }); } } 注: 1.由于TabWidget被隐藏,所以相关的事件也会无效,这里取巧用RadioGroup与RadioButton的特性来处理切换,然后监听事件调用setCurrentTabByTag来切换Activity。 2.注意即使TabWidget被隐藏,也要为其设置indicator,否则会保持。 效果图: (点击底部就可以实现切换不同的Activity的操作了,这里需要注意的一点是,切换底部菜单时不会重新调用onCreate()方法的!!) 二.底部回调接口实现(使用Fragment)--- 重要! 这种方式使用了最新的Fragment,采用了底部导航栏回调接口的方法,来切换底部菜单,并且每次切换回重新调用onCreate()方法!! main.xml: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <?xml version= "1.0" encoding= "utf-8" ?> <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http://schemas.android.com/tools" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "vertical" tools:context= ".MainActivity" > <LinearLayout android:layout_width= "fill_parent" android:layout_height= "0dp" android:layout_weight= "10" android:orientation= "vertical" > <RelativeLayout android:id= "@+id/main_title_RelativeLayout" android:layout_width= "fill_parent" android:layout_height= "50dp" android:background= "@drawable/fragment_bottom_normal" android:orientation= "horizontal" > <TextView android:id= "@+id/main_title_TextView" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:layout_centerInParent= "true" android:text= "主页" android:textColor= "@android:color/white" android:textSize= "24sp" /> </RelativeLayout> <FrameLayout android:id= "@+id/main_detail_FrameLayout" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:background= "#ffffff" > </FrameLayout> </LinearLayout> <fragment android:id= "@+id/bottom_fragment" android:name= "com.zhf.frameworkdemo02.fragments.BottomFragment" android:layout_width= "fill_parent" android:layout_height= "0dp" android:layout_weight= "1" /> </LinearLayout> 这里由于我们底部菜单我们采用了fragment,所以布局里面要留出位置! BottomFragment类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 package com.zhf.frameworkdemo02.fragments; import com.zhf.frameworkdemo02.R; 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; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; /** * 页面底部导航栏 * * @author ZHF * */ public class BottomFragment extends Fragment { //默认回调接口实现类的对象 private Callbacks callbacks = defaultCallbacks; /** Fragment和Activity建立关联的时候调用 **/ @Override public void onAttach(Activity activity) { super .onAttach(activity); //当前类是否实现了底部导航栏点击事件回调接口 if (!(activity instanceof Callbacks)) { throw new IllegalStateException( "Activity must implements fragment's callbacks !" ); } callbacks = (Callbacks) activity; } /** 为Fragment加载布局时调用 **/ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { RadioGroup radioGroup = (RadioGroup) inflater.inflate(R.layout.fragment_bottom, container, false ); //绑定监听器 radioGroup.setOnCheckedChangeListener(changeListener); return radioGroup; } /**RadioGroup监听器**/ private OnCheckedChangeListener changeListener = new OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { System.out.println(checkedId); callbacks.onItemSelected(checkedId); //调用接口中方法 } }; public interface Callbacks{ /**导航栏回调接口**/ public void onItemSelected( int item); } /**默认回调实现类的对象**/ private static Callbacks defaultCallbacks = new Callbacks() { @Override public void onItemSelected( int item) { //什么都不干 } }; /**Fragment和Activity解除关联的时候调用**/ @Override public void onDetach() { super .onDetach(); callbacks = defaultCallbacks; } } 底部菜单布局fragment_bottom.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 <?xml version= "1.0" encoding= "utf-8" ?> <RadioGroup xmlns:android= "http://schemas.android.com/apk/res/android" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "horizontal" > <RadioButton android:id= "@+id/fragment_bottom_home" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:layout_weight= "1" android:background= "@drawable/fragment_bottom_selector" android:button= "@null" android:drawableTop= "@drawable/main_readiobutton_home" android:gravity= "center" android:text= "@string/home" android:textColor= "@color/white" android:textSize= "12sp" /> <View android:layout_width= "1dp" android:layout_height= "fill_parent" android:background= "@color/white" /> <RadioButton android:id= "@+id/fragment_bottom_order" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:layout_weight= "1" android:background= "@drawable/fragment_bottom_selector" android:button= "@null" android:drawableTop= "@drawable/main_readiobutton_order" android:gravity= "center" android:text= "@string/order" android:textColor= "@color/white" android:textSize= "12sp" /> <View android:layout_width= "1dp" android:layout_height= "fill_parent" android:background= "@color/white" /> <RadioButton android:id= "@+id/fragment_bottom_notice" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:layout_weight= "1" android:background= "@drawable/fragment_bottom_selector" android:button= "@null" android:drawableTop= "@drawable/main_readiobutton_notice" android:gravity= "center" android:text= "@string/notice" android:textColor= "@color/white" android:textSize= "12sp" /> <View android:layout_width= "1dp" android:layout_height= "fill_parent" android:background= "@color/white" /> <RadioButton android:id= "@+id/fragment_bottom_more" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:layout_weight= "1" android:background= "@drawable/fragment_bottom_selector" android:button= "@null" android:drawablePadding= "3dip" android:drawableTop= "@drawable/main_readiobutton_more" android:gravity= "center" android:text= "@string/more" android:textColor= "@color/white" android:textSize= "12sp" /> </RadioGroup> 这里我们定义了一个框架类:GeneralFragment(所有的fragment界面都需继承它) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 package com.zhf.frameworkdemo02.fragments; import java.io.Serializable; import com.zhf.frameworkdemo02.R; import com.zhf.frameworkdemo02.view.OrderView; import com.zhf.frameworkdemo02.view.HomeView; import com.zhf.frameworkdemo02.view.MoreView; import com.zhf.frameworkdemo02.view.NoticeView; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; /** * 框架类,抽象公共方法 * @author ZHF * */ public class GeneralFragment extends Fragment implements Serializable{ /** * */ private static final long serialVersionUID = 1L; private int item; //用于区分底部菜单项 protected static View main_title_RelativeLayout; //标题栏 protected final static String key = "Bundle" ; //跳转值传递key的名称 @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super .onCreate(savedInstanceState); if (getArguments() != null ) { //根据接收子类传来的arguments判断item的哪一项 if (getArguments().containsKey(MainFragment.Item)) { item = getArguments().getInt(MainFragment.Item); } } } /**为Fragment加载布局时调用 **/ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_general, container, false ); GeneralFragment fragment = null ; switch (item) { case R.id.fragment_bottom_home: //初始化主页 fragment = new HomeView(); break ; case R.id.fragment_bottom_order: fragment = new OrderView(); //初始化订单 break ; case R.id.fragment_bottom_notice: fragment = new NoticeView(); //初始化公告 break ; case R.id.fragment_bottom_more: fragment = new MoreView(); //初始化更多 break ; default : break ; } if (fragment != null ) { //更换mainView中间的内容(home,msg,at,more) getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.general_fragment, fragment).commit(); } main_title_RelativeLayout = ((View) container.getParent()).findViewById(R.id.main_title_RelativeLayout); //将生成的view返回 return view; } /**设置标题**/ protected void setTitle(Object title) { if (main_title_RelativeLayout != null ) { //标题栏中的文字 TextView mTvTitle = (TextView) main_title_RelativeLayout.findViewById(R.id.main_title_TextView); if (mTvTitle != null ) { if (title instanceof Integer) { //整型 mTvTitle.setText((Integer)title); } else { //字符类型 mTvTitle.setText((CharSequence)title); } } } } /**页面跳转值传递**/ protected void setBundle(Object... objects) { Bundle arguments = new Bundle(); arguments.putSerializable(key, objects); GeneralFragment generalFragment = new GeneralFragment(); generalFragment.setArguments(arguments); } /**获取所传递的值**/ protected Object[] getBundle() { if (getArguments() != null ) { System.out.println( "getBundle" ); if (getArguments().containsKey(key)) { Object[] object = (Object[]) getArguments().getSerializable(key); return object; } } return null ; } /**无参页面跳转**/ protected void toIntent(GeneralFragment generalFragment) { if (generalFragment != null ) { getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.general_fragment, generalFragment).commit(); } } } 程序入口MainFragment: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package com.zhf.frameworkdemo02.fragments; import com.zhf.frameworkdemo02.R; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; /** *MainView * @author ZHF * */ public class MainFragment extends FragmentActivity implements BottomFragment.Callbacks { public final static String Item = "item" ; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super .onCreate(savedInstanceState); setContentView(R.layout.main); //初始化默认调用接口中item选中方法 onItemSelected(R.id.fragment_bottom_home); } @Override public void onItemSelected( int item) { Bundle arguments = new Bundle(); arguments.putInt(Item, item); //将选中的底部radio的Id放进去 GeneralFragment generalFragment = new GeneralFragment(); generalFragment.setArguments(arguments); //设置参数值 //这里根据item的ID进行界面跳转 FragmentManager fm = getSupportFragmentManager(); fm.beginTransaction().replace(R.id.main_detail_FrameLayout, generalFragment).commit(); } } 说明:这里我们的每个界面都将采用Fragment,故每个界面需重写onCreateView() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.zhf.frameworkdemo02.view; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.zhf.frameworkdemo02.R; import com.zhf.frameworkdemo02.fragments.GeneralFragment; /** * 主页面 * @author ZHF * */ public class HomeView extends GeneralFragment{ @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super .onCreate(savedInstanceState); super .setTitle( "主页" ); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.home, container, false ); } } (其他三个略) 最终效果图: ok!大功告成!相当实用的!有兴趣的可以学习一下! 源码下载:http://down.51cto.com/data/1009354 今天,我将总结一下Android应用中大家经常见到的底部导航栏的几种实现! 一。TabHost + RadioGroup实现方式 在我们平时开发过程中使用的TabHost是在上方,这里我们简单修改了一下<TabHost>的布局,让叶片放到了底部。 main.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 <?xml version= "1.0" encoding= "utf-8" ?> <TabHost xmlns:android= "http://schemas.android.com/apk/res/android" android:id= "@android:id/tabhost" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "horizontal" > <LinearLayout android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "vertical" > <TabWidget android:id= "@android:id/tabs" android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:visibility= "gone" /> <FrameLayout android:id= "@android:id/tabcontent" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:layout_weight= "1.0" /> <RadioGroup android:id= "@+id/radioGroup" android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:layout_gravity= "bottom" android:background= "@drawable/bar" android:gravity= "center_vertical" android:orientation= "horizontal" > <RadioButton android:id= "@+id/rd_home" style= "@style/main_btn_style" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:drawableTop= "@drawable/home_icon" android:text= "主页" /> <RadioButton android:id= "@+id/rd_wt" style= "@style/main_btn_style" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:drawableTop= "@drawable/wb_icon_write_n" android:text= "发表" /> <RadioButton android:id= "@+id/rd_msg" style= "@style/main_btn_style" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:drawableTop= "@drawable/msg_icon" android:text= "信息" /> <RadioButton android:id= "@+id/rd_more" style= "@style/main_btn_style" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:drawableTop= "@drawable/more_icon" android:text= "更多" /> </RadioGroup> </LinearLayout> </TabHost> styles.xml 1 2 3 4 5 6 7 8 9 <style name= "main_btn_style" > <item name= "android:button" >@ null </item> <item name= "android:textSize" >10dp</item> <item name= "android:textColor" >#ffffff</item> <item name= "android:gravity" >center_horizontal</item> <item name= "android:drawablePadding" >4dp</item> <item name= "android:layout_weight" > 1.0 </item> <item name= "android:background" >@drawable/main_btn_bg_d</item> </style> main_btn_bg_d.xml 1 2 3 4 5 <?xml version= "1.0" encoding= "utf-8" ?> <selector xmlns:android= "http://schemas.android.com/apk/res/android" > <item android:drawable= "@drawable/main_btn_bg" android:state_enabled= "true" android:state_pressed= "true" ></item> <item android:drawable= "@drawable/main_btn_bg" android:state_checked= "true" android:state_enabled= "true" ></item> </selector> 这里需要注意的是: 1.main.xml中:TabWidget的id必须是@android:id/tabs,FrameLayout的id必须是 @android:id/tabcontent。 2.把TabWidget的Visibility设置成了gone!也就是默认难看的风格不见了:,取而代之的是5个带风格的单选按钮. MainActivity类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 package com.zhf.android_tabhost; import android.app.TabActivity; import android.content.Intent; import android.os.Bundle; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; import android.widget.TabHost; import android.widget.TabHost.TabSpec; public class MainActivity extends TabActivity { private TabHost tabHost; @Override public void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.main); tabHost = this .getTabHost(); TabSpec homeSpec = tabHost.newTabSpec( "home" ).setIndicator( "home" ).setContent( new Intent( this ,HomeActivity. class )); TabSpec writeSpec = tabHost.newTabSpec( "write" ).setIndicator( "write" ).setContent( new Intent( this ,WriteActivity. class )); TabSpec msgSpec = tabHost.newTabSpec( "msg" ).setIndicator( "msg" ).setContent( new Intent( this ,MsgActivity. class )); TabSpec moreSpec = tabHost.newTabSpec( "more" ).setIndicator( "more" ).setContent( new Intent( this ,MoreActivity. class )); tabHost.addTab(homeSpec); tabHost.addTab(writeSpec); tabHost.addTab(msgSpec); tabHost.addTab(moreSpec); RadioGroup rg = (RadioGroup) this .findViewById(R.id.radioGroup); rg.setOnCheckedChangeListener( new OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { switch (checkedId) { case R.id.rd_home: tabHost.setCurrentTabByTag( "home" ); break ; case R.id.rd_wt: tabHost.setCurrentTabByTag( "write" ); break ; case R.id.rd_msg: tabHost.setCurrentTabByTag( "msg" ); break ; case R.id.rd_more: tabHost.setCurrentTabByTag( "more" ); break ; default : break ; } } }); } } 注: 1.由于TabWidget被隐藏,所以相关的事件也会无效,这里取巧用RadioGroup与RadioButton的特性来处理切换,然后监听事件调用setCurrentTabByTag来切换Activity。 2.注意即使TabWidget被隐藏,也要为其设置indicator,否则会保持。 效果图: (点击底部就可以实现切换不同的Activity的操作了,这里需要注意的一点是,切换底部菜单时不会重新调用onCreate()方法的!!) 二.底部回调接口实现(使用Fragment)--- 重要! 这种方式使用了最新的Fragment,采用了底部导航栏回调接口的方法,来切换底部菜单,并且每次切换回重新调用onCreate()方法!! main.xml: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <?xml version= "1.0" encoding= "utf-8" ?> <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http://schemas.android.com/tools" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "vertical" tools:context= ".MainActivity" > <LinearLayout android:layout_width= "fill_parent" android:layout_height= "0dp" android:layout_weight= "10" android:orientation= "vertical" > <RelativeLayout android:id= "@+id/main_title_RelativeLayout" android:layout_width= "fill_parent" android:layout_height= "50dp" android:background= "@drawable/fragment_bottom_normal" android:orientation= "horizontal" > <TextView android:id= "@+id/main_title_TextView" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:layout_centerInParent= "true" android:text= "主页" android:textColor= "@android:color/white" android:textSize= "24sp" /> </RelativeLayout> <FrameLayout android:id= "@+id/main_detail_FrameLayout" android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:background= "#ffffff" > </FrameLayout> </LinearLayout> <fragment android:id= "@+id/bottom_fragment" android:name= "com.zhf.frameworkdemo02.fragments.BottomFragment" android:layout_width= "fill_parent" android:layout_height= "0dp" android:layout_weight= "1" /> </LinearLayout> 这里由于我们底部菜单我们采用了fragment,所以布局里面要留出位置! BottomFragment类: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 package com.zhf.frameworkdemo02.fragments; import com.zhf.frameworkdemo02.R; 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; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; /** * 页面底部导航栏 * * @author ZHF * */ public class BottomFragment extends Fragment { //默认回调接口实现类的对象 private Callbacks callbacks = defaultCallbacks; /** Fragment和Activity建立关联的时候调用 **/ @Override public void onAttach(Activity activity) { super .onAttach(activity); //当前类是否实现了底部导航栏点击事件回调接口 if (!(activity instanceof Callbacks)) { throw new IllegalStateException( "Activity must implements fragment's callbacks !" ); } callbacks = (Callbacks) activity; } /** 为Fragment加载布局时调用 **/ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { RadioGroup radioGroup = (RadioGroup) inflater.inflate(R.layout.fragment_bottom, container, false ); //绑定监听器 radioGroup.setOnCheckedChangeListener(changeListener); return radioGroup; }