一句话搞定Android底部导航栏,一键绑定Fragment、ViewPager

现在大多数App都会用到底部导航栏,比如常见的聊天工具QQ、微信、购物App等等,有了底部导航栏,用户可以随时切换界面,查看不同的内容。它的实现方式也很多,以前大多使用TabHost来实现,但是现在我们有很多更好的选择。

常见的底部导航栏实现方式:
1.使用LinearLayout + TextView实现了底部导航栏的效果
2.使用RadioGroup + RadioButton实现了底部导航栏的效果
3.利用BottomNavigationBar实现底部导航栏
.......

实现方式有很多,不过好像都只是关于下边Tab切换而已,没有实现Tab与界面的联动,用的时候还要自己手写这部分代码,麻烦不麻烦?

作为一名注定要改变世界的程序猿,你让我天天写这个?这是不能忍的。

更高,更快,更强

就不能有个东西,能够一句话搞定Android底部导航栏,一键绑定Fragment、ViewPager吗?

所以,这个BottomTabBar产生了。GitHub项目地址

先来看下效果:


简陋的演示.gif

How to use:



Step 1. Add the JitPack repository to your build file
Add it in your root build.gradle at the end of repositories:

    allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

Step 2. Add the dependency

    dependencies {
         compile 'com.github.zhaolei9527:UseBottomTabBar:v1.0.4'
    }

XML布局文件代码:

        <sakura.bottomtabbar.BottomTabBar
            android:id="@+id/BottomTabBar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
          ></sakura.bottomtabbar.BottomTabBar>

控件可设置参数:

参数名 描述
tab_bar_background BottomTabBar的整体背景颜色
tab_img_width 图片宽度
tab_img_height 图片高度
tab_font_size 文字尺寸
tab_img_font_padding 图片文字间隔
tab_padding_top 上边距
tab_padding_bottom 下边距
tab_isshow_divider 是否显示分割线
tab_divider_height 分割线高度
tab_divider_background 分割线背景
tab_selected_color 选中的颜色
tab_unselected_color 未选中的颜色

Activity文件代码:

导包:import sakura.bottomtabbar.BottomTabBar;

绑定Fragment的:(一句话搞定有木有?)

            BottomTabBar.initFragmentorViewPager(getSupportFragmentManager())
                .addReplaceLayout(R.id.fl_content)
                .addTabItem("草莓", getResources().getDrawable(R.mipmap.icon01), getResources().getDrawable(R.mipmap.icon_round), FragmentA.class)
                .addTabItem("凤梨", getResources().getDrawable(R.mipmap.icon02), getResources().getDrawable(R.mipmap.icon_round), FragmentB.class)
                .addTabItem("樱桃", getResources().getDrawable(R.mipmap.icon03), getResources().getDrawable(R.mipmap.icon_round), FragmentC.class)
                .addTabItem("香蕉", getResources().getDrawable(R.mipmap.icon04), getResources().getDrawable(R.mipmap.icon_round), FragmentD.class)
                .commit();

绑定ViewPager的:(一句话搞定有木有?)

        BottomTabBar.initFragmentorViewPager(viewpager)
                .setChangeColor(getResources().getColor(R.color.colorAccent), getResources().getColor(R.color.colorPrimary))
                .addTabItem("草莓", getResources().getDrawable(R.mipmap.icon01), getResources().getDrawable(R.mipmap.icon_round))
                .addTabItem("凤梨", getResources().getDrawable(R.mipmap.icon02), getResources().getDrawable(R.mipmap.icon_round))
                .addTabItem("樱桃", getResources().getDrawable(R.mipmap.icon03), getResources().getDrawable(R.mipmap.icon_round))
                .addTabItem("香蕉", getResources().getDrawable(R.mipmap.icon04), getResources().getDrawable(R.mipmap.icon_round))
                .commit(); 

代码可配置参数方法:

参数名 描述
setImgSize 设置图片的尺寸
setFontSize 设置文字的尺寸
setTabPadding 设置Tab的padding值
setChangeColor 设置选中未选中的颜色
setTabBarBackgroundColor 设置BottomTabBar的整体背景颜色
setTabBarBackgroundResource 设置BottomTabBar的整体背景图片
isShowDivider 是否显示分割线
setDividerHeight 设置分割线的高度
setDividerColor 设置分割线的颜色

很简单,对不对,你想干什么,我都替你干

划重点,这个initFragmentorViewPager ( getSupportFragmentManager() | ViewPager)方法一定要第一个调用,没有这个初始化,后边什么也做不了。

另外,上述实例的addTabItem是支持选中状态图片切换的方法,在此之外,还支持不需要切换图片的模式。

/**
     * 添加TabItem
     * @param name  文字
     * @param imgId 图片id
     * @return
     */
    public BottomTabBar addTabItem(String name, int imgId){...}

/**
     * 添加TabItem
     * @param name          文字
     * @param imgId         图片id
     * @param Fragmentclazz Fragment类
     * @return
     */
    public BottomTabBar addTabItem(String name, int imgId, Class Fragmentclazz){...}

另外,考虑到在底部导航栏点击切换界面的需求之外的其他需求,BottomTabBar提供了点击事件的回调。

((BottomTabBar) findViewById(R.id.BottomTabBar))
                .initFragmentorViewPager(getSupportFragmentManager())
                .addReplaceLayout(R.id.fl_content)
                .addTabItem("草莓", getResources().getDrawable(R.mipmap.icon01), getResources().getDrawable(R.mipmap.icon_round), FragmentA.class)
                .addTabItem("凤梨", getResources().getDrawable(R.mipmap.icon02), getResources().getDrawable(R.mipmap.icon_round), FragmentB.class)
                .addTabItem("樱桃", getResources().getDrawable(R.mipmap.icon03), getResources().getDrawable(R.mipmap.icon_round), FragmentC.class)
                .addTabItem("香蕉", getResources().getDrawable(R.mipmap.icon04), getResources().getDrawable(R.mipmap.icon_round), FragmentD.class)
                .setOnTabChangeListener(new BottomTabBar.OnTabChangeListener() {
                    @Override
                    public void onTabChange(int position, View V) {
                        Toast.makeText(FragmentActivity.this, "position:" + position, Toast.LENGTH_SHORT).show();
                    }
                })
                .commit();

项目代码概览:

获取xml配置样式 :

    public BottomTabBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.BottomTabBar);
        if (attributes != null) {
            //图片宽度
            imgWidth = attributes.getDimension(R.styleable.BottomTabBar_tab_img_width, dp2px(30));
            //图片高度
            imgHeight = attributes.getDimension(R.styleable.BottomTabBar_tab_img_height, dp2px(30));
            //文字尺寸
            fontSize = attributes.getDimension(R.styleable.BottomTabBar_tab_font_size, 14);
            //上边距
            paddingTop = attributes.getDimension(R.styleable.BottomTabBar_tab_padding_top, dp2px(2));
            //图片文字间隔
            fontImgPadding = attributes.getDimension(R.styleable.BottomTabBar_tab_img_font_padding, dp2px(3));
            //下边距
            paddingBottom = attributes.getDimension(R.styleable.BottomTabBar_tab_padding_bottom, dp2px(5));
            //分割线高度
            dividerHeight = attributes.getDimension(R.styleable.BottomTabBar_tab_divider_height, dp2px(1));
            //是否显示分割线
            isShowDivider = attributes.getBoolean(R.styleable.BottomTabBar_tab_isshow_divider, false);
            //选中的颜色
            selectColor = attributes.getColor(R.styleable.BottomTabBar_tab_selected_color, Color.parseColor("#F1453B"));
            //未选中的颜色
            unSelectColor = attributes.getColor(R.styleable.BottomTabBar_tab_unselected_color, Color.parseColor("#626262"));
            //BottomTabBar的整体背景
            tabBarBackgroundColor = attributes.getColor(R.styleable.BottomTabBar_tab_bar_background, Color.parseColor("#FFFFFF"));
            //分割线背景
            dividerBackgroundColor = attributes.getColor(R.styleable.BottomTabBar_tab_divider_background, Color.parseColor("#CCCCCC"));
            attributes.recycle();
        }
    }

初始化View :

   private void initView() {
        mLayout = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.bottom_tab_bar, null);
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
        mLayout.setLayoutParams(layoutParams);
        mLayout.setBackgroundColor(tabBarBackgroundColor);
        addView(mLayout);
        mDivider = mLayout.findViewById(R.id.mDivider);
        mTabContent = (LinearLayout) mLayout.findViewById(R.id.mTabContent);
        if (isShowDivider) {
            LayoutParams dividerParams = new LayoutParams(LayoutParams.MATCH_PARENT, (int) dividerHeight);
            mDivider.setLayoutParams(dividerParams);
            mDivider.setBackgroundColor(dividerBackgroundColor);
            mDivider.setVisibility(VISIBLE);
        } else {
            mDivider.setVisibility(GONE);
        }
    }

ViewPager模式添加Tab :

public BottomTabBar addTabItem(final String name, Drawable selectdrawable, Drawable unselectdrawable) {
        selectdrawableList.add(selectdrawable);
        unselectdrawableList.add(unselectdrawable);
        LinearLayout TabItem = (LinearLayout) View.inflate(context, R.layout.tab_item, null);
        TabItem.setGravity(Gravity.CENTER);
        //设置TabItem标记
        TabItem.setTag(name);
        //添加标记至集合以作辨别
        tabIdList.add(String.valueOf(TabItem.getTag()));
        TabItem.setOnClickListener(this);
        //Tab图片样式及内容设置
        ImageView tab_item_img = (ImageView) TabItem.findViewById(R.id.tab_item_img);
        tab_item_imgparams = new LayoutParams((int) imgWidth, (int) imgHeight);
        tab_item_imgparams.topMargin = (int) paddingTop;
        tab_item_imgparams.bottomMargin = (int) fontImgPadding;
        tab_item_img.setLayoutParams(tab_item_imgparams);
        //Tab文字样式及内容设置
        TextView tab_item_tv = (TextView) TabItem.findViewById(R.id.tab_item_tv);
        tab_item_tvparams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        tab_item_tvparams.bottomMargin = (int) paddingBottom;
        tab_item_tv.setLayoutParams(tab_item_tvparams);
        tab_item_tv.setTextSize(fontSize);
        tab_item_tv.setText(name);
        if (tabIdList.size() == 1) {
            tab_item_tv.setTextColor(selectColor);
            tab_item_img.setBackground(selectdrawable);
        } else {
            tab_item_tv.setTextColor(unSelectColor);
            tab_item_img.setBackground(unselectdrawable);
        }
        TabItem.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f));
        mTabContent.addView(TabItem);
        return this;
    }

Fragment模式添加Tab :

  public BottomTabBar addTabItem(final String name, Drawable selectdrawable, Drawable unselectdrawable, Class fragmentClass) {
        selectdrawableList.add(selectdrawable);
        unselectdrawableList.add(unselectdrawable);
        Class<?> clazz = null;
        try {
            clazz = Class.forName(fragmentClass.getName());
            Fragment fragment = (Fragment) clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        FragmentList.add(fragmentClass);
        LinearLayout TabItem = (LinearLayout) View.inflate(context, R.layout.tab_item, null);
        TabItem.setGravity(Gravity.CENTER);
        //设置TabItem标记
        TabItem.setTag(name);
        //添加标记至集合以作辨别
        tabIdList.add(String.valueOf(TabItem.getTag()));
        TabItem.setOnClickListener(this);
        //Tab图片样式及内容设置
        ImageView tab_item_img = (ImageView) TabItem.findViewById(R.id.tab_item_img);
        tab_item_imgparams = new LayoutParams((int) imgWidth, (int) imgHeight);
        tab_item_imgparams.topMargin = (int) paddingTop;
        tab_item_imgparams.bottomMargin = (int) fontImgPadding;
        tab_item_img.setLayoutParams(tab_item_imgparams);
        //Tab文字样式及内容设置
        TextView tab_item_tv = (TextView) TabItem.findViewById(R.id.tab_item_tv);
        tab_item_tvparams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        tab_item_tvparams.bottomMargin = (int) paddingBottom;
        tab_item_tv.setLayoutParams(tab_item_tvparams);
        tab_item_tv.setTextSize(fontSize);
        tab_item_tv.setText(name);
        if (tabIdList.size() == 1) {
            tab_item_tv.setTextColor(selectColor);
            tab_item_img.setBackground(selectdrawable);
        } else {
            tab_item_tv.setTextColor(unSelectColor);
            tab_item_img.setBackground(unselectdrawable);
        }
        TabItem.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f));
        mTabContent.addView(TabItem);
        return this;
    }

Fragment切换处理 :

    private void relaceFrament(int i) {
        Class aClass = FragmentList.get(i);
        Class<?> clazz = null;
        try {
            clazz = Class.forName(aClass.getName());
            Fragment Fragment = (Fragment) clazz.newInstance();
            android.support.v4.app.FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
            fragmentTransaction.replace(mReplaceLayout, Fragment);
            fragmentTransaction.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Tab点击事件处理 :

    @Override
    public void onClick(View v) {
        for (int i = 0; i < tabIdList.size(); i++) {
            if (tabIdList.get(i).equals(v.getTag())) {
                if (mViewpager != null) {
                    //绑定ViewPager
                    mViewpager.setCurrentItem(i);
                }
                if (mFragmentManager != null) {
                    if (mReplaceLayout == 0) {
                        throw new IllegalStateException(
                                "Must input ReplaceLayout of mReplaceLayout");
                    }
                    relaceFrament(i);
                    changeTab(i);
                }
                //绑定点击监听回调
                listener.onTabChange(i, v);
            }
        }
    }

Tab选中更改样式 :

    private void changeTab(int position) {
        if (position + 1 > mTabContent.getChildCount()) {
            throw new IndexOutOfBoundsException("onPageSelected:" + (position + 1) +
                    ",of Max mTabContent ChildCount:" + mTabContent.getChildCount());
        }
        for (int i = 0; i < mTabContent.getChildCount(); i++) {
            View TabItem = mTabContent.getChildAt(i);
            if (i == position) {
                ((TextView) TabItem.findViewById(R.id.tab_item_tv)).setTextColor(selectColor);
                if (!selectdrawableList.isEmpty())
                    TabItem.findViewById(R.id.tab_item_img).setBackground(selectdrawableList.get(i));
            } else {
                ((TextView) TabItem.findViewById(R.id.tab_item_tv)).setTextColor(unSelectColor);
                if (!selectdrawableList.isEmpty())
                    TabItem.findViewById(R.id.tab_item_img).setBackground(unselectdrawableList.get(i));
            }
        }
    }

总结

代码整体满足了一句话搞定Android底部导航栏,一键绑定Fragment、ViewPager的功能,当然,

有了需求才有了功能,有了想法才有了创作,你的反馈会是使我进步的最大动力。

觉得还不够方便?还想要什么功能?告诉我!欢迎反馈,欢迎Star。源码入口: UseBottomTabBar-GitHub项目地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容