Android开发-两种方式实现Android应用底部Tab标签栏

前 言

在我们日常使用的Android应用中,几乎所有的应用都使用到底部Tab标签栏,比如微信、淘宝、支付宝等。而他们实现的方式又大同小异,实现底部Tab标签栏无非有两种方式,一是使用“show()和hide()控制Fragment”方式,这种方式也称之为使用事务的方式,是目前大多数的应用都使用这种方式的,如淘宝、支付宝,二是使用“Fragment+ViewPager”的方式,这种方式是微信所使用的。那么,下面就来看看如何实现吧。

使用show()和hide()控制Fragment的方式

首先先定义一个布局,布局里主要显示底部icon图标和文本信息。如下布局所示:




    

        

            

            
        

        

            

            
        

        

            

            
        
    

    

    


然后接着在Activity代码里实现,代码如下:

mHomeView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_home_selected));
home_text_view.setTextColor(getResources().getColor(R.color.comui_tab_selected));

mHomeFragment = new HomeFragment();
fm = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.content_layout, mHomeFragment);
fragmentTransaction.commit();

上面的代码是实现应用进入首页后默认要加载的Tab,然后以事务的方式提交。

 public void labelSelection(int position) {

        FragmentTransaction fragmentTransaction = fm.beginTransaction();
        switch (position) {
            case 0:
                mHomeView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_home_selected));
                home_text_view.setTextColor(getResources().getColor(R.color.comui_tab_selected));
                mMessageView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_message));
                message_text_view.setTextColor(getResources().getColor(R.color.comui_tab));
                mMineView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_person));
                mine_text_view.setTextColor(getResources().getColor(R.color.comui_tab));
                hideFragment(mCommonFragmentOne, fragmentTransaction);
                hideFragment(mMessageFragment, fragmentTransaction);
                hideFragment(mMineFragment, fragmentTransaction);
                if (mHomeFragment == null) {
                    mHomeFragment = new HomeFragment();
                    fragmentTransaction.add(R.id.content_layout, mHomeFragment);
                } else {
                    mCurrent = mHomeFragment;
                    fragmentTransaction.show(mHomeFragment);
                }
                break;
            case 1:
                mMessageView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_message_selected));
                message_text_view.setTextColor(getResources().getColor(R.color.comui_tab_selected));
                mHomeView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_home));
                home_text_view.setTextColor(getResources().getColor(R.color.comui_tab));
                mMineView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_person));
                mine_text_view.setTextColor(getResources().getColor(R.color.comui_tab));
                hideFragment(mCommonFragmentOne, fragmentTransaction);
                hideFragment(mHomeFragment, fragmentTransaction);
                hideFragment(mMineFragment, fragmentTransaction);
                if (mMessageFragment == null) {
                    mMessageFragment = new MessageFragment();
                    fragmentTransaction.add(R.id.content_layout, mMessageFragment);
                } else {
                    mCurrent = mMessageFragment;
                    fragmentTransaction.show(mMessageFragment);
                }
                break;
            case 2:
                mMineView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_person_selected));
                mine_text_view.setTextColor(getResources().getColor(R.color.comui_tab_selected));
                mHomeView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_home));
                home_text_view.setTextColor(getResources().getColor(R.color.comui_tab));
                mMessageView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_message));
                message_text_view.setTextColor(getResources().getColor(R.color.comui_tab));
                hideFragment(mCommonFragmentOne, fragmentTransaction);
                hideFragment(mMessageFragment, fragmentTransaction);
                hideFragment(mHomeFragment, fragmentTransaction);
                if (mMineFragment == null) {
                    mMineFragment = new MineFragment();
                    fragmentTransaction.add(R.id.content_layout, mMineFragment);
                } else {
                    mCurrent = mMineFragment;
                    fragmentTransaction.show(mMineFragment);
                }
                break;
            default:
                break;
        }
        fragmentTransaction.commit();

    }

上面的代码主要实现当用户切换底部Tab标签后要更换不用颜色的icon和不用颜色的文本以及加载对应的Fragment界面。

为了更好的理解,下面附上Activity完整的代码:

public class Home1Activity extends BaseActivity implements View.OnClickListener {

    public static Home1Activity instance;

    private FragmentManager fm;
    private HomeFragment mHomeFragment;
    private Fragment mCommonFragmentOne;
    private MessageFragment mMessageFragment;
    private MineFragment mMineFragment;
    private Fragment mCurrent;

    private RelativeLayout mHomeLayout;
    private RelativeLayout mMessageLayout;
    private RelativeLayout mMineLayout;
    private ImageView mHomeView;
    private TextView home_text_view;
    private ImageView mMessageView;
    private TextView message_text_view;
    private ImageView mMineView;
    private TextView mine_text_view;

    private long exitTime = 0;

    @Override
    protected int getLayoutId() {
        instance = this;
        return R.layout.activity_home1_layout;
    }

    @Override
    protected void initView() {

        mHomeLayout = (RelativeLayout) findViewById(R.id.home_layout_view);
        mHomeLayout.setOnClickListener(this);
        mMessageLayout = (RelativeLayout) findViewById(R.id.message_layout_view);
        mMessageLayout.setOnClickListener(this);
        mMineLayout = (RelativeLayout) findViewById(R.id.mine_layout_view);
        mMineLayout.setOnClickListener(this);

        mHomeView = (ImageView) findViewById(R.id.home_image_view);
        home_text_view = (TextView) findViewById(R.id.home_text_view);
        mMessageView = (ImageView) findViewById(R.id.message_image_view);
        message_text_view = (TextView) findViewById(R.id.message_text_view);
        mMineView = (ImageView) findViewById(R.id.mine_image_view);
        mine_text_view = (TextView) findViewById(R.id.mine_text_view);

        mHomeView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_home_selected));
        home_text_view.setTextColor(getResources().getColor(R.color.comui_tab_selected));

        mHomeFragment = new HomeFragment();
        fm = getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fm.beginTransaction();
        fragmentTransaction.replace(R.id.content_layout, mHomeFragment);
        fragmentTransaction.commit();

    }

    @Override
    protected void initData() {

    }

    private void hideFragment(Fragment fragment, FragmentTransaction ft) {
        if (fragment != null) {
            ft.hide(fragment);
        }
    }

    @Override
    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.home_layout_view:
                labelSelection(0);
                break;
            case R.id.message_layout_view:
                labelSelection(1);
                break;
            case R.id.mine_layout_view:
                labelSelection(2);
                break;
            default:
                break;
        }
    }

    public void labelSelection(int position) {

        FragmentTransaction fragmentTransaction = fm.beginTransaction();
        switch (position) {
            case 0:
                mHomeView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_home_selected));
                home_text_view.setTextColor(getResources().getColor(R.color.comui_tab_selected));
                mMessageView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_message));
                message_text_view.setTextColor(getResources().getColor(R.color.comui_tab));
                mMineView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_person));
                mine_text_view.setTextColor(getResources().getColor(R.color.comui_tab));
                hideFragment(mCommonFragmentOne, fragmentTransaction);
                hideFragment(mMessageFragment, fragmentTransaction);
                hideFragment(mMineFragment, fragmentTransaction);
                if (mHomeFragment == null) {
                    mHomeFragment = new HomeFragment();
                    fragmentTransaction.add(R.id.content_layout, mHomeFragment);
                } else {
                    mCurrent = mHomeFragment;
                    fragmentTransaction.show(mHomeFragment);
                }
                break;
            case 1:
                mMessageView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_message_selected));
                message_text_view.setTextColor(getResources().getColor(R.color.comui_tab_selected));
                mHomeView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_home));
                home_text_view.setTextColor(getResources().getColor(R.color.comui_tab));
                mMineView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_person));
                mine_text_view.setTextColor(getResources().getColor(R.color.comui_tab));
                hideFragment(mCommonFragmentOne, fragmentTransaction);
                hideFragment(mHomeFragment, fragmentTransaction);
                hideFragment(mMineFragment, fragmentTransaction);
                if (mMessageFragment == null) {
                    mMessageFragment = new MessageFragment();
                    fragmentTransaction.add(R.id.content_layout, mMessageFragment);
                } else {
                    mCurrent = mMessageFragment;
                    fragmentTransaction.show(mMessageFragment);
                }
                break;
            case 2:
                mMineView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_person_selected));
                mine_text_view.setTextColor(getResources().getColor(R.color.comui_tab_selected));
                mHomeView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_home));
                home_text_view.setTextColor(getResources().getColor(R.color.comui_tab));
                mMessageView.setImageDrawable(getResources().getDrawable(R.drawable.comui_tab_message));
                message_text_view.setTextColor(getResources().getColor(R.color.comui_tab));
                hideFragment(mCommonFragmentOne, fragmentTransaction);
                hideFragment(mMessageFragment, fragmentTransaction);
                hideFragment(mHomeFragment, fragmentTransaction);
                if (mMineFragment == null) {
                    mMineFragment = new MineFragment();
                    fragmentTransaction.add(R.id.content_layout, mMineFragment);
                } else {
                    mCurrent = mMineFragment;
                    fragmentTransaction.show(mMineFragment);
                }
                break;
            default:
                break;
        }
        fragmentTransaction.commit();

    }

    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {

            if ((System.currentTimeMillis() - exitTime) > 2000) {
                ToastUtil.showToast("再按一次退出应用");
                exitTime = System.currentTimeMillis();
            } else {
//                Intent intent = new Intent(Intent.ACTION_MAIN);
//                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//                intent.addCategory(Intent.CATEGORY_HOME);
//                startActivity(intent);
                finish();
            }
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}

界面运行效果图如下:
Android开发-两种方式实现Android应用底部Tab标签栏_第1张图片

使用Fragment+ViewPager的方式

先定义一个xml布局,布局xml代码如下,布局中的AlphaTabsIndicator控件是用到自定义View,它继承于LinearLayout布局。




    

    

    

        

        

        

    


自定义View的AlphaTabsIndicator控件代码如下。

public class AlphaTabsIndicator extends LinearLayout {

    private ViewPager mViewPager;
    private OnTabChangedListner mListner;
    private List mTabViews;
    private boolean ISINIT;
    /**
     * 子View的数量
     */
    private int mChildCounts;
    /**
     * 当前的条目索引
     */
    private int mCurrentItem = 0;

    public AlphaTabsIndicator(Context context) {
        this(context, null);
    }

    public AlphaTabsIndicator(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public AlphaTabsIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        post(new Runnable() {
            @Override
            public void run() {
                isInit();
            }
        });
    }

    public void setViewPager(ViewPager mViewPager) {
        this.mViewPager = mViewPager;
        init();
    }

    public void setOnTabChangedListner(OnTabChangedListner listner) {
        this.mListner = listner;
        isInit();
    }

    public AlphaTabView getCurrentItemView() {
        isInit();
        return mTabViews.get(mCurrentItem);
    }

    public AlphaTabView getTabView(int tabIndex) {
        isInit();
        return mTabViews.get(tabIndex);
    }

    public void removeAllBadge() {
        isInit();
        for (AlphaTabView alphaTabView : mTabViews) {
            alphaTabView.removeShow();
        }
    }

    public void setTabCurrenItem(int tabIndex) {
        if (tabIndex < mChildCounts && tabIndex > -1) {
            mTabViews.get(tabIndex).performClick();
        } else {
            throw new IllegalArgumentException("IndexOutOfBoundsException");
        }

    }

    private void isInit() {
        if (!ISINIT) {
            init();
        }
    }

    private void init() {
        ISINIT = true;
        mTabViews = new ArrayList<>();
        mChildCounts = getChildCount();

        if (null != mViewPager) {
            if (null == mViewPager.getAdapter()) {
                throw new NullPointerException("viewpager的adapter为null");
            }
            if (mViewPager.getAdapter().getCount() != mChildCounts) {
                throw new IllegalArgumentException("子View数量必须和ViewPager条目数量一致");
            }
            //对ViewPager添加监听
            mViewPager.addOnPageChangeListener(new MyOnPageChangeListener());
        }

        for (int i = 0; i < mChildCounts; i++) {
            if (getChildAt(i) instanceof AlphaTabView) {
                AlphaTabView tabView = (AlphaTabView) getChildAt(i);
                mTabViews.add(tabView);
                //设置点击监听
                tabView.setOnClickListener(new MyOnClickListener(i));
            } else {
                throw new IllegalArgumentException("TabIndicator的子View必须是TabView");
            }
        }

        mTabViews.get(mCurrentItem).setIconAlpha(1.0f);
    }

    private class MyOnPageChangeListener extends ViewPager.SimpleOnPageChangeListener {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            //滑动时的透明度动画
            if (positionOffset > 0) {
                mTabViews.get(position).setIconAlpha(1 - positionOffset);
                mTabViews.get(position + 1).setIconAlpha(positionOffset);
            }
            //滑动时保存当前按钮索引
            mCurrentItem = position;
        }

        @Override
        public void onPageSelected(int position) {
            super.onPageSelected(position);
            resetState();
            mTabViews.get(position).setIconAlpha(1.0f);
            mCurrentItem = position;
        }
    }

    private class MyOnClickListener implements OnClickListener {

        private int currentIndex;

        public MyOnClickListener(int i) {
            this.currentIndex = i;
        }

        @Override
        public void onClick(View v) {
            //点击前先重置所有按钮的状态
            resetState();
            mTabViews.get(currentIndex).setIconAlpha(1.0f);
            if (null != mListner) {
                mListner.onTabSelected(currentIndex);
            }
            if (null != mViewPager) {
                //不能使用平滑滚动,否者颜色改变会乱
                mViewPager.setCurrentItem(currentIndex, false);
            }
            //点击是保存当前按钮索引
            mCurrentItem = currentIndex;
        }
    }

    /**
     * 重置所有按钮的状态
     */
    private void resetState() {
        for (int i = 0; i < mChildCounts; i++) {
            mTabViews.get(i).setIconAlpha(0);
        }
    }

    private static final String STATE_INSTANCE = "instance_state";
    private static final String STATE_ITEM = "state_item";

    /**
     * @return 当View被销毁的时候,保存数据
     */
    @Override
    protected Parcelable onSaveInstanceState() {
        Bundle bundle = new Bundle();
        bundle.putParcelable(STATE_INSTANCE, super.onSaveInstanceState());
        bundle.putInt(STATE_ITEM, mCurrentItem);
        return bundle;
    }

    /**
     * @param state 用于恢复数据使用
     */
    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        if (state instanceof Bundle) {
            Bundle bundle = (Bundle) state;
            mCurrentItem = bundle.getInt(STATE_ITEM);
            if (null == mTabViews || mTabViews.isEmpty()) {
                super.onRestoreInstanceState(bundle.getParcelable(STATE_INSTANCE));
                return;
            }
            //重置所有按钮状态
            resetState();
            //恢复点击的条目颜色
            mTabViews.get(mCurrentItem).setIconAlpha(1.0f);
            super.onRestoreInstanceState(bundle.getParcelable(STATE_INSTANCE));
        } else {
            super.onRestoreInstanceState(state);
        }
    }
}

然后接着在Activity代码里实现,代码如下:

public class Home2Activity extends BaseActivity {

    private AlphaTabsIndicator alphaTabsIndicator;
    private long exitTime = 0;

    @Override
    protected int getLayoutId() {
        return R.layout.activity_home2_layout;
    }

    @Override
    protected void initView() {
        ViewPager mViewPger = (ViewPager) findViewById(R.id.mViewPager);
        Home2Activity.HomeAdapter mainAdapter = new Home2Activity.HomeAdapter(getSupportFragmentManager());
        mViewPger.setAdapter(mainAdapter);
        mViewPger.addOnPageChangeListener(mainAdapter);

        alphaTabsIndicator = (AlphaTabsIndicator) findViewById(R.id.alphaIndicator);
        alphaTabsIndicator.setViewPager(mViewPger);

        alphaTabsIndicator.getTabView(0).showNumber(10);
        alphaTabsIndicator.getTabView(1).showNumber(100);
        alphaTabsIndicator.getTabView(2).showPoint();
    }

    @Override
    protected void initData() {

    }


    private class HomeAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener {

        private List fragments = new ArrayList<>();
        private String[] titles = {"首页", "消息", "我的"};

        public HomeAdapter(FragmentManager fm) {
            super(fm);
            fragments.add(HomeFragment.newInstance(titles[0]));
            fragments.add(MessageFragment.newInstance(titles[1]));
            fragments.add(MineFragment.newInstance(titles[2]));
        }

        @Override
        public Fragment getItem(int position) {
            return fragments.get(position);
        }

        @Override
        public int getCount() {
            return fragments.size();
        }

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            if (0 == position) {
                alphaTabsIndicator.getCurrentItemView().removeShow();
            } else if (2 == position) {
                alphaTabsIndicator.getCurrentItemView().removeShow();
            } else if (3 == position) {
                alphaTabsIndicator.removeAllBadge();
            }
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    }

    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {

            if ((System.currentTimeMillis() - exitTime) > 2000) {
                ToastUtil.showToast("再按一次退出应用");
                exitTime = System.currentTimeMillis();
            } else {
//                Intent intent = new Intent(Intent.ACTION_MAIN);
//                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//                intent.addCategory(Intent.CATEGORY_HOME);
//                startActivity(intent);
                finish();
            }
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

}

上面代码是使用ViewPager的方式来实现,它支持点击底部按钮或者左右滑动的方式来切换不同的界面。

界面运行效果图如下:
Android开发-两种方式实现Android应用底部Tab标签栏_第2张图片

apk安装包下载体验地址:

可以扫描以下二维码进行下载安装,或者点击以下链接 https://fir.im/bottomTab 进行下载安装体验。

———————— The end ————————

码字不易,如果您觉得这篇博客写的比较好的话,可以赞赏一杯咖啡吧~~


Demo程序源码下载地址一(GitHub)
Demo程序源码下载地址二(码云)

你可能感兴趣的:(Android移动开发随笔)