• 三种实现Android主界面Tab的方式


    在平时的Android开发中,我们经常会使用Tab来进行主界面的布局。由于手机屏幕尺寸的限制,合理使用Tab可以极大的利用屏幕资源,给用户带来良好的体验。学会Tab的使用方法已经成为学习Android开发必不可少的技能了。我们经常使用的微信、QQ就是使用Tab的方式进行主界面的布局的。

      

    下面我们通过三种方式实现旧版的微信主界面以演示Tab的使用方式。

    最终效果:

    第一种:单纯使用ViewPager

    MainActivity.java

    复制代码
    public class MainActivity extends Activity implements OnClickListener {
        //声明ViewPager
        private ViewPager mViewpager;
    
        //声明四个Tab
        private LinearLayout mTabWeixin;
        private LinearLayout mTabFrd;
        private LinearLayout mTabAddress;
        private LinearLayout mTabSetting;
    
        //声明四个ImageButton
        private ImageButton mWeixinImg;
        private ImageButton mFrdImg;
        private ImageButton mAddressImg;
        private ImageButton mSettingImg;
    
        //声明ViewPager的适配器
        private PagerAdapter mAdpater;
        //用于装载四个Tab的List
        private List<View> mTabs = new ArrayList<View>();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            //去掉TitleBar
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.activity_main);
            initViews();//初始化控件
            initDatas();//初始化数据
            initEvents();//初始化事件
    
        }
    
        private void initEvents() {
            //设置四个Tab的点击事件
            mTabWeixin.setOnClickListener(this);
            mTabFrd.setOnClickListener(this);
            mTabAddress.setOnClickListener(this);
            mTabSetting.setOnClickListener(this);
    
            //添加ViewPager的切换Tab的监听事件
            mViewpager.addOnPageChangeListener(new OnPageChangeListener() {
                @Override
                public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
                }
    
                @Override
                public void onPageSelected(int position) {
                    //获取ViewPager的当前Tab
                    int currentItem = mViewpager.getCurrentItem();
                    //将所以的ImageButton设置成灰色
                    resetImgs();
                    //将当前Tab对应的ImageButton设置成绿色
                    switch (currentItem) {
                        case 0:
                            mWeixinImg.setImageResource(R.mipmap.tab_weixin_pressed);
                            break;
                        case 1:
                            mFrdImg.setImageResource(R.mipmap.tab_find_frd_pressed);
                            break;
                        case 2:
                            mAddressImg.setImageResource(R.mipmap.tab_address_pressed);
                            break;
                        case 3:
                            mSettingImg.setImageResource(R.mipmap.tab_settings_pressed);
                            break;
                    }
                }
    
                @Override
                public void onPageScrollStateChanged(int state) {
    
                }
            });
        }
    
        private void initDatas() {
            //初始化ViewPager的适配器
            mAdpater = new PagerAdapter() {
                @Override
                public int getCount() {
                    return mTabs.size();
                }
    
                @Override
                public boolean isViewFromObject(View view, Object object) {
                    return view == object;
                }
    
                @Override
                public Object instantiateItem(ViewGroup container, int position) {
                    View view = mTabs.get(position);
                    container.addView(view);
                    return view;
                }
    
                @Override
                public void destroyItem(ViewGroup container, int position, Object object) {
                    container.removeView(mTabs.get(position));
                }
            };
            //设置ViewPager的适配器
            mViewpager.setAdapter(mAdpater);
        }
    
        //初始化控件
        private void initViews() {
            mViewpager = (ViewPager) findViewById(R.id.id_viewpager);
    
            mTabWeixin = (LinearLayout) findViewById(R.id.id_tab_weixin);
            mTabFrd = (LinearLayout) findViewById(R.id.id_tab_frd);
            mTabAddress = (LinearLayout) findViewById(R.id.id_tab_address);
            mTabSetting = (LinearLayout) findViewById(R.id.id_tab_setting);
    
            mWeixinImg = (ImageButton) findViewById(R.id.id_tab_weixin_img);
            mFrdImg = (ImageButton) findViewById(R.id.id_tab_frd_img);
            mAddressImg = (ImageButton) findViewById(R.id.id_tab_address_img);
            mSettingImg = (ImageButton) findViewById(R.id.id_tab_setting_img);
    
            //获取到四个Tab
            LayoutInflater inflater = LayoutInflater.from(this);
            View tab1 = inflater.inflate(R.layout.tab1, null);
            View tab2 = inflater.inflate(R.layout.tab2, null);
            View tab3 = inflater.inflate(R.layout.tab3, null);
            View tab4 = inflater.inflate(R.layout.tab4, null);
    
            //将四个Tab添加到集合中
            mTabs.add(tab1);
            mTabs.add(tab2);
            mTabs.add(tab3);
            mTabs.add(tab4);
    
        }
    
        @Override
        public void onClick(View v) {
            //先将四个ImageButton都设置成灰色
            resetImgs();
            switch (v.getId()) {
                case R.id.id_tab_weixin:
                    //设置viewPager的当前Tab
                    mViewpager.setCurrentItem(0);
                    //将当前Tab对应的ImageButton设置成绿色
                    mWeixinImg.setImageResource(R.mipmap.tab_weixin_pressed);
                    break;
                case R.id.id_tab_frd:
                    mViewpager.setCurrentItem(1);
                    mFrdImg.setImageResource(R.mipmap.tab_find_frd_pressed);
                    break;
                case R.id.id_tab_address:
                    mViewpager.setCurrentItem(2);
                    mAddressImg.setImageResource(R.mipmap.tab_address_pressed);
                    break;
                case R.id.id_tab_setting:
                    mViewpager.setCurrentItem(3);
                    mSettingImg.setImageResource(R.mipmap.tab_settings_pressed);
                    break;
            }
        }
    
        //将四个ImageButton设置成灰色
        private void resetImgs () {
            mWeixinImg.setImageResource(R.mipmap.tab_weixin_normal);
            mFrdImg.setImageResource(R.mipmap.tab_find_frd_normal);
            mAddressImg.setImageResource(R.mipmap.tab_address_normal);
            mSettingImg.setImageResource(R.mipmap.tab_settings_normal);
        }
    }
    复制代码

    顶部布局文件

     top.xml

    四个Tab对应页面的布局文件

     tab1.xml
     tab2.xml
     tab3.xml
     tab4.xml

    底部布局文件

     bottom.xml

    主布局文件

    复制代码
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <include layout="@layout/top"/>
    
        <android.support.v4.view.ViewPager
            android:id="@+id/id_viewpager"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
    
        </android.support.v4.view.ViewPager>
    
        <include layout="@layout/bottom"/>
    </LinearLayout>
    复制代码

    完整源码 : 点击下载

    单纯使用ViewPager的方式可以实现左右滑动切换页面和点击Tab切换页面的效果。但是大家发现,这种方式需要在Activity完成所有的代码实现,包括初始化Tab及其对应页面的初始化控件、数据、事件及业务逻辑的处理。这样会使得Activity看起来非常臃肿,进而造成代码的可读性和可维护性变得极差。

    谷歌在Android 3.0时推出了Fragment。可以分别使用Fragment来管理每个Tab对应的页面的布局及功能的实现。然后将Fragment与Android关联,这样Android只需要管理Fragment就行了,起到了调度器的作用,不再关心每个Fragment里的内容及功能实现是什么。这样就极大的解放了Activity,使代码变得简单、易读。

    下面我们通过使用Fragment的方式来实现Tab。

    第二种:单纯使用Fragment

    MainActivity.java

    复制代码
    public class MainActivity extends FragmentActivity implements OnClickListener {
        //声明四个Tab的布局文件
        private LinearLayout mTabWeixin;
        private LinearLayout mTabFrd;
        private LinearLayout mTabAddress;
        private LinearLayout mTabSetting;
    
        //声明四个Tab的ImageButton
        private ImageButton mWeixinImg;
        private ImageButton mFrdImg;
        private ImageButton mAddressImg;
        private ImageButton mSettingImg;
    
        //声明四个Tab分别对应的Fragment
        private Fragment mFragWeinxin;
        private Fragment mFragFrd;
        private Fragment mFragAddress;
        private Fragment mFragSetting;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.activity_main);
            initViews();//初始化控件
            initEvents();//初始化事件
            selectTab(0);//默认选中第一个Tab
        }
    
        private void initEvents() {
            //初始化四个Tab的点击事件
            mTabWeixin.setOnClickListener(this);
            mTabFrd.setOnClickListener(this);
            mTabAddress.setOnClickListener(this);
            mTabSetting.setOnClickListener(this);
        }
    
        private void initViews() {
            //初始化四个Tab的布局文件
            mTabWeixin = (LinearLayout) findViewById(R.id.id_tab_weixin);
            mTabFrd = (LinearLayout) findViewById(R.id.id_tab_frd);
            mTabAddress = (LinearLayout) findViewById(R.id.id_tab_address);
            mTabSetting = (LinearLayout) findViewById(R.id.id_tab_setting);
    
            //初始化四个ImageButton
            mWeixinImg = (ImageButton) findViewById(R.id.id_tab_weixin_img);
            mFrdImg = (ImageButton) findViewById(R.id.id_tab_frd_img);
            mAddressImg = (ImageButton) findViewById(R.id.id_tab_address_img);
            mSettingImg = (ImageButton) findViewById(R.id.id_tab_setting_img);
        }
    
        //处理Tab的点击事件
        @Override
        public void onClick(View v) {
            //先将四个ImageButton置为灰色
            resetImgs();
            switch (v.getId()) {
                case R.id.id_tab_weixin:
                    selectTab(0);//当点击的是微信的Tab就选中微信的Tab
                    break;
                case R.id.id_tab_frd:
                    selectTab(1);
                    break;
                case R.id.id_tab_address:
                    selectTab(2);
                    break;
                case R.id.id_tab_setting:
                    selectTab(3);
                    break;
            }
    
        }
    
        //进行选中Tab的处理
        private void selectTab(int i) {
            //获取FragmentManager对象
            FragmentManager manager = getSupportFragmentManager();
            //获取FragmentTransaction对象
            FragmentTransaction transaction = manager.beginTransaction();
            //先隐藏所有的Fragment
            hideFragments(transaction);
            switch (i) {
                //当选中点击的是微信的Tab时
                case 0:
                    //设置微信的ImageButton为绿色
                    mWeixinImg.setImageResource(R.mipmap.tab_weixin_pressed);
                    //如果微信对应的Fragment没有实例化,则进行实例化,并显示出来
                    if (mFragWeinxin == null) {
                        mFragWeinxin = new WeixinFragment();
                        transaction.add(R.id.id_content, mFragWeinxin);
                    } else {
                        //如果微信对应的Fragment已经实例化,则直接显示出来
                        transaction.show(mFragWeinxin);
                    }
                    break;
                case 1:
                    mFrdImg.setImageResource(R.mipmap.tab_find_frd_pressed);
                    if (mFragFrd == null) {
                        mFragFrd = new FrdFragment();
                        transaction.add(R.id.id_content, mFragFrd);
                    } else {
                        transaction.show(mFragFrd);
                    }
                    break;
                case 2:
                    mAddressImg.setImageResource(R.mipmap.tab_address_pressed);
                    if (mFragAddress == null) {
                        mFragAddress = new AddressFragment();
                        transaction.add(R.id.id_content, mFragAddress);
                    } else {
                        transaction.show(mFragAddress);
                    }
                    break;
                case 3:
                    mSettingImg.setImageResource(R.mipmap.tab_settings_pressed);
                    if (mFragSetting == null) {
                        mFragSetting = new SettingFragment();
                        transaction.add(R.id.id_content, mFragSetting);
                    } else {
                        transaction.show(mFragSetting);
                    }
                    break;
            }
            //不要忘记提交事务
            transaction.commit();
        }
    
        //将四个的Fragment隐藏
        private void hideFragments(FragmentTransaction transaction) {
            if (mFragWeinxin != null) {
                transaction.hide(mFragWeinxin);
            }
            if (mFragFrd != null) {
                transaction.hide(mFragFrd);
            }
            if (mFragAddress != null) {
                transaction.hide(mFragAddress);
            }
            if (mFragSetting != null) {
                transaction.hide(mFragSetting);
            }
        }
    
        //将四个ImageButton置为灰色
        private void resetImgs() {
            mWeixinImg.setImageResource(R.mipmap.tab_weixin_normal);
            mFrdImg.setImageResource(R.mipmap.tab_find_frd_normal);
            mAddressImg.setImageResource(R.mipmap.tab_address_normal);
            mSettingImg.setImageResource(R.mipmap.tab_settings_normal);
        }
    }
    复制代码

    “微信”、“朋友”、“通讯录”、“设置”所对应的Fragment

    复制代码
    public class WeixinFragment extends Fragment{
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.tab1, container, false);
            return view;
        }
    }
    复制代码
     FrdFragment.java
     AddressFragment.java
     SettingFragment.java

    顶部布局文件

     top.xml

    四个Tab对应页面的布局文件

     tab1.xml
     tab2.xml
     tab3.xml
     tab4.xml

    底部布局文件

     bottom.xml

    主布局文件

    复制代码
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <include layout="@layout/top"/>
    
        <FrameLayout
            android:id="@+id/id_content"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
    
        </FrameLayout>
    
        <include layout="@layout/bottom"/>
    </LinearLayout>
    复制代码

    完整源码 : 点击下载

    可以看出,使用Fragment实现了Activity与Tab对应的页面分离,特别是当Tab对应的页面的布局和逻辑比较复杂时更能体会到使用Fragment的好处。但是单纯使用Fragment只能通过点击Tab来切换页面,并不能实现左右滑动进行切换。

    下面我们通过使用 ViewPager + Fragment 的方式实现Tab,这也是开发中使用比较广泛的一种方式。

    第三种:使用 ViewPager + Fragment

    MainActivity.java

    复制代码
    public class MainActivity extends FragmentActivity implements OnClickListener {
        //声明ViewPager
        private ViewPager mViewPager;
        //适配器
        private FragmentPagerAdapter mAdapter;
        //装载Fragment的集合
        private List<Fragment> mFragments;
    
        //四个Tab对应的布局
        private LinearLayout mTabWeixin;
        private LinearLayout mTabFrd;
        private LinearLayout mTabAddress;
        private LinearLayout mTabSetting;
    
        //四个Tab对应的ImageButton
        private ImageButton mImgWeixin;
        private ImageButton mImgFrd;
        private ImageButton mImgAddress;
        private ImageButton mImgSetting;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.activity_main);
            initViews();//初始化控件
            initEvents();//初始化事件
            initDatas();//初始化数据
        }
    
        private void initDatas() {
            mFragments = new ArrayList<>();
            //将四个Fragment加入集合中
            mFragments.add(new WeixinFragment());
            mFragments.add(new FrdFragment());
            mFragments.add(new AddressFragment());
            mFragments.add(new SettingFragment());
    
            //初始化适配器
            mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
                @Override
                public Fragment getItem(int position) {//从集合中获取对应位置的Fragment
                    return mFragments.get(position);
                }
    
                @Override
                public int getCount() {//获取集合中Fragment的总数
                    return mFragments.size();
                }
    
            };
            //不要忘记设置ViewPager的适配器
            mViewPager.setAdapter(mAdapter);
            //设置ViewPager的切换监听
            mViewPager.addOnPageChangeListener(new OnPageChangeListener() {
                @Override
                //页面滚动事件
                public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
                }
    
                //页面选中事件
                @Override
                public void onPageSelected(int position) {
                    //设置position对应的集合中的Fragment
                    mViewPager.setCurrentItem(position);
                    resetImgs();
                    selectTab(position);
                }
    
                @Override
                //页面滚动状态改变事件
                public void onPageScrollStateChanged(int state) {
    
                }
            });
        }
    
        private void initEvents() {
            //设置四个Tab的点击事件
            mTabWeixin.setOnClickListener(this);
            mTabFrd.setOnClickListener(this);
            mTabAddress.setOnClickListener(this);
            mTabSetting.setOnClickListener(this);
    
        }
    
        //初始化控件
        private void initViews() {
            mViewPager = (ViewPager) findViewById(R.id.id_viewpager);
    
            mTabWeixin = (LinearLayout) findViewById(R.id.id_tab_weixin);
            mTabFrd = (LinearLayout) findViewById(R.id.id_tab_frd);
            mTabAddress = (LinearLayout) findViewById(R.id.id_tab_address);
            mTabSetting = (LinearLayout) findViewById(R.id.id_tab_setting);
    
            mImgWeixin = (ImageButton) findViewById(R.id.id_tab_weixin_img);
            mImgFrd = (ImageButton) findViewById(R.id.id_tab_frd_img);
            mImgAddress = (ImageButton) findViewById(R.id.id_tab_address_img);
            mImgSetting = (ImageButton) findViewById(R.id.id_tab_setting_img);
    
        }
    
        @Override
        public void onClick(View v) {
            //先将四个ImageButton置为灰色
            resetImgs();
    
            //根据点击的Tab切换不同的页面及设置对应的ImageButton为绿色
            switch (v.getId()) {
                case R.id.id_tab_weixin:
                    selectTab(0);
                    break;
                case R.id.id_tab_frd:
                    selectTab(1);
                    break;
                case R.id.id_tab_address:
                    selectTab(2);
                    break;
                case R.id.id_tab_setting:
                    selectTab(3);
                    break;
            }
        }
    
        private void selectTab(int i) {
            //根据点击的Tab设置对应的ImageButton为绿色
            switch (i) {
                case 0:
                    mImgWeixin.setImageResource(R.mipmap.tab_weixin_pressed);
                    break;
                case 1:
                    mImgFrd.setImageResource(R.mipmap.tab_find_frd_pressed);
                    break;
                case 2:
                    mImgAddress.setImageResource(R.mipmap.tab_address_pressed);
                    break;
                case 3:
                    mImgSetting.setImageResource(R.mipmap.tab_settings_pressed);
                    break;
            }
            //设置当前点击的Tab所对应的页面
            mViewPager.setCurrentItem(i);
        }
    
        //将四个ImageButton设置为灰色
        private void resetImgs() {
            mImgWeixin.setImageResource(R.mipmap.tab_weixin_normal);
            mImgFrd.setImageResource(R.mipmap.tab_find_frd_normal);
            mImgAddress.setImageResource(R.mipmap.tab_address_normal);
            mImgSetting.setImageResource(R.mipmap.tab_settings_normal);
        }
    }
    复制代码

    “微信”、“朋友”、“通讯录”、“设置”所对应的Fragment

     WeixinFragment.java
     FrdFragment.java
    复制代码
    public class AddressFragment extends Fragment {
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.tab3, container, false);
            return view;
        }
    }
    复制代码
     SettingFragment.java

    顶部布局文件

     top.xml

    四个Tab对应页面的布局文件

    复制代码
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:orientation="vertical"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:textSize="30sp"
            android:text="The Weixin Tab!"/>
    </LinearLayout>
    复制代码
     tab2.xml
     tab3.xml
     tab4.xml

    底部布局文件

     bottom.xml

    主布局文件

     activity_main.xml

    完整源码 : 点击下载

    使用 ViewPager + Fragment 的方式综合了使用ViewPager和使用Fragment的优势,即:既能使用Fragment管理Tab对应页面的布局及业务逻辑的实现,使得Activity与Tab对应的页面分离,又能使用ViewPager实现左右滑动切换页面的效果。这种方式需要为ViewPager设置FragmentPagerAdapter适配器,关于适配器的知识可参考我之前写的一篇

  • 相关阅读:
    (转)Golang reflect.DeepEqual函数:判断两个值是否一致
    Kubernetes字段Finalizers
    校园电子屏无人值守模式探索
    史上最全测试开发工具推荐(含自动化、性能、稳定性、抓包)
    Java 将Word转为HTML的方法
    C# 在PPT中添加数学公式
    C# 将PPT转为OFD/DPT/DPS/ODP/POTX/UOP
    C# 将Excel转为OFD、UOS
    Java 扫描识别条形码图片
    C# 加载Word的3种方法
  • 原文地址:https://www.cnblogs.com/vana/p/11189496.html
Copyright © 2020-2023  润新知