程序员人生 网站导航

android-多种方式实现主界面的Tab

栏目:综合技术时间:2016-11-09 16:34:55

本人水平有限,文章中如果出现甚么不正确或模糊的地方,还请各位小火伴留下评论,多多指教 : )

  • 前言
  • 使用Fragment实现
    • 思路
    • 效果
    • 具体讲授
      • 底部布局
      • 顶部布局
      • Fragment的布局
      • Java控制代码
  • 使用ViewPager实现
    • 思路
    • 效果
    • 具体实现
  • 使用ViewPagerFragmentPagerAdapter方法实现
    • 思路
    • 效果
    • 补充
    • 具体代码
  • 使用框架

前言

这篇文章主要介绍多种方式实现主界面的tab,包括:
(1)使用Fragment实现
(2)使用ViewPage实现
(3)使用ViewPage+FragmentPageAdapter
(4)使用框架实现

在线的视频课程来自慕课网——多种多样的App主界面Tab实现方法。觉得文字不好理解的小火伴可以去看视频,然后再回头自己敲1遍。

使用Fragment实现

比较常规的使用方法,需要大家对Fragment有基本了解,这里推荐hongyang大神的几篇博文:
Android Fragment 真实的完全解析(上)
Android Fragment 真实的完全解析(下)
相信各位看完以后对Fragment就可以有1个比较清楚的了解。

思路

这类方式实现的思路比较简单:
1、首先在主布局中加入FragmentLayout
2、然后在Java代码中监听底部的按钮,当点击时,只需让FragmentLayout加载相应的Fragment便可

这里写图片描述

效果

这里写图片描述

可以看到,如果单纯地使用Fragment,实际上是不能实现左右滑动的效果,页面的切换,只能靠点击底部的Button来实现。

具体讲授

底部布局

首先是底部的1个布局文件bottom.xml

<?xml version="1.0" encoding="utf⑻"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="65dp" android:background="@drawable/bottom_bar"> <LinearLayout android:id="@+id/id_tab_weixin" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <ImageButton android:id="@+id/id_tab_weixin_img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/tab_weixin_pressed" android:background="#0000"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#fff" android:text="微信"/> </LinearLayout> <LinearLayout android:id="@+id/id_tab_frd" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <ImageButton android:id="@+id/id_tab_frd_img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/tab_find_frd_normal" android:background="#0000"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#fff" android:text="朋友"/> </LinearLayout> <LinearLayout android:id="@+id/id_tab_address" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <ImageButton android:id="@+id/id_tab_address_img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/tab_address_normal" android:background="#0000"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#fff" android:text="通讯录"/> </LinearLayout> <LinearLayout android:id="@+id/id_tab_setting" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <ImageButton android:id="@+id/id_tab_setting_img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/tab_settings_normal" android:background="#0000"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#fff" android:text="设置"/> </LinearLayout> </LinearLayout>

简单的线性布局,放置我们的按钮。
这里写图片描述
这个布局在后面的栗子中也会使用。

顶部布局

接下来是1个顶部的title

<?xml version="1.0" encoding="utf⑻"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center" android:background="@drawable/title_bar"> <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="微信" android:textColor="#ffffff" android:textSize="20sp" android:textStyle="bold" android:layout_gravity="center"/> </LinearLayout>

就1个TextView。

Fragment的布局

这里写图片描述

为了简单起见,这里面的布局只放置1个TextView

Java控制代码

TestActivity2

public class TestActivity2 extends Activity implements View.OnClickListener { private LinearLayout mTabWeixin; private LinearLayout mTabFrd; private LinearLayout mTabAddress; private LinearLayout mTabSetting; //底部的按钮 private ImageButton mWeiXin; private ImageButton mFriend; private ImageButton mAddress; private ImageButton mSetting; //FragmentLayout要加载的4个Fragment private WeiXinFragment weiXinFragment; private FriendFragment friendFragment; private AddressFragment addressFragment; private SettingFragment settingFragment; //顶部的标题 private TextView tvTitle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.test_ac_2); initView(); initEvents(); setSelect(0); } private void initEvents() { mWeiXin.setOnClickListener(this); mFriend.setOnClickListener(this); mAddress.setOnClickListener(this); mSetting.setOnClickListener(this); } private void initView() { //初始化 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); mWeiXin= (ImageButton) findViewById(R.id.id_tab_weixin_img); mFriend= (ImageButton) findViewById(R.id.id_tab_frd_img); mAddress= (ImageButton) findViewById(R.id.id_tab_address_img); mSetting= (ImageButton) findViewById(R.id.id_tab_setting_img); tvTitle= (TextView) findViewById(R.id.tv_title); } @Override public void onClick(View view) { switch (view.getId()){ case R.id.id_tab_weixin_img: setSelect(0); break; case R.id.id_tab_frd_img: setSelect(1); break; case R.id.id_tab_address_img: setSelect(2); break; case R.id.id_tab_setting_img: setSelect(3); break; } } private void hideFragment(FragmentTransaction fragmentTransaction) { if (weiXinFragment!=null){ fragmentTransaction.hide(weiXinFragment); } if (friendFragment!=null){ fragmentTransaction.hide(friendFragment); } if (addressFragment!=null){ fragmentTransaction.hide(addressFragment); } if (settingFragment!=null){ fragmentTransaction.hide(settingFragment); } } /* * 重置所有的图片,让其恢复到灰色状态 * */ private void resetImage() { mSetting.setImageResource(R.drawable.tab_settings_normal); mWeiXin.setImageResource(R.drawable.tab_weixin_normal); mAddress.setImageResource(R.drawable.tab_address_normal); mFriend.setImageResource(R.drawable.tab_find_frd_normal); } /* * 设置某个Fragment * */ private void setSelect(int i){ FragmentManager fm=getFragmentManager(); FragmentTransaction fragmentTransaction=fm.beginTransaction(); //重置图片状态 resetImage(); hideFragment(fragmentTransaction); switch (i){ case 0: //设置标题 tvTitle.setText("微信"); if (weiXinFragment==null){ //如果Fragment还没实例化,实例化,并在fragmentTransaction中添加 weiXinFragment=new WeiXinFragment(); fragmentTransaction.add(R.id.id_content,weiXinFragment); }else{ //如果已实例化了,就显示 fragmentTransaction.show(weiXinFragment); } fragmentTransaction.commit(); //改变底部图标的状态 mWeiXin.setImageResource(R.drawable.tab_weixin_pressed); break; case 1: tvTitle.setText("朋友"); if (friendFragment==null){ friendFragment=new FriendFragment(); fragmentTransaction.add(R.id.id_content,friendFragment); }else{ fragmentTransaction.show(friendFragment); } fragmentTransaction.commit(); mFriend.setImageResource(R.drawable.tab_find_frd_pressed); break; case 2: tvTitle.setText("通讯录"); if (addressFragment==null){ addressFragment=new AddressFragment(); fragmentTransaction.add(R.id.id_content,addressFragment); }else{ fragmentTransaction.show(addressFragment); } fragmentTransaction.commit(); mAddress.setImageResource(R.drawable.tab_address_pressed); break; case 3: tvTitle.setText("设置"); if (settingFragment==null){ settingFragment=new SettingFragment(); fragmentTransaction.add(R.id.id_content,settingFragment); }else{ fragmentTransaction.show(settingFragment); } fragmentTransaction.commit(); mSetting.setImageResource(R.drawable.tab_settings_pressed); break; } } }

代码逻辑很清楚,中间需要提示的地方已用注释表明,这个小栗子其实就是Fragment的常规使用,触及到的内容也都是Fragment基础知识,需要各位小火伴烂熟于心。

使用ViewPager实现

思路

在上1个栗子当中,我们使用的是FragmentLayout来作为填充Fragment的容器。当使用ViewPage,我们需要把布局文件中的Layout替换成ViewPager。这就要求开发者对ViewPager的使用有基本的了解。

效果

这里写图片描述

可以看到使用了ViewPager以后不但可以实现左右的滑动,而且还能通过底部的点击来实现页面切换的效果

具体实现

首先是布局文件

<?xml version="1.0" encoding="utf⑻"?> <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_weight="1" android:layout_height="0dp"> </android.support.v4.view.ViewPager> <include layout="@layout/bottom"/> </LinearLayout>

非常简单,就是把中间的FragmentLayout换成了ViewPager。

重点在于接下里的Java代码当中,里面触及到了ViewPager的基本使用。

public class TestActivity1 extends Activity implements View.OnClickListener { private ViewPager viewPager; private PagerAdapter pagerAdapter; private List<View> mViews =new ArrayList<>(); private FragmentPagerAdapter fragmentPagerAdapter; private FragmentStatePagerAdapter fragmentStatePagerAdapter; private LinearLayout mTabWeixin; private LinearLayout mTabFrd; private LinearLayout mTabAddress; private LinearLayout mTabSetting; private ImageButton mWeiXin; private ImageButton mFriend; private ImageButton mAddress; private ImageButton mSetting; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.test_ac_1); initView(); initEvents(); } /* * 初始化事件 * */ private void initEvents() { mWeiXin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { viewPager.setCurrentItem(0); mWeiXin.setImageResource(R.drawable.tab_weixin_pressed); } }); mSetting.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { viewPager.setCurrentItem(3); mSetting.setImageResource(R.drawable.tab_settings_pressed); } }); mAddress.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { viewPager.setCurrentItem(2); mAddress.setImageResource(R.drawable.tab_address_pressed); } }); mFriend.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { viewPager.setCurrentItem(1); mFriend.setImageResource(R.drawable.tab_find_frd_pressed); } }); viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { int currentItem =viewPager.getCurrentItem(); resetImage(); switch (currentItem){ case 0: mWeiXin.setImageResource(R.drawable.tab_weixin_pressed); break; case 1: mFriend.setImageResource(R.drawable.tab_find_frd_pressed); break; case 2: mAddress.setImageResource(R.drawable.tab_address_pressed); break; case 3: mSetting.setImageResource(R.drawable.tab_settings_pressed); break; } } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { } }); } private void initView() { //初始化 viewPager= (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); mWeiXin= (ImageButton) findViewById(R.id.id_tab_weixin_img); mFriend= (ImageButton) findViewById(R.id.id_tab_frd_img); mAddress= (ImageButton) findViewById(R.id.id_tab_address_img); mSetting= (ImageButton) findViewById(R.id.id_tab_setting_img); LayoutInflater mLayoutInfater=LayoutInflater.from(this); View view1=mLayoutInfater.inflate(R.layout.tab01,null); View view2=mLayoutInfater.inflate(R.layout.tab02,null); View view3=mLayoutInfater.inflate(R.layout.tab03,null); View view4=mLayoutInfater.inflate(R.layout.tab04,null); mViews.add(view1); mViews.add(view2); mViews.add(view3); mViews.add(view4); pagerAdapter=new PagerAdapter() { @Override public Object instantiateItem(ViewGroup container, int position) { View view=mViews.get(position); container.addView(view); return view; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(mViews.get(position)); } @Override public int getCount() { return mViews.size(); } @Override public boolean isViewFromObject(View view, Object object) { return view==object; } }; viewPager.setAdapter(pagerAdapter); } @Override public void onClick(View view) { Log.d("--tab--","tab click"); //重置所有的图片 resetImage(); switch (view.getId()){ case R.id.id_tab_weixin: viewPager.setCurrentItem(0); mWeiXin.setImageResource(R.drawable.tab_weixin_pressed); Log.d("--tab--","tab weixin"); break; case R.id.id_tab_frd: viewPager.setCurrentItem(1); mFriend.setImageResource(R.drawable.tab_find_frd_pressed); Log.d("--tab--","tab friend"); break; case R.id.id_tab_address: viewPager.setCurrentItem(2); mAddress.setImageResource(R.drawable.tab_address_pressed); Log.d("--tab--","tab address"); break; case R.id.id_tab_setting: viewPager.setCurrentItem(3); mSetting.setImageResource(R.drawable.tab_settings_pressed); Log.d("--tab--","tab setting"); break; } } /* * 让所有的图片都变暗 * */ private void resetImage() { mSetting.setImageResource(R.drawable.tab_settings_normal); mWeiXin.setImageResource(R.drawable.tab_weixin_normal); mAddress.setImageResource(R.drawable.tab_address_normal); mFriend.setImageResource(R.drawable.tab_find_frd_normal); } }

使用ViewPager+FragmentPagerAdapter方法实现

思路

同ViewPager实现相同

效果

同ViewPager实现相同

补充

既然这类方式使用的思路和效果和直接使用ViewPager的相同,那末采取FragmenAdapter的方式来实现Tab页面切换有甚么好处呢?

首先单纯使用ViewPager时,里面的View是通过LayoutInfater装载进去的,虽然也能够实现和和采取FragmentPagerAdapter1样的效果,但是如果这么做,必定所有的逻辑控制都放在MainActivity当中,对后期代码的保护10分不利。

使用FragmentPagerAdapter的好处之1就是能够使得当前页面的逻辑处理唯一当前Fragment来承当,相当于把MainActivity里面的事件逻辑分派给了Fragment来处理。这个优点,其实在使用Fragment的时候也能体现出来。

所以说,如果仅仅是页面的展现(如图片轮播),直接使用ViewPager就行了,但如果ViewPager的每一个页面中包括比较复杂的逻辑,就应当使用ViewPager+FragmentPagerAdapter的方式来完成Tab页面的切换。

具体代码

xml与ViewPager实现的相同,不再重复。

Java代码:

public class TestActivity3 extends FragmentActivity implements View.OnClickListener { private ViewPager viewPager; private FragmentPagerAdapter mAdapter; private List<Fragment> fragments; private LinearLayout mTabWeixin; private LinearLayout mTabFrd; private LinearLayout mTabAddress; private LinearLayout mTabSetting; private ImageButton mWeiXin; private ImageButton mFriend; private ImageButton mAddress; private ImageButton mSetting; private int select; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.test_ac_3); initView(); initEvent(); } private void initEvent() { mWeiXin.setOnClickListener(this); mFriend.setOnClickListener(this); mAddress.setOnClickListener(this); mSetting.setOnClickListener(this); } private void initView() { //初始化 viewPager= (ViewPager) findViewById(R.id.id_viewpager3); 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); mWeiXin= (ImageButton) findViewById(R.id.id_tab_weixin_img); mFriend= (ImageButton) findViewById(R.id.id_tab_frd_img); mAddress= (ImageButton) findViewById(R.id.id_tab_address_img); mSetting= (ImageButton) findViewById(R.id.id_tab_setting_img); fragments=new ArrayList<>(); WeiXinFragment weiXinFragment=new WeiXinFragment(); FriendFragment friendFragment=new FriendFragment(); AddressFragment addressFragment=new AddressFragment(); SettingFragment settingFragment=new SettingFragment(); fragments.add(weiXinFragment); fragments.add(friendFragment); fragments.add(addressFragment); fragments.add(settingFragment); mAdapter=new FragmentPagerAdapter(getSupportFragmentManager()) { @Override public Fragment getItem(int position) { return fragments.get(position); } @Override public int getCount() { return fragments.size(); } }; viewPager.setAdapter(mAdapter); viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { resetImage(); switch (position){ case 0: mWeiXin.setImageResource(R.drawable.tab_weixin_pressed); viewPager.setCurrentItem(0); break; case 1: mFriend.setImageResource(R.drawable.tab_find_frd_pressed); viewPager.setCurrentItem(1); break; case 2: mAddress.setImageResource(R.drawable.tab_address_pressed); viewPager.setCurrentItem(2); break; case 3: mSetting.setImageResource(R.drawable.tab_settings_pressed); viewPager.setCurrentItem(3); break; } } @Override public void onPageScrollStateChanged(int state) { } }); } @Override public void onClick(View view) { resetImage(); switch (view.getId()) { case R.id.id_tab_weixin_img: setSelect(0); break; case R.id.id_tab_frd_img: setSelect(1); break; case R.id.id_tab_address_img: setSelect(2); break; case R.id.id_tab_setting_img: setSelect(3); break; } } public void setSelect(int select) { switch (select){ case 0: mWeiXin.setImageResource(R.drawable.tab_weixin_pressed); viewPager.setCurrentItem(0); break; case 1: mFriend.setImageResource(R.drawable.tab_find_frd_pressed); viewPager.setCurrentItem(1); break; case 2: mAddress.setImageResource(R.drawable.tab_address_normal); viewPager.setCurrentItem(2); break; case 3: mSetting.setImageResource(R.drawable.tab_settings_pressed); viewPager.setCurrentItem(3); break; } } private void resetImage() { mSetting.setImageResource(R.drawable.tab_settings_normal); mWeiXin.setImageResource(R.drawable.tab_weixin_normal); mAddress.setImageResource(R.drawable.tab_address_normal); mFriend.setImageResource(R.drawable.tab_find_frd_normal); } }

使用框架

如果每次在开发的进程当中都去写1个这样的Tab页面,无疑耗时耗力,固然,对初学者而言,这类“耗时耗力”能够帮助他们了解效果实现的基本实现原理。

在这里推荐给大家1款比较不错的ViewPager框架:

LuckyJayce/ViewPagerIndicator

里面的介绍比较详细,这里就不多讲了,对这个框架感兴趣的小火伴可以去github上仔细研读1下~

最后附上下载的源码:github

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐