转载本专栏文章,请注明出处,尊重原创 。文章博客地址:道龙的博客

现在很多的App要么顶部带有tab,要么就底部带有tab。用户通过点击tab从而切换不同的页面(大部分情况时去切换fragment)。本篇博客就通过简单的动态添加tab方式实现这个功能(当然最好的方式还是自定义控件来切换页面,就像微信那样)。

在开始之前,让我们对原型看看效果图:

因为最终效果是动态添加底部tab,我这里只是给出了两个tab去切换对应的fragment。如果想继续添加更多,直接在对应代码处添加即可。在写到对应代码的时候,我也会提到。

那么就开始这个Demo的开发吧~

一、ViewPage+Fragment先实现基本的切换功能

主活动布局代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.itydl.ydltabdemo.MainActivity"> <android.support.v4.view.ViewPager
android:id="@+id/viewpagge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</RelativeLayout>

然后创建两个Fragment,只需要创建完毕即可,不需要给其设置华丽的布局。代码太简单了,读者朋友可下载最后的Demo查看。

主活动中的代码完成切换功能,简单的代码谢了出来:

public class MainActivity extends AppCompatActivity {

    private ViewPager mMViewPager;
List<Fragment> mFragments = new ArrayList<Fragment>() ; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFragments.add(new OneFragment());
mFragments.add(new TwoFragment()); mMViewPager = (ViewPager) findViewById(R.id.viewpagge);
mMViewPager.setAdapter(new MyFragmentAdapter(getSupportFragmentManager()));
} class MyFragmentAdapter extends FragmentPagerAdapter{ public MyFragmentAdapter(FragmentManager fm) {
super(fm);
} @Override
public Fragment getItem(int position) {
return mFragments.get(position);
} @Override
public int getCount() {
return mFragments.size();
}
}
}

运行程序,发现完成了最基本的滑动切换Fragment的功能:

接下来,我们需要为之添加Tab了,添加Tab很简单,这里是教您怎么动态添加Tab。

二、给活动添加底部tab容器(我选择了LinearLayout,其他的父容器也可以的)。

主活动中的布局文件添加如下代码:

<?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:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.itydl.ydltabdemo.MainActivity"> <TextView
android:id="@+id/tvtitle"
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="#56cced"
android:gravity="center"
android:text="标题"
android:textColor="#fff"
android:textSize="22sp"/> <android.support.v4.view.ViewPager
android:id="@+id/viewpagge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
/> <!--底部tab的容器--> <LinearLayout
android:id="@+id/llbootom_container"
android:background="#25cb91"
android:layout_width="match_parent"
android:layout_height="52dp"> </LinearLayout> </LinearLayout>

我们添加了标题栏,和底部容器。

三、创建ToolBar工具类,添加底部Tab,并实现均分

添加tab的话,这里又有许多手段来完成它。我觉得新建一个类,就像自定义控件类一样的去使用这个工具类来添加tab,用起来更方便,这里读者可参考自觉地可行的方案。

新建ToolBar,里面添加这样一个方法:

public class ToolBar {
public void addBottomTab(LinearLayout container){ View childView = View.inflate(container.getContext(), R.layout.bottom_tab_textview, null);
container.addView(childView);
}
}

代码也很简单,没必要赘述太多。打气筒填充的布局是一个TextView,看看代码:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableTop="@drawable/icon_meassage_normal"
android:textSize="18sp"
android:text="会话"
android:gravity="center"
android:padding="4dp"
android:layout_marginTop="4dp"
android:orientation="vertical"> </TextView>

这个时候再来运行Demo瞧瞧:

我们可以清晰地看到,添加了一个底部tab。说明通过这种手段是可行的。那么高歌猛进,继续添加底部Tab,真正的实现动态添加吧,我们本来目的就是要动态添加Tab的嘛:

ToolBar的方法修改为下面情况:

public void addBottomTab(LinearLayout container, String[] bottomTitleArr, int[] bottomPic){

    for(int i = 0 ; i<bottomTitleArr.length;i++){
TextView childView = (TextView) View.inflate(container.getContext(), R.layout.bottom_tab_textview, null);
//给TextView添加文本
childView.setText(bottomTitleArr[i]);
//修改对应位置的图片.参数代表位于TextView的哪个方位。仅仅位于上方
childView.setCompoundDrawablesWithIntrinsicBounds(0, bottomPic[i], 0, 0); //把两个底部tab平分秋色.使用paramas对象 int w = 0;
int h = LinearLayout.LayoutParams.WRAP_CONTENT;
//创建params对象,并绘制具体的控件的宽高
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(w,h);
//weight设置为1,才是真正的均分父容器宽度
params.weight = 1;
container.addView(childView,params);
}
}

显然,我们需要传入多少个tab名称,多少个对应的tab图标。

主活动自己定义一下显示的图片和文本就可以了,图片我自定义了选择器,注意选择器看一下代码:

<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/icon_selfinfo_pressed" android:state_selected="true"/>
<item android:drawable="@drawable/icon_selfinfo_pressed" android:state_pressed="true"/>
<item android:drawable="@drawable/icon_selfinfo_normal" />
</selector>

注意我定义了selected属性,为什么要定义它,待会你就明白原因了。

运行效果:

可参看图片,已经均分孩子控件。

四、滑动viewPage改变Tab图标颜色,改变页面标题

对于改变图标颜色,我们还需要在toolBar里面添加一个切换图标颜色的方法:

/**进入某项fragment,对之改变Tab图标的颜色.在ViewPage切换到一项fragment的时候调用*/
public void changeColor(int position){
//还原所有颜色
for(TextView textView : mTextViews){
//在这里就知道我为什么定义状态选择器的时候,使用selected属性了
textView.setSelected(false);
} //让当前fragment位置的tab改变颜色
mTextViews.get(position).setSelected(true);
}

颜色的改变,以及标题的设置只需要加入滑动监听事件即可。

@Override
public void onPageSelected(int position) {
//某项ViewPage选中的时候调用。在这里顺便改变底部Tab的颜色
mMToolBar.changeColor(position);
//同时修改对应fragment的标题
mMTextView.setText(bottomTitleArr[position]);
}

五、完成点击切换页面、完成项目

底部控件模块都在toolBar类里面维护的,因而点击事件只能在这里面设置。而如果我想在MainActivity里面控制按钮点击切换页面,我就需要知道tooBar里点击按钮的位置,同时点击立即知道这个位置。根据这个位置再去切换对应的页面就好了。不同模块之间的通信,又可以有多重手段来操作完成,我这里选择了监听回调。

/***使用接口传递控件点击的位置*/

//1、定义接口和接口回调的方法
public interface OnToolBarChangeListener{
void onToolBarChange(int position);
} //2、创建接口变量,作为接口对象
OnToolBarChangeListener mOnToolBarChangeListener;
childView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//3、在需要通过接口回调传值的地方调用一次接口回调方法
mOnToolBarChangeListener.onToolBarChange(finalI);
}
});

//4、暴露一个公共方法,或者构造方法。参数是接口变量(对象)public void setOnToolBarChangeListener(OnToolBarChangeListener onToolBarChangeListener) { mOnToolBarChangeListener = onToolBarChangeListener;}

活动中只需要设置该监听器,监听toobar里面的点击事件位置就好了。

mMToolBar.setOnToolBarChangeListener(new ToolBar.OnToolBarChangeListener() {
@Override
public void onToolBarChange(int position) {
//切换对应的fragment
mMViewPager.setCurrentItem(position);
}
});

运行最终的结果:

我们可以看到,效果图跟最初遇开发的效果功能一模一样了~到此这个demo也讲解完毕了。

那么说好的动态添加呢?怎么就两个Tab??这个建议您下载demo试试,只需要修改两行代码,就是提供底部数据源的地方的两个字符串,添加对应的文字、图片(当然要额外创建多余的fragment)。就能实现多个Tab切换了,动态添加,也就解释清楚了~

附源码在文章最后,读者可自行下载。

喜欢我的朋友可以关注我,不定期更新类似的文章。一起交流讨论问题~

源码下载链接:源码下载

也可以打开微信搜索公众号  Android程序员开发指南  或者手机扫描下方二维码 在公众号阅读更多Android文章。

微信公众号图片:

Android Studio精彩案例(二)《仿微信动态点击底部tab切换Fragment》的更多相关文章

  1. Android Studio精彩案例(三)《模仿微信ViewPage+Fragment实现方式二》

    转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 写在前面的话:此专栏是博主在工作之余所写,每一篇文章尽可能写的思路清晰一些,属于博主的"精华"部分,不同于以往专栏 ...

  2. Android Studio精彩案例(一)《ActionBar和 ViewPager版仿网易新闻客户端》

    转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 为了能更好的分享高质量的文章,所以开设了此专栏.文章代码都以Android Studio亲测运行,读者朋友可在后面直接下载源码.该专栏 ...

  3. Android Studio精彩案例(四)《DrawerLayout使用详解仿网易新闻客户端侧边栏 》

    转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 为了提高兴趣,咱们开头先看看最终要实现什么样的效果: 侧拉菜单在Android应用中非常常见,它的实现方式太多了,今天我们就说说使用G ...

  4. Android Studio精彩案例(六)《使用一个Demo涵盖补间动画所有知识》

    转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 元旦假期里,闲的无事,看到美团加载数据的动画,就突想写个Demo把动画知识集成一下.后来想了想,还是直接用一个Demo来把所有动画知识 ...

  5. Android Studio精彩案例(五)《JSMS短信验证码功能实现》

    转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 很多应用刚打开的时候,让我们输入手机号,通过短信验证码来登录该应用.那么,这个场景是怎么实现的呢?其实是很多开放平台提供了短信验证功能 ...

  6. Android Studio精彩案例(七)《ToolBar使用详解<一>》

    转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 本文参考博客:http://blog.csdn.net/h_zhang/article/details/51232773 http:/ ...

  7. Android Studio系列教程二--基本设置与运行

    Android Studio系列教程二--基本设置与运行 2014 年 11 月 28 日 DevTools 本文为个人原创,欢迎转载,但请务必在明显位置注明出处! 上面一篇博客,介绍了Studio的 ...

  8. Android实训案例(二)——Android下的CMD命令之关机重启以及重启recovery

    Android实训案例(二)--Android下的CMD命令之关机重启以及重启recovery Android刚兴起的时候,着实让一些小众软件火了一把,切水果,Tom猫,吹裙子就是其中的代表,当然还有 ...

  9. Android studio 使用心得(四)—android studio 多渠道打包(二)

    Android studio 使用心得(四)—android studio 多渠道打包 这篇文章讲了一种打包方式.是直接在android studio 里面可视化操作,结合配置文件.我个人觉得严格上来 ...

随机推荐

  1. 前端开发必备之Chrome开发者工具(下篇)

    本文介绍的 Chrome 开发者工具基于 Chrome 65版本,如果你的 Chrome 开发者工具没有下文提到的那些内容,请检查下 Chrome 的版本 本文是 前端开发必备之Chrome开发者工具 ...

  2. Resource 的 IsSealed 问题

    WFP 的 Generic.xaml ,App.xaml 等中的资源会被调用 Freezable. 在后台对该资源进行修改等操作会被提示.资源为密封对象. 如果,确定需要在后台对资源进行修改. 则需要 ...

  3. .Net Core 部署在win10 的IIS上注意问题。

    事项一:_Layout.cshtml页面中<environment include="Development"></environment>里应用的样式无用 ...

  4. [HAOI 2007]上升序列

    Description 对于一个给定的S={a1,a2,a3,…,an},若有P={ax1,ax2,ax3,…,axm},满足(x1 < x2 < … < xm)且( ax1 < ...

  5. 计蒜客NOIP模拟赛4 D2T1 鬼脚图

    鬼脚图,又称画鬼脚,在日本称作阿弥陀签,是一种经典游戏,也是一种简易的决策方法,常常用来抽签或决定分配组合. 下图就是一张鬼脚图,其包含若干条竖线和若干条横线.请注意,横线只能水平连接相邻的两条竖线, ...

  6. [BZOJ]1069: [SCOI2007]最大土地面积

    题目大意:给出二维平面上n个点,求最大的由这些点组成的四边形面积.(n<=2000) 思路:求出凸包后旋转卡壳枚举对踵点对作为四边形的对角线,枚举或二分另外两个点,复杂度O(n^2)或O(nlo ...

  7. SPOJ NSUBSTR

    You are given a string S which consists of 250000 lowercase latin letters at most. We define F(x) as ...

  8. bzoj3825 NOI2017 游戏

    题目背景 狂野飙车是小 L 最喜欢的游戏.与其他业余玩家不同的是,小 L 在玩游戏之余,还精于研究游戏的设计,因此他有着与众不同的游戏策略. 题目描述 小 L 计划进行nn 场游戏,每场游戏使用一张地 ...

  9. 【CODEVS 6384 大米兔学全排列】

    ·大米兔学习全排列,还有一些逆序对,还有一棵二叉索引树.· ·分析:       首先肯定不是像题目上说的那样,使用next_permutation去完成这道题,因为就算是线性的它也不能承受庞大的排列 ...

  10. A Problem-Solving FlowChart || 如何解决编程问题

    This is from book Cracking the coding interview, Gayle Laakmann Mcdowell. The flowchart can be used ...