我们在Android手机上使用新浪微博和QQ等一些软件时,经常会遇到类似下面这种页面底部导航栏的控件,使用这种导航栏可以在手机屏幕的一页中显示尽可能多的内容,如下图所示:
下面我将实现这种导航栏的三种方法总结如下:
一、使用TabHost实现(TabHost在新版的Android SDK中已经不推荐使用了,但是这里还是可以了解下它的用法)
使用TabHost的Activity需要继承自TabActivity,且布局文件中的id有三个地方需要固定,布局文件如下:
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent" >
android:id="@android:id/tabcontent"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
android:id="@android:id/tabs"
android:background="@drawable/tab_bg"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
注意上面的布局文件中标红的三个地方,这三个地方的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起到互斥作用,请看代码,首先是布局文件:
在上面的代码中需要注意的一个地方是,在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
* 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 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();
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,通过这两个类才能实现页面的切换,下面放上源码:
下载源码