Android中的底部菜单框架(Fragment)

今天,我将总结一下Android应用中大家经常见到的底部导航栏的几种实现!

 

一。TabHost + RadioGroup实现方式

在我们平时开发过程中使用的TabHost是在上方,这里我们简单修改了一下<TabHost>的布局,让叶片放到了底部。

main.xml


01. <?xml version="1.0" encoding="utf-8"?> 
02. <TabHost xmlns:android="http://schemas.android.com/apk/res/android"
03.     android:id="@android:id/tabhost"
04.     android:layout_width="fill_parent"
05.     android:layout_height="fill_parent"
06.     android:orientation="horizontal"
07.     <LinearLayout 
08.         android:layout_width="fill_parent"
09.         android:layout_height="fill_parent"
10.         android:orientation="vertical"
11.         <TabWidget 
12.             android:id="@android:id/tabs"
13.             android:layout_width="fill_parent"
14.             android:layout_height="wrap_content"
15.             android:visibility="gone" /> 
16.         <FrameLayout 
17.             android:id="@android:id/tabcontent"
18.             android:layout_width="fill_parent"
19.             android:layout_height="fill_parent"
20.             android:layout_weight="1.0" /> 
21.         <RadioGroup 
22.             android:id="@+id/radioGroup"
23.             android:layout_width="fill_parent"
24.             android:layout_height="wrap_content"
25.             android:layout_gravity="bottom"
26.             android:background="@drawable/bar"
27.             android:gravity="center_vertical"
28.             android:orientation="horizontal"
29.             <RadioButton 
30.                 android:id="@+id/rd_home"
31.                 style="@style/main_btn_style"
32.                 android:layout_width="wrap_content"
33.                 android:layout_height="wrap_content"
34.                 android:drawableTop="@drawable/home_icon"
35.                 android:text="主页" /> 
36.             <RadioButton 
37.                 android:id="@+id/rd_wt"
38.                 style="@style/main_btn_style"
39.                 android:layout_width="wrap_content"
40.                 android:layout_height="wrap_content"
41.                 android:drawableTop="@drawable/wb_icon_write_n"
42.                 android:text="发表" /> 
43.             <RadioButton 
44.                 android:id="@+id/rd_msg"
45.                 style="@style/main_btn_style"
46.                 android:layout_width="wrap_content"
47.                 android:layout_height="wrap_content"
48.                 android:drawableTop="@drawable/msg_icon"
49.                 android:text="信息" /> 
50.             <RadioButton 
51.                 android:id="@+id/rd_more"
52.                 style="@style/main_btn_style"
53.                 android:layout_width="wrap_content"
54.                 android:layout_height="wrap_content"
55.                 android:drawableTop="@drawable/more_icon"
56.                 android:text="更多" /> 
57.         </RadioGroup
58.     </LinearLayout
59. </TabHost>

styles.xml

 

01. <style name="main_btn_style"
02.        <item name="android:button">@null</item
03.        <item name="android:textSize">10dp</item
04.        <item name="android:textColor">#ffffff</item
05.        <item name="android:gravity">center_horizontal</item
06.        <item name="android:drawablePadding">4dp</item
07.        <item name="android:layout_weight">1.0</item
08.        <item name="android:background">@drawable/main_btn_bg_d</item
09.    </style>

main_btn_bg_d.xml
 

1. <?xml version="1.0" encoding="utf-8"?> 
2. <selector xmlns:android="http://schemas.android.com/apk/res/android"
3.     <item android:drawable="@drawable/main_btn_bg" android:state_enabled="true" android:state_pressed="true"></item
4.     <item android:drawable="@drawable/main_btn_bg" android:state_checked="true" android:state_enabled="true"></item
5. </selector>

这里需要注意的是:

1.main.xml中:TabWidget的id必须是@android:id/tabs,FrameLayout的id必须是 @android:id/tabcontent。

2.把TabWidget的Visibility设置成了gone!也就是默认难看的风格不见了2011-3-1_2.jpg取而代之的是5个带风格的单选按钮.

 

MainActivity类


01. package com.zhf.android_tabhost; 
02. import android.app.TabActivity; 
03. import android.content.Intent; 
04. import android.os.Bundle; 
05. import android.widget.RadioGroup; 
06. import android.widget.RadioGroup.OnCheckedChangeListener; 
07. import android.widget.TabHost; 
08. import android.widget.TabHost.TabSpec; 
09. public class MainActivity extends TabActivity { 
10.     private TabHost tabHost; 
11.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
12.     @Override 
13.     public void onCreate(Bundle savedInstanceState) { 
14.         super.onCreate(savedInstanceState); 
15.         setContentView(R.layout.main); 
16.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
17.         tabHost = this.getTabHost(); 
18.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
19.         TabSpec homeSpec = tabHost.newTabSpec("home").setIndicator("home").setContent(new Intent(this,HomeActivity.class)); 
20.         TabSpec writeSpec = tabHost.newTabSpec("write").setIndicator("write").setContent(new Intent(this,WriteActivity.class)); 
21.         TabSpec msgSpec = tabHost.newTabSpec("msg").setIndicator("msg").setContent(new Intent(this,MsgActivity.class)); 
22.         TabSpec moreSpec = tabHost.newTabSpec("more").setIndicator("more").setContent(new Intent(this,MoreActivity.class)); 
23.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
24.         tabHost.addTab(homeSpec); 
25.         tabHost.addTab(writeSpec); 
26.         tabHost.addTab(msgSpec); 
27.         tabHost.addTab(moreSpec); 
28.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
29.         RadioGroup rg = (RadioGroup) this.findViewById(R.id.radioGroup); 
30.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
31.         rg.setOnCheckedChangeListener(new OnCheckedChangeListener() { 
32.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
33.             @Override 
34.             public void onCheckedChanged(RadioGroup group, int checkedId) { 
35.                 switch (checkedId) { 
36.                 case R.id.rd_home: 
37.                     tabHost.setCurrentTabByTag("home"); 
38.                     break
39.                 case R.id.rd_wt: 
40.                     tabHost.setCurrentTabByTag("write"); 
41.                     break
42.                 case R.id.rd_msg: 
43.                     tabHost.setCurrentTabByTag("msg"); 
44.                     break
45.                 case R.id.rd_more: 
46.                     tabHost.setCurrentTabByTag("more"); 
47.                     break
48.                 default
49.                     break
50.                 
51.             
52.         }); 
53.     
54. }

注:

1.由于TabWidget被隐藏,所以相关的事件也会无效,这里取巧用RadioGroup与RadioButton的特性来处理切换,然后监听事件调用setCurrentTabByTag来切换Activity。

2.注意即使TabWidget被隐藏,也要为其设置indicator,否则会保持。

效果图:

174435324.png

点击底部就可以实现切换不同的Activity的操作了,这里需要注意的一点是,切换底部菜单时不会重新调用onCreate()方法的!!)

 

 

二.底部回调接口实现(使用Fragment)--- 重要!

 

这种方式使用了最新的Fragment,采用了底部导航栏回调接口的方法,来切换底部菜单,并且每次切换回重新调用onCreate()方法!!

 

main.xml:


01. <?xml version="1.0" encoding="utf-8"?> 
02. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
03.     xmlns:tools="http://schemas.android.com/tools"
04.     android:layout_width="fill_parent"
05.     android:layout_height="fill_parent"
06.     android:orientation="vertical"
07.     tools:context=".MainActivity"
08.     <LinearLayout 
09.         android:layout_width="fill_parent"
10.         android:layout_height="0dp"
11.         android:layout_weight="10"
12.         android:orientation="vertical"
13.         <RelativeLayout 
14.             android:id="@+id/main_title_RelativeLayout"
15.             android:layout_width="fill_parent"
16.             android:layout_height="50dp"
17.             android:background="@drawable/fragment_bottom_normal"
18.             android:orientation="horizontal"
19.             <TextView 
20.                 android:id="@+id/main_title_TextView"
21.                 android:layout_width="wrap_content"
22.                 android:layout_height="wrap_content"
23.                 android:layout_centerInParent="true"
24.                 android:text="主页"
25.                 android:textColor="@android:color/white"
26.                 android:textSize="24sp" /> 
27.         </RelativeLayout
28.         <FrameLayout 
29.             android:id="@+id/main_detail_FrameLayout"
30.             android:layout_width="fill_parent"
31.             android:layout_height="fill_parent"
32.             android:background="#ffffff"
33.         </FrameLayout
34.     </LinearLayout
35.     <fragment 
36.         android:id="@+id/bottom_fragment"
37.         android:name="com.zhf.frameworkdemo02.fragments.BottomFragment"
38.         android:layout_width="fill_parent"
39.         android:layout_height="0dp"
40.         android:layout_weight="1" /> 
41. </LinearLayout>

这里由于我们底部菜单我们采用了fragment,所以布局里面要留出位置!

 

BottomFragment类:


01. package com.zhf.frameworkdemo02.fragments; 
02. import com.zhf.frameworkdemo02.R; 
03. import android.app.Activity; 
04. import android.os.Bundle; 
05. import android.support.v4.app.Fragment; 
06. import android.view.LayoutInflater; 
07. import android.view.View; 
08. import android.view.ViewGroup; 
09. import android.widget.RadioGroup; 
10. import android.widget.RadioGroup.OnCheckedChangeListener; 
11. /** 
12.  * 页面底部导航栏 
13.  
14.  * @author ZHF 
15.  
16.  */
17. public class BottomFragment extends Fragment { 
18.     //默认回调接口实现类的对象 
19.     private Callbacks callbacks = defaultCallbacks; 
20.     /** Fragment和Activity建立关联的时候调用 **/
21.     @Override 
22.     public void onAttach(Activity activity) { 
23.         super.onAttach(activity); 
24.         //当前类是否实现了底部导航栏点击事件回调接口 
25.         if(!(activity instanceof Callbacks)) { 
26.             throw new IllegalStateException("Activity must implements fragment's callbacks !"); 
27.         
28.         callbacks = (Callbacks) activity; 
29.     
30.     /** 为Fragment加载布局时调用 **/
31.     @Override 
32.     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
33.             Bundle savedInstanceState) { 
34.         RadioGroup radioGroup = (RadioGroup) inflater.inflate(R.layout.fragment_bottom, container, false); 
35.         //绑定监听器 
36.         radioGroup.setOnCheckedChangeListener(changeListener); 
37.         return radioGroup; 
38.     
39.                                                                                                                                                                                                                                                                                                                       
40.     /**RadioGroup监听器**/
41.     private OnCheckedChangeListener changeListener = new OnCheckedChangeListener() { 
42.         @Override 
43.         public void onCheckedChanged(RadioGroup group, int checkedId) { 
44.             System.out.println(checkedId); 
45.             callbacks.onItemSelected(checkedId); //调用接口中方法 
46.         
47.     }; 
48.     public interface Callbacks{ 
49.         /**导航栏回调接口**/
50.         public void onItemSelected(int item); 
51.     
52.     /**默认回调实现类的对象**/
53.     private static Callbacks defaultCallbacks = new Callbacks() { 
54.         @Override 
55.         public void onItemSelected(int item) { 
56.         //什么都不干 
57.         
58.     }; 
59.                                                                                                                                                                                                                                                                                                                       
60.     /**Fragment和Activity解除关联的时候调用**/
61.     @Override 
62.     public void onDetach() { 
63.         super.onDetach(); 
64.        callbacks = defaultCallbacks; 
65.     
66. }

底部菜单布局fragment_bottom.xml
 

01. <?xml version="1.0" encoding="utf-8"?> 
02. <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
03.     android:layout_width="fill_parent"
04.     android:layout_height="fill_parent"
05.     android:orientation="horizontal"
06.     <RadioButton 
07.         android:id="@+id/fragment_bottom_home"
08.         android:layout_width="fill_parent"
09.         android:layout_height="fill_parent"
10.         android:layout_weight="1"
11.         android:background="@drawable/fragment_bottom_selector"
12.         android:button="@null"
13.         android:drawableTop="@drawable/main_readiobutton_home"
14.         android:gravity="center"
15.         android:text="@string/home"
16.         android:textColor="@color/white"
17.         android:textSize="12sp" /> 
18.     <View 
19.         android:layout_width="1dp"
20.         android:layout_height="fill_parent"
21.         android:background="@color/white" /> 
22.     <RadioButton 
23.         android:id="@+id/fragment_bottom_order"
24.         android:layout_width="fill_parent"
25.         android:layout_height="fill_parent"
26.         android:layout_weight="1"
27.         android:background="@drawable/fragment_bottom_selector"
28.         android:button="@null"
29.         android:drawableTop="@drawable/main_readiobutton_order"
30.         android:gravity="center"
31.         android:text="@string/order"
32.         android:textColor="@color/white"
33.         android:textSize="12sp" /> 
34.     <View 
35.         android:layout_width="1dp"
36.         android:layout_height="fill_parent"
37.         android:background="@color/white"
38.         /> 
39.     <RadioButton 
40.         android:id="@+id/fragment_bottom_notice"
41.         android:layout_width="fill_parent"
42.         android:layout_height="fill_parent"
43.         android:layout_weight="1"
44.         android:background="@drawable/fragment_bottom_selector"
45.         android:button="@null"
46.         android:drawableTop="@drawable/main_readiobutton_notice"
47.         android:gravity="center"
48.         android:text="@string/notice"
49.         android:textColor="@color/white"
50.         android:textSize="12sp" /> 
51.     <View 
52.         android:layout_width="1dp"
53.         android:layout_height="fill_parent"
54.         android:background="@color/white" /> 
55.     <RadioButton 
56.         android:id="@+id/fragment_bottom_more"
57.         android:layout_width="fill_parent"
58.         android:layout_height="fill_parent"
59.         android:layout_weight="1"
60.         android:background="@drawable/fragment_bottom_selector"
61.         android:button="@null"
62.         android:drawablePadding="3dip"
63.         android:drawableTop="@drawable/main_readiobutton_more"
64.         android:gravity="center"
65.         android:text="@string/more"
66.         android:textColor="@color/white"
67.         android:textSize="12sp" /> 
68. </RadioGroup>

这里我们定义了一个框架类:GeneralFragment(所有的fragment界面都需继承它)

 

001. package com.zhf.frameworkdemo02.fragments; 
002. import java.io.Serializable; 
003. import com.zhf.frameworkdemo02.R; 
004. import com.zhf.frameworkdemo02.view.OrderView; 
005. import com.zhf.frameworkdemo02.view.HomeView; 
006. import com.zhf.frameworkdemo02.view.MoreView; 
007. import com.zhf.frameworkdemo02.view.NoticeView; 
008. import android.os.Bundle; 
009. import android.support.v4.app.Fragment; 
010. import android.view.LayoutInflater; 
011. import android.view.View; 
012. import android.view.ViewGroup; 
013. import android.widget.TextView; 
014. /** 
015.  * 框架类,抽象公共方法 
016.  * @author ZHF 
017.  
018.  */
019. public class GeneralFragment extends Fragment implements Serializable{ 
020.     /** 
021.      
022.      */
023.     private static final long serialVersionUID = 1L; 
024.                                                                                                                                                                                                                                                                   
025.     private int item; //用于区分底部菜单项 
026.     protected static View main_title_RelativeLayout; //标题栏 
027.     protected final static String key = "Bundle";   //跳转值传递key的名称 
028.                                                                                                                                                                                                                                                                   
029.     @Override
030.     public void onCreate(Bundle savedInstanceState) { 
031.         // TODO Auto-generated method stub 
032.         super.onCreate(savedInstanceState); 
033.         if(getArguments() != null) {  //根据接收子类传来的arguments判断item的哪一项 
034.             if(getArguments().containsKey(MainFragment.Item)) { 
035.                 item = getArguments().getInt(MainFragment.Item); 
036.             
037.         
038.     
039.                                                                                                                                                                                                                                                                   
040.     /**为Fragment加载布局时调用 **/
041.     @Override
042.     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
043.             Bundle savedInstanceState) { 
044.         View view = inflater.inflate(R.layout.fragment_general, container, false); 
045.         GeneralFragment fragment = null
046.         switch(item) { 
047.         case R.id.fragment_bottom_home:  //初始化主页 
048.             fragment = new HomeView(); 
049.             break
050.         case R.id.fragment_bottom_order: 
051.             fragment = new OrderView();  //初始化订单 
052.              break
053.         case R.id.fragment_bottom_notice: 
054.             fragment = new NoticeView();   //初始化公告 
055.             break
056.         case R.id.fragment_bottom_more: 
057.             fragment = new MoreView();  //初始化更多 
058.             break
059.         default
060.             break
061.         
062.         if(fragment != null) { 
063.             //更换mainView中间的内容(home,msg,at,more) 
064.             getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.general_fragment, fragment).commit(); 
065.         
066.         main_title_RelativeLayout =  ((View) container.getParent()).findViewById(R.id.main_title_RelativeLayout); 
067.         //将生成的view返回 
068.         return view; 
069.     
070.                                                                                                                                                                                                                                                                   
071.     /**设置标题**/
072.     protected void setTitle(Object title) { 
073.         if(main_title_RelativeLayout != null) { 
074.             //标题栏中的文字 
075.             TextView mTvTitle = (TextView) main_title_RelativeLayout.findViewById(R.id.main_title_TextView); 
076.             if(mTvTitle != null) { 
077.                 if(title instanceof Integer) {  //整型 
078.                     mTvTitle.setText((Integer)title); 
079.                 } else { //字符类型 
080.                     mTvTitle.setText((CharSequence)title); 
081.                 
082.             
083.         
084.     
085.                                                                                                                                                                                                                                                                   
086.     /**页面跳转值传递**/
087.     protected void setBundle(Object... objects) { 
088.         Bundle arguments = new Bundle(); 
089.         arguments.putSerializable(key, objects); 
090.         GeneralFragment generalFragment = new GeneralFragment(); 
091.         generalFragment.setArguments(arguments); 
092.     
093.                                                                                                                                                                                                                                                                   
094.     /**获取所传递的值**/
095.     protected Object[] getBundle() { 
096.         if(getArguments() != null) { 
097.             System.out.println("getBundle"); 
098.             if(getArguments().containsKey(key)) { 
099.                 Object[] object = (Object[]) getArguments().getSerializable(key); 
100.                 return object; 
101.             
102.         
103.         return null
104.     
105.                                                                                                                                                                                                                                                                   
106.     /**无参页面跳转**/
107.     protected void toIntent(GeneralFragment generalFragment) { 
108.         if(generalFragment != null) { 
109.             getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.general_fragment, generalFragment).commit(); 
110.         
111.     
112. }

程序入口MainFragment:

 

01. package com.zhf.frameworkdemo02.fragments; 
02. import com.zhf.frameworkdemo02.R; 
03. import android.os.Bundle; 
04. import android.support.v4.app.FragmentActivity; 
05. import android.support.v4.app.FragmentManager; 
06. /** 
07.  *MainView 
08.  * @author ZHF 
09.  
10.  */
11. public class MainFragment extends FragmentActivity implements BottomFragment.Callbacks { 
12.                                                                                                                                                                                                                                      
13.     public final static String Item = "item"
14.                                                                                                                                                                                                                                      
15.     @Override 
16.     protected void onCreate(Bundle savedInstanceState) { 
17.         // TODO Auto-generated method stub 
18.         super.onCreate(savedInstanceState); 
19.         setContentView(R.layout.main); 
20.         //初始化默认调用接口中item选中方法 
21.         onItemSelected(R.id.fragment_bottom_home); 
22.     
23.     @Override 
24.     public void onItemSelected(int item) { 
25.         Bundle arguments = new Bundle(); 
26.         arguments.putInt(Item, item); //将选中的底部radio的Id放进去 
27.         GeneralFragment generalFragment = new GeneralFragment(); 
28.         generalFragment.setArguments(arguments); //设置参数值 
29.         //这里根据item的ID进行界面跳转 
30.         FragmentManager fm = getSupportFragmentManager(); 
31.         fm.beginTransaction().replace(R.id.main_detail_FrameLayout, generalFragment).commit(); 
32.     
33. }

说明:这里我们的每个界面都将采用Fragment,故每个界面需重写onCreateView()

 

01. package com.zhf.frameworkdemo02.view; 
02. import android.os.Bundle; 
03. import android.view.LayoutInflater; 
04. import android.view.View; 
05. import android.view.ViewGroup; 
06. import com.zhf.frameworkdemo02.R; 
07. import com.zhf.frameworkdemo02.fragments.GeneralFragment; 
08. /** 
09.  * 主页面 
10.  * @author ZHF 
11.  
12.  */
13. public class HomeView extends GeneralFragment{ 
14.     @Override 
15.     public void onCreate(Bundle savedInstanceState) { 
16.         // TODO Auto-generated method stub 
17.         super.onCreate(savedInstanceState); 
18.         super.setTitle("主页"); 
19.     
20.                                                                                                                                                   
21.     @Override 
22.     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
23.             Bundle savedInstanceState) { 
24.         return inflater.inflate(R.layout.home, container, false); 
25.     
26. }

(其他三个略)

最终效果图:

225533378.png

 

ok!大功告成!相当实用的!有兴趣的可以学习一下!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值