今天,我将总结一下Android应用中大家经常见到的底部导航栏的几种实现!
一。TabHost + RadioGroup实现方式
在我们平时开发过程中使用的TabHost是在上方,这里我们简单修改了一下<TabHost>的布局,让叶片放到了底部。
main.xml
<?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" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableTop="@drawable/home_icon" android:text="主页" /> <RadioButton android:id="@+id/rd_wt" 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" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableTop="@drawable/msg_icon" android:text="信息" /> <RadioButton android:id="@+id/rd_more" android:layout_width="wrap_content" android:layout_height="wrap_content" android:drawableTop="@drawable/more_icon" android:text="更多" /> </RadioGroup> </LinearLayout> </TabHost>
styles.xml
<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
<?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类
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:
<?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类:
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
<?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界面都需继承它)
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:
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()
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
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。