我们在Android手机上使用新浪微博和QQ等一些软件时,经常会遇到类似下面这种页面底部导航栏的控件,使用这种导航栏可以在手机屏幕的一页中显示尽可能多的内容,如下图所示:
下面我将实现这种导航栏的三种方法总结如下:
一、使用TabHost实现(TabHost在新版的Android SDK中已经不推荐使用了,但是这里还是可以了解下它的用法)
使用TabHost的Activity需要继承自TabActivity,且布局文件中的id有三个地方需要固定,布局文件如下:
<?xml version="1.0" encoding="utf-8"?> <TabHost xmlns:android="http://schemas.android.com/apk/res/android" <span style="color:#ff0000;">android:id="@android:id/tabhost"</span> android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <FrameLayout <span style="color:#ff0000;">android:id="@android:id/tabcontent"</span> android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" /> <TabWidget <span style="color:#ff0000;">android:id="@android:id/tabs"</span> android:background="@drawable/tab_bg" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> </TabHost>注意上面的布局文件中标红的三个地方,这三个地方的id值必须写成这样,然后是Activity中的代码:
package cn.yubo.testtabhost; import android.app.TabActivity; import android.content.Intent; import android.os.Bundle; import android.widget.TabHost; import android.widget.TabWidget; public class TabHostActivity extends TabActivity { private TabHost tabHost; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_tab_host); tabHost = getTabHost(); //添加三个Tab标签 tabHost.addTab(tabHost.newTabSpec("tab1") .setIndicator("选项1", getResources().getDrawable(R.drawable.tab_activity_normal)) .setContent(new Intent(this, TabHost1Activity.class))); tabHost.addTab(tabHost.newTabSpec("tab2") .setIndicator("选项2", getResources().getDrawable(R.drawable.tab_activity_normal)) .setContent(new Intent(this, TabHost2Activity.class))); tabHost.addTab(tabHost.newTabSpec("tab3") .setIndicator("选项3", getResources().getDrawable(R.drawable.tab_img_selector)) .setContent(new Intent(this, TabHost3Activity.class))); } }在上面的代码中,我们首先通过getTabHost()方法得到一个TabHost对象,然后添加了三个导航栏标签,通过setContent()方法指定了每个标签跳转到的页面,最后的效果图为:
这里不知道为什么在底部的Tab中没有显示出图标来,明明通过setIndicator方法设置了图标,但是没显示出来。
下面说下第二种实现导航栏的方法:
二、使用ViewPager+RadioGroup实现
这种方法实现起来比较容易,就是在页面上加个ViewPager,底部放一个RadioGroup,里面放几个RadioButton起到互斥作用,请看代码,首先是布局文件:
<?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:orientation="vertical" > <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" /> <RadioGroup android:id="@+id/radiogroup" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/tab_bg" android:gravity="center_vertical" android:orientation="horizontal" > <RadioButton android:id="@+id/tab1" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:button="@null" android:checked="true" android:drawableTop="@drawable/tab_img_selector" android:gravity="center" android:paddingLeft="0dp" android:text="选项1" /> <RadioButton android:id="@+id/tab2" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:button="@null" android:drawableTop="@drawable/tab_img_selector" android:gravity="center" android:paddingLeft="0dp" android:text="选项2" /> <RadioButton android:id="@+id/tab3" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:button="@null" android:drawableTop="@drawable/tab_img_selector" android:gravity="center" android:paddingLeft="0dp" android:text="选项2" /> </RadioGroup> </LinearLayout>在上面的代码中需要注意的一个地方是,在RadioButton里,我们设置了button属性为@null,这样就去掉了原来的RadioButton中的圆圈,但是如果不加paddingLeft="0dp"这个属性的话,你会发现RadioButton中的图标和文字还是靠右的,就是说,虽然button属性设置了@null,但是button占据的位置还是在的,只有设置了paddingLeft="0dp"和gravity="center"属性后,RadioButton中的图标和文字才会居中。
写完了布局文件的代码,再来看看Activity中的代码该怎么写:
package cn.yubo.testtabhost; import java.util.ArrayList; import java.util.List; import net.tsz.afinal.FinalActivity; import net.tsz.afinal.annotation.view.ViewInject; import android.os.Bundle; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; import android.widget.TextView; /** * 使用ViewPager和RadioGroup实现底部导航栏 * * @author yubo<br/> * 2014年12月12日 */ public class ViewPagerTabActivity extends FinalActivity { @ViewInject(id = R.id.viewpager) private ViewPager viewPager; @ViewInject(id = R.id.radiogroup) private RadioGroup radioGroup; @ViewInject(id = R.id.tab1) private RadioButton tab1; @ViewInject(id = R.id.tab2) private RadioButton tab2; @ViewInject(id = R.id.tab3) private RadioButton tab3; private List<View> viewList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_view_pager_tab); initViewPager(); radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() { public void onCheckedChanged(RadioGroup group, int checkedId) { switch (checkedId) { case R.id.tab1: viewPager.setCurrentItem(0); break; case R.id.tab2: viewPager.setCurrentItem(1); break; case R.id.tab3: viewPager.setCurrentItem(2); break; } } }); } private void initViewPager() { viewList = new ArrayList<View>(); viewList.add(LayoutInflater.from(this).inflate(R.layout.page_layout, null)); viewList.add(LayoutInflater.from(this).inflate(R.layout.page_layout, null)); viewList.add(LayoutInflater.from(this).inflate(R.layout.page_layout, null)); viewPager.setAdapter(new MyViewPagerAdapter()); viewPager.setOnPageChangeListener(new OnPageChangeListener() { public void onPageSelected(int arg0) { switch (arg0) { case 0: tab1.setChecked(true); tab2.setChecked(false); tab3.setChecked(false); break; case 1: tab1.setChecked(false); tab2.setChecked(true); tab3.setChecked(false); break; case 2: tab1.setChecked(false); tab2.setChecked(false); tab3.setChecked(true); break; } } public void onPageScrolled(int arg0, float arg1, int arg2) { } public void onPageScrollStateChanged(int arg0) { } }); } private class MyViewPagerAdapter extends PagerAdapter { @Override public int getCount() { return viewList.size(); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(viewList.get(position)); } @Override public Object instantiateItem(ViewGroup container, int position) { View view = viewList.get(position); container.addView(view); TextView textView = (TextView) view .findViewById(R.id.page_textview); textView.setText("第" + position + "页的数据"); return view; } } }这里也没什么难点的,就是设置ViewPager滑动时切换RadioButton的选中状态,然后设置RadioButton被选中时显示ViewPager的哪个页面,上面的代码中用到了AFinal框架,使用FinalActivity中的注解方式获取控件,其他就没什么了,效果图如下:
三、使用Fragment+RadioButton实现导航栏
这种方式也蛮不错的,最后实现的效果图跟第二种方法的一样,区别之处就在于,第二种方法使用了ViewPager,所以上面的区域是可以左右滑动的,而我们这第三种方式实现的导航栏,上面一部分的区域是不可以左右滑动的,页面的切换只能通过下面的导航栏tab来进行,布局文件就不上了,跟第二种方法的布局文件一致,关键是Activity中的代码:
package cn.yubo.testtabhost; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.widget.RadioGroup; import android.widget.RadioGroup.OnCheckedChangeListener; public class MyFragmentActivity extends FragmentActivity { private FragmentManager manager; private FragmentTransaction tran; private RadioGroup radioGroup; @Override protected void onCreate(Bundle arg0) { super.onCreate(arg0); setContentView(R.layout.activity_my_fragment); manager = getSupportFragmentManager(); tran = manager.beginTransaction(); tran.replace(R.id.content, new Fragment1()); tran.commit(); radioGroup = (RadioGroup) findViewById(R.id.radiogroup); radioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() { public void onCheckedChanged(RadioGroup group, int checkedId) { tran = manager.beginTransaction(); switch(checkedId){ case R.id.tab1: tran.replace(R.id.content, new Fragment1()); break; case R.id.tab2: tran.replace(R.id.content, new Fragment2()); break; case R.id.tab3: tran.replace(R.id.content, new Fragment3()); break; } tran.commit(); } }); } }使用Fragment做这种页面的切换时,我们要继承FragmentActivity类,其中比较重要的地方是FragmentManager和FragmentTransaction,通过这两个类才能实现页面的切换,下面放上源码:
下载源码