從TabLayout源碼告訴你使用它的正確姿勢

sunrui9521 8年前發布 | 19K 次閱讀 安卓開發 Android開發 移動開發

前言:以前總是覺得tablayout使用特別麻煩,所以一直選擇第三方庫,都不用它,仔細研究發現我們都錯過了它,看完這篇讓你愛上它,使用非常簡單

  • 布局文件

    <android.support.design.widget.TabLayout
          android:id="@+id/tabs"
      <!--Tab被選中字體的顏色-->
          app:tabSelectedTextColor="@android:color/holo_blue_bright"
      <!--Tab未被選中字體的顏色-->
          app:tabTextColor="@android:color/black"
      <!--Tab指示器下標的顏色-->
          app:tabIndicatorColor="@android:color/holo_blue_bright"
          android:layout_width="match_parent"
          android:layout_height="wrap_content" />
    • 常用的屬性有三個:
      app:tabSelectedTextColor:Tab被選中字體的顏色
      app:tabTextColor:Tab未被選中字體的顏色
      app:tabIndicatorColor:Tab指示器下標的顏色
    • TabLayout常用的方法如下:
      addTab(TabLayout.Tab tab, int position, boolean setSelected) 增加選項卡到 layout 中 
      addTab(TabLayout.Tab tab, boolean setSelected) 同上 
      addTab(TabLayout.Tab tab) 同上 
      getTabAt(int index) 得到選項卡 
      getTabCount() 得到選項卡的總個數 
      getTabGravity() 得到 tab 的 Gravity 
      getTabMode() 得到 tab 的模式 
      getTabTextColors() 得到 tab 中文本的顏色 
      newTab() 新建個 tab 
      removeAllTabs() 移除所有的 tab 
      removeTab(TabLayout.Tab tab) 移除指定的 tab 
      removeTabAt(int position) 移除指定位置的 tab 
      setOnTabSelectedListener(TabLayout.OnTabSelectedListener onTabSelectedListener) 為每個 tab 增加選擇監聽器 
      setScrollPosition(int position, float positionOffset, boolean updateSelectedText) 設置滾動位置 
      setTabGravity(int gravity) 設置 Gravity 
      setTabMode(int mode) 設置 Mode,有兩種值:TabLayout.MODE_SCROLLABLE和TabLayout.MODE_FIXED分別表示當tab的內容超過屏幕寬度是否支持橫向水平滑動,第一種支持滑動,第二種不支持,默認不支持水平滑動。 
      setTabTextColors(ColorStateList textColor) 設置 tab 中文本的顏色 
      setTabTextColors(int normalColor, int selectedColor) 設置 tab 中文本的顏色 默認 選中 
      setTabsFromPagerAdapter(PagerAdapter adapter) 設置 PagerAdapter 
      setupWithViewPager(ViewPager viewPager) 和 ViewPager 聯動
  • 代碼中,使用只需要四步,非常簡單:
    1. 找到控件
      tabLayout = (TabLayout)findViewById(R.id.tabs);
    2. 設置模式(當然這步是可以放到布局文件中的)
      tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);//設置tab模式,MODE_FIXED是固定的,不能超出屏幕,MODE_SCROLLABLE可超出屏幕范圍滾動的
    3. 關聯viewpager
      tabLayout.setupWithViewPager(viewPager);//將TabLayout和ViewPager關聯起來。
    4. 為tab設置適配器
      tabLayout.setTabsFromPagerAdapter(fragmentAdapter);//給Tabs設置適配器
  • 到此就完了,可能很多人就要說我這個有問題呀,都沒設置tablayout中的tab,網上大多數的dome是這樣的:

    tabLayout = (TabLayout)findViewById(R.id.tabs);
          //設置tab模式,MODE_FIXED是固定的,MODE_SCROLLABLE可超出屏幕范圍滾動的
          tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
          //網上很多dome都是在這里把tab添加到tablayout中的,但實際上這是多余的
          tabLayout.addTab(tabLayout.newTab().setText(tabList.get(0)));//添加tab選項卡
          tabLayout.addTab(tabLayout.newTab().setText(tabList.get(1)));
          tabLayout.addTab(tabLayout.newTab().setText(tabList.get(2)));
          tabLayout.addTab(tabLayout.newTab().setText(tabList.get(3)));
          tabLayout.addTab(tabLayout.newTab().setText(tabList.get(4)));
          tabLayout.addTab(tabLayout.newTab().setText(tabList.get(5)));
    
          List<Fragment> fragmentList = new ArrayList<>();
          for (int i = 0; i < tabList.size(); i++) {
              Fragment f1 = new TabFragment();
              Bundle bundle = new Bundle();
              bundle.putString("content", "http://www.jianshu.com/users/2229fd214880/latest_articles");
              f1.setArguments(bundle);
              fragmentList.add(f1);
          }
    
          TabFragmentAdapter fragmentAdapter = new TabFragmentAdapter(getSupportFragmentManager(), fragmentList, tabList);
          viewPager.setAdapter(fragmentAdapter);//給ViewPager設置適配器
          tabLayout.setupWithViewPager(viewPager);//將TabLayout和ViewPager關聯起來。
          tabLayout.setTabsFromPagerAdapter(fragmentAdapter);//給Tabs設置適配器

    但實際上是多余的,其實只要為tab設置了適配器就已經完成了這一步了,下面就來看看源碼吧

    //這里我只提出來了一些重要的代碼塊
    /** 
        *為tab設置適配器          
       */
      @Deprecated
      public void setTabsFromPagerAdapter(@Nullable final PagerAdapter adapter) {
          setPagerAdapter(adapter, false);
      }
    
    void setPagerAdapter(@Nullable final PagerAdapter adapter, final boolean addObserver) {
          .
          .
          .
    
          // Finally make sure we reflect the new adapter
          populateFromPagerAdapter();
      }
    
    void populateFromPagerAdapter() {
          removeAllTabs();//清除所有的tab,所以你如果在設置適配器之前addTab就是多余的了
      //這里在一次從adapter中getPageTitle添加到tab
          if (mPagerAdapter != null) {
              final int adapterCount = mPagerAdapter.getCount();
              for (int i = 0; i < adapterCount; i++) {
                  addTab(newTab().setText(mPagerAdapter.getPageTitle(i)), false);
              }
    
              // Make sure we reflect the currently set ViewPager item
              if (mViewPager != null && adapterCount > 0) {
                  final int curItem = mViewPager.getCurrentItem();
                  if (curItem != getSelectedTabPosition() && curItem < getTabCount()) {
                      selectTab(getTabAt(curItem));
                  }
              }
          }
      }
  • 不過可能有認是跟我的步驟一步步敲下來的但是卻發現,麻痹,出現的效果是這樣的

錯誤示范

那是因為少了一步重要的步驟,重寫TabFragmentAdapter中的getPageTitle方法

說到這里很多人可能會說,你如果之前在代碼中使用addTab方法把tab添加進去就不會出現這個問題了吧,殘忍的告訴你還是這樣的,原因,我已經在解析源碼的時候告訴大家了,就是因為你再一次調用為tablayout設置適配器的時候,tablayout做了一次清空tab的處理

可能有人又會想那我先給tablayout設置適配器,再去調用addTab方法啥,顯示是殘酷的,還是不行,效果和上面一樣

  • 所一還是重寫TabFragmentAdapter中的getPageTitle方法吧
    @Override
      public CharSequence getPageTitle(int position) {
          return mTitles.get(position);
      }
  • 效果圖

 

tablayout

接下來貼一下代碼

  • TabFragment

    public class TabFragment extends Fragment {
      private String content;
      private View view;
      @Override
      public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
          view = inflater.inflate(R.layout.item, container,false);
          return view;
      }
    
      @Override
      public void onActivityCreated(@Nullable Bundle savedInstanceState) {
          super.onActivityCreated(savedInstanceState);
          content = getArguments().getString("content");
          TextView tvContent = (TextView) view.findViewById(R.id.tv_tab_content);
          tvContent.setText(content + "");
      }
    }
  • TabFragmentAdapter

    public class TabFragmentAdapter extends FragmentStatePagerAdapter {
    
      private List<Fragment> mFragments;
      private List<String> mTitles;
    
      public TabFragmentAdapter(FragmentManager fm, List<Fragment> fragments, List<String> titles) {
          super(fm);
          mFragments = fragments;
          mTitles = titles;
      }
    
      @Override
      public Fragment getItem(int position) {
          return mFragments.get(position);
      }
    
      @Override
      public int getCount() {
          return mFragments.size();
      }
    
      @Override
      public CharSequence getPageTitle(int position) {
          return mTitles.get(position);
      }
    }
  • activity
    List<String> tabList = new ArrayList<>();
          tabList.add("Tab1");
          tabList.add("Tab2");
          tabList.add("Tab3");
          tabList.add("Tab5");
          tabList.add("Tab6");
          tabList.add("Tab7");
          tabLayout = (TabLayout)findViewById(R.id.tabs);
          //設置tab模式,MODE_FIXED是固定的,MODE_SCROLLABLE可超出屏幕范圍滾動的
          tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
          List<Fragment> fragmentList = new ArrayList<>();
          for (int i = 0; i < tabList.size(); i++) {
              Fragment f1 = new TabFragment();
              Bundle bundle = new Bundle();
              bundle.putString("content", "http://www.jianshu.com/users/2229fd214880/latest_articles");
              f1.setArguments(bundle);
              fragmentList.add(f1);
          }
          TabFragmentAdapter fragmentAdapter = new TabFragmentAdapter(getSupportFragmentManager(), fragmentList, tabList);
          viewPager.setAdapter(fragmentAdapter);//給ViewPager設置適配器
          tabLayout.setupWithViewPager(viewPager);//將TabLayout和ViewPager關聯起來。
          tabLayout.setTabsFromPagerAdapter(fragmentAdapter);//給Tabs設置適配器

 

來自:http://www.jianshu.com/p/8090ca4564c2

 

 本文由用戶 sunrui9521 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!