今天,我将总结一下Android应用中大家经常见到的底部导航栏的几种实现!
一。TabHost + RadioGroup实现方式
在我们平时开发过程中使用的TabHost是在上方,这里我们简单修改了一下
main.xml
styles.xml
main_btn_bg_d.xml
这里需要注意的是:
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:
这里由于我们底部菜单我们采用了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
这里我们定义了一个框架类: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