底部标签页实现思路

现在的APP,大多在页面底部显示标签栏Tabbar,用于切换不同栏目的页面。Tabbar起源于iOS,iOS的Tabbar自动位于页面下方,可是Android搬过来的时候做了改动,自带的Tabbar位于页面上方,很不适合用户的使用习惯。为此我们在Android实现底部标签栏,得额外进行底部适配处理,适配思路基本都是在底部罗列一排的按钮,然后根据点击不同的按钮,跳到不同的Activity页面。具体的实现方式,博主目前发现了三个:

1、使用TabActivity。其中在布局文件中设置TabHost、TabWidget和RadioButton,在代码文件中应用TabActivity、TabSpec和CompoundButton。
2、使用ActivityGroup。将几个栏目的首页Activity都放入ActivityGroup,然后根据点击事件选择切换到哪个Activity。
3、使用FragmentActivity和Fragment。将几个栏目的首页Fragment都放入FragmentActivity,可自动响应点击事件。
其中TabActivity继承自ActivityGroup,目前Android声称TabActivity与ActivityGroup都已废弃,建议采用Fragment和FragmentManager来代替。从实现代码来看,TabActivity和ActivityGroup两种方式的代码量都较多,而FragmentActivity方式的代码就显得很简洁,所以博主也推荐第三种方式。
下面简要介绍三种方式的代码实现:

TabActivity方式

调用代码如下:

import android.app.TabActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.TabHost;@SuppressWarnings("deprecation")
public class TestTabActivity extends TabActivity implements OnCheckedChangeListener {private static final String TAG = "TestTabActivity";private Bundle mBundle = new Bundle();private TabHost tab_host;private CompoundButton first_button;private CompoundButton second_button;private CompoundButton third_button;private String FIRST_TAG = "first";private String SECOND_TAG = "second";private String THIRD_TAG = "third";private TabHost.TabSpec getNewTab(String spec, int label, int icon, Intent intent) {return tab_host.newTabSpec(spec).setIndicator(getString(label), getResources().getDrawable(icon)).setContent(intent);}private void setButtonCheck(CompoundButton button) {if (button.equals(first_button)) {button.setChecked(true);second_button.setChecked(false);third_button.setChecked(false);} else if (button.equals(third_button)) {button.setChecked(true);second_button.setChecked(false);first_button.setChecked(false);} else if (button.equals(second_button)) {button.setChecked(true);first_button.setChecked(false);third_button.setChecked(false);}}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_test_tab);mBundle.putString("tag", TAG);tab_host = getTabHost();tab_host.addTab(getNewTab(FIRST_TAG, R.string.menu_first,R.drawable.tab_first_selector, new Intent(this, FirstActivity.class).putExtras(mBundle)));tab_host.addTab(getNewTab(SECOND_TAG, R.string.menu_second,R.drawable.tab_second_selector, new Intent(this, SecondActivity.class).putExtras(mBundle)));tab_host.addTab(getNewTab(THIRD_TAG, R.string.menu_third,R.drawable.tab_third_selector, new Intent(this, ThirdActivity.class).putExtras(mBundle)));first_button = ((CompoundButton) findViewById(R.id.rbtn_tab_first));first_button.setOnCheckedChangeListener(this);second_button = ((CompoundButton) findViewById(R.id.rbtn_tab_second));second_button.setOnCheckedChangeListener(this);third_button = ((CompoundButton) findViewById(R.id.rbtn_tab_third));third_button.setOnCheckedChangeListener(this);tab_host.setCurrentTabByTag(FIRST_TAG);setButtonCheck(first_button);}@Overridepublic void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {if (isChecked == true) {setButtonCheck(buttonView);if (buttonView.equals(first_button)) {tab_host.setCurrentTabByTag(FIRST_TAG);} else if (buttonView.equals(second_button)) {tab_host.setCurrentTabByTag(SECOND_TAG);} else if (buttonView.equals(third_button)) {tab_host.setCurrentTabByTag(THIRD_TAG);}}}}

该方式的核心是getNewTab函数,可设置标签的文本和图标,以及该标签对应的跳转页面。当发生点击事件时,系统调用TabHost的setCurrentTabByTag函数来定位到具体的跳转页面。

ActivityGroup方式

调用代码如下:

import android.app.ActivityGroup;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;@SuppressWarnings("deprecation")
public class TestGroupActivity extends ActivityGroup implements OnClickListener {private static final String TAG = "TestGroupActivity";private Bundle mBundle = new Bundle();private LinearLayout layout_container, layout_first, layout_second, layout_third;private ImageView img_first, img_second, img_third;private TextView txt_first, txt_second, txt_third;public static final int PAGE_FIRST = 1001;public static final int PAGE_SECOND = 1002;public static final int PAGE_XINXI = 1003;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_test_group);layout_container = (LinearLayout) findViewById(R.id.layout_container);layout_first = (LinearLayout) findViewById(R.id.layout_first);layout_second = (LinearLayout) findViewById(R.id.layout_second);layout_third = (LinearLayout) findViewById(R.id.layout_third);img_first = (ImageView) findViewById(R.id.img_first);img_second = (ImageView) findViewById(R.id.img_second);img_third = (ImageView) findViewById(R.id.img_third);txt_first = (TextView) findViewById(R.id.txt_first);txt_second = (TextView) findViewById(R.id.txt_second);txt_third = (TextView) findViewById(R.id.txt_third);layout_first.setOnClickListener(this);layout_second.setOnClickListener(this);layout_third.setOnClickListener(this);mBundle.putString("tag", TAG);changeContainerView(PAGE_FIRST);}private void changeContainerView(int page) {switch (page) {case PAGE_FIRST:layout_first.setBackgroundResource(R.drawable.ic_tabbar_bg_click);layout_second.setBackgroundResource(R.drawable.ic_tabbar_bg_normal);layout_third.setBackgroundResource(R.drawable.ic_tabbar_bg_normal);img_first.setBackgroundResource(R.drawable.ic_tabbar_first_pressed);img_second.setBackgroundResource(R.drawable.ic_tabbar_second_normal);img_third.setBackgroundResource(R.drawable.ic_tabbar_third_normal);txt_first.setTextColor(getResources().getColor(R.color.tab_text_selected));txt_second.setTextColor(getResources().getColor(R.color.tab_text_normal));txt_third.setTextColor(getResources().getColor(R.color.tab_text_normal));toActivity("item1", new Intent(this, FirstActivity.class).putExtras(mBundle));return;case PAGE_SECOND:layout_first.setBackgroundResource(R.drawable.ic_tabbar_bg_normal);layout_second.setBackgroundResource(R.drawable.ic_tabbar_bg_click);layout_third.setBackgroundResource(R.drawable.ic_tabbar_bg_normal);img_first.setBackgroundResource(R.drawable.ic_tabbar_first_normal);img_second.setBackgroundResource(R.drawable.ic_tabbar_second_pressed);img_third.setBackgroundResource(R.drawable.ic_tabbar_third_normal);txt_first.setTextColor(getResources().getColor(R.color.tab_text_normal));txt_second.setTextColor(getResources().getColor(R.color.tab_text_selected));txt_third.setTextColor(getResources().getColor(R.color.tab_text_normal));toActivity("item1", new Intent(this, SecondActivity.class).putExtras(mBundle));return;case PAGE_XINXI:layout_first.setBackgroundResource(R.drawable.ic_tabbar_bg_normal);layout_second.setBackgroundResource(R.drawable.ic_tabbar_bg_normal);layout_third.setBackgroundResource(R.drawable.ic_tabbar_bg_click);img_first.setBackgroundResource(R.drawable.ic_tabbar_first_normal);img_second.setBackgroundResource(R.drawable.ic_tabbar_second_normal);img_third.setBackgroundResource(R.drawable.ic_tabbar_third_pressed);txt_first.setTextColor(getResources().getColor(R.color.tab_text_normal));txt_second.setTextColor(getResources().getColor(R.color.tab_text_normal));txt_third.setTextColor(getResources().getColor(R.color.tab_text_selected));toActivity("item1", new Intent(this, ThirdActivity.class).putExtras(mBundle));return;default:return;}}@Overridepublic void onClick(View view) {switch (view.getId()) {case R.id.layout_first:changeContainerView(PAGE_FIRST);return;case R.id.layout_second:changeContainerView(PAGE_SECOND);return;case R.id.layout_third:changeContainerView(PAGE_XINXI);return;default:return;}}private void toActivity(String label, Intent intent) {layout_container.removeAllViews();View view = getLocalActivityManager().startActivity(label, intent).getDecorView();layout_container.addView(view);}}

该方式的核心是toActivity函数,也可设置标签的文本和图标,以及该标签对应的跳转页面。在toActivity函数中可以看到,startActivity方法返回一个Window对象,系统从该Window对象提取标签页的实际视图getDecorView(我们可以把DecorView理解为该标签页的根视图),然后这个DecorView加入到Tabbar的视图容器中。

FragmentActivity方式

调用代码如下:

import android.annotation.SuppressLint;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TabHost.TabSpec;
import android.widget.TextView;@SuppressLint("InflateParams")
public class TestFragmentActivity extends FragmentActivity {private static final String TAG = "TestFragmentActivity";private Bundle mBundle = new Bundle();private FragmentTabHost mTabHost;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_test_fragment);mBundle.putString("tag", TAG);mTabHost = (FragmentTabHost)findViewById(android.R.id.tabhost);mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);//addTab(标题,跳转的Fragment,传递参数的Bundle)mTabHost.addTab(getTabView(R.string.menu_first, R.drawable.tabbar_first_selector), FirstFragment.class, mBundle);mTabHost.addTab(getTabView(R.string.menu_second, R.drawable.tabbar_second_selector), SecondFragment.class, mBundle);mTabHost.addTab(getTabView(R.string.menu_third, R.drawable.tabbar_third_selector), ThirdFragment.class, mBundle);//设置tabs之间的分隔线不显示mTabHost.getTabWidget().setShowDividers(LinearLayout.SHOW_DIVIDER_NONE);}private TabSpec getTabView(int textId, int imgId) {String text = getResources().getString(textId);Drawable drawable = getResources().getDrawable(imgId);//必须设置图片大小,否则不显示drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());View tabbar_item = getLayoutInflater().inflate(R.layout.tabbar_item, null);TextView tv_item = (TextView) tabbar_item.findViewById(R.id.tv_item);tv_item.setText(text);tv_item.setCompoundDrawables(null, drawable, null, null);TabSpec spec = mTabHost.newTabSpec(text).setIndicator(tabbar_item);return spec;}}

该方式的核心是getTabView函数,可自定义每个标签项的具体视图。因为FragmentTabHost已经自动处理了点击事件,所以该方式的代码量比前两种缩小很多。

下面是底部标签页三种方式的效果图

点击下载本文用到的底部标签页三种方式的工程代码

点此查看Android开发笔记的完整目录

Android开发笔记(十九)底部标签栏TabBar相关推荐

  1. Android开发笔记(九十七)图片的特效处理

    图片特效用到的函数 本文讲述的图片特效处理包括:怀旧.光照.光晕.底片.浮雕.模糊.锐化.黑白.冰冻.素描,所有这些特效都是基于一定的算法,对图像每个点的RGB值进行计算,并汇总所有点的计算结果生成新 ...

  2. 【Visual C++】游戏开发笔记十九 DirectX与OpenGL的博弈

    From: http://blog.csdn.net/zhmxy555/article/details/7522960 本系列文章由zhmxy555(毛星云)编写,转载请注明出处. http://bl ...

  3. 【Visual C 】游戏开发笔记十九 DirectX与OpenGL的博弈

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...

  4. Android开发笔记(九)特别的.9图片

    为什么使用.9图片 .9图片的扩展名是png,文件名后常带有".9"字样,因为它把一个png图片划分为3*3的九宫格来分别处理,所以得名.9图片..9.png是Android开发中 ...

  5. Andriod开发之二十:Android开发笔记(序)写在前面的目录

    https://blog.csdn.net/aqi00/article/details/50038385 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教 ...

  6. Android开发笔记(一百一十五)设计工具

    UI/UE UI是User Interface的简称,即用户接口,也称用户界面.UI泛指用户的操作界面,对手机来说,UI设计就是app的页面设计.一个好的UI,不但能让用户操作起来更加舒适.方便,而且 ...

  7. Android开发笔记(十五)淡入淡出动画TransitionDrawable

    说到淡入淡出动画,可能大家会想到补间动画里面的AlphaAnimation,不过这个深浅动画只能对透明度做渐变效果,也就是只能对一个图形做深浅的颜色变换.如果我们想要从A图片逐渐变为B图片,也就是要实 ...

  8. Android开发笔记(序)写在前面的目录

    知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教训,与网友互相切磋,从而去芜存菁进一步提升自己的水平.因此博主就想,入门的东西咱就不写了,人不能老停留在入 ...

  9. Android开发笔记(序)

    本开发笔记,借鉴与其他开发者整理的文章范例与心得体会.在这里作为开发过程中的一个总结与笔记式记录. 如有侵犯作者权益,请及时联系告知删除.俗话说:集百家成一言,去粕成金. ************** ...

  10. Android开发笔记(序)写在前面的目录大全

    转自  湖前琴亭 的博客https://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面 ...

最新文章

  1. numpy中的matrix与array的区别
  2. 快速排序(quick sort)
  3. 以太坊在哪里买_DeFi只是以太坊的开胃小菜,以太坊2.0才是重头戏
  4. python爬取大众点评_浅谈python爬取58同城,大众点评这两个网站
  5. rest资源设计_REST资源何时应获得其自己的地址?
  6. Fragment与Activity交互(使用接口)
  7. Python抓取2500份招聘需求,数据显示未来最吃香的岗位是这个
  8. Edge 浏览器有秘密白名单,允许 Facebook 运行 Flash 代码
  9. 嵌入式基础面八股文——孤儿进程、僵尸进程、守护进程的概念(3)
  10. 树莓派蜂鸣器唱歌c语言,关于蜂鸣器唱歌程序
  11. CRT使用(二)CRT软件修改超时时间
  12. 这几个Python数据可视化探索实例,拿走不谢
  13. 数学分析(1):集合相关公式的证明
  14. 浅谈网站建设方案主要内容
  15. centos7安装的大致步骤
  16. 龙格库塔(runge-kutta,RK)法求解微分方程
  17. 技术升级 | 戴着口罩也能识别人脸啦
  18. python from __future__ import
  19. 校园枪击案后,这个美国小哥开发了“枪支检测器”!迅速定位疑犯,适配任何摄像头...
  20. T2080 U-BOOT与OS内核移植 u-boot移植篇(一)——创建新目标板的u-boot工程

热门文章

  1. Leetcode每日一题:381.insert-delete-getrandom-o1-duplicates-allowed(时间插入、删除和获取随机元素-允许重复)
  2. CS230+deeplearning.ai专项课程笔记及作业目录
  3. 花书+吴恩达深度学习(二十)构建模型策略(超参数调试、监督预训练、无监督预训练)
  4. jquery只获取自身文本节点,不获取子元素的
  5. 51单片机数码管滚动显示学号_51单片机四位数码管4个LED灯4个按键实现多种功能?...
  6. 为何电脑html无法删除,电脑文件无法删除该怎么办?几种解决方法介绍
  7. 遍历所有点的最短路径matlab_运筹学实验8 最短路的求解
  8. 精通oracle能干嘛,五分鍾精通Oracle表空間
  9. Java事务管理之Hibernate
  10. Windows 帐号管理相关操作