ToolBar、TabLayout、Fragment+ViewPager的開發實踐

此文優先發佈於我的個人博客:TB+TableLayout+Fragment+VP開發實踐

研究ToolBar、TabLayout、Fragment+ViewPager的開發實踐覆盤以及尚未解決的問題。歡迎評論留言。

XML

TabLayout

添加依賴

'android.support.design:28.0.0'

此處添加AppBarLayout作爲完整的佈局1:

AppBarLayout是Android Design Support Library新加的控件繼承自LinearLayout,
它用來將Toolbar和TabLayout組合起來作爲一個整體。
<android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
    
<android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:layout_scrollFlags="scroll|enterAlways" //滑動隱藏功能
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
<android.support.design.widget.TabLayout
          android:id="@+id/main_tablayout"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"         
          android:background="@color/color_title_bar"/>

<android.support.v4.view.ViewPager <!--TabLayout相關聯的ViewPager-->
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:layout_weight="1"
        android:background="@android:color/white" />

TabLayout可選屬性

tab
可更改屬性 屬性說明
tabBackground TabLayout的背景
tabSelectedTextColor 當前標籤的字體顏色
tabIndicator

可以寫一個style,下文中會提到

可更改屬性 屬性說明
tabIndicatorColor 選中線的顏色
tabIndicatorHeight 選中線的高度
tabMode
可更改屬性 屬性說明
FIXED 不可左右滑動,用於標籤較少時
SCROLLABLE 可左右滑動,用於標籤較多時

Fragment

爲什麼要創建Fragment:TabLayout中的ViewPager對應着相應的Fragment,所以需要創建。

有的示例僅創建了一個Fragment,其中爲定義文字數組實現,若開發中則需要多個Fragment添加,均用Arratlist於Activity中。

XXXFragment.java:

public class XXXFragment extends Fragment {
    
    private Page/View;  //創建變量
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //mPage = getArguments().getInt(ARG_PAGE);
    }
 
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_page, container, false);
        TextView textView = (TextView) view; //參考[^6]
        textView.setText("Fragment #" + mPage); 
        return view;
    }
 
}

一些暫未明確的代碼段

 public static final String TYPE = "TYPE"; //此處未知含義

參考2

//此處的含義可能是新增實例,存儲值?
    public static XXXFragment newInstance(int page) { 
        Bundle args = new Bundle();
        args.putInt(ARG_PAGE, page);
        PageFragment pageFragment = new PageFragment();
        pageFragment.setArguments(args);
        return pageFragment;
    }

Activity

如果需要定義TableLayout的tab文字,則在其中定義:public static final String[] titles,之後添加集合。

這裏把2定義文字放在了Adapter中,原因未知。

關於添加圖片,下文有提到。

    private Toolbar toolbar; //增加相關變量
    private TabLayout tabLayout;
    private ViewPager viewPager;

    public static final String[] titles = {"", ""};

    private List<Fragment> fragments; //定義fragment的集合縮寫
    private List<String> tabNames;
    private List<Integer> tabIcs;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_xxx);
        initView();        //各種初始化:界面、添加的fragment值、事件
        initValue();
        initEvent();
    }

    //各種初始化開始

    private void initView() { //初始化實例

        toolbar = (Toolbar) findViewById(R.id.Toolbar); 
        setSupportActionBar(toolbar); //支持actionbar,此處多種寫法
        getSupportActionBar().setDisplayHomeAsUpEnabled(true); //在首頁顯示

        viewPager = (ViewPager) findViewById(R.id.viewpager); //實例化控件
        tabLayout = (TabLayout) findViewById(R.id.tabs);
    }

    private void initValue() { 
    //初始化值,添加每一個TableLayout裏的ArrayList,設置與標題欄一一對應的視圖(片段)集合

        fragments = new ArrayList<>();
        fragments.add(new xxxFragment());
        fragments.add(new xxxFragment()); //有多少個fragment就在這裏添加多少

        tabNames = new ArrayList<>(); //添加標題集合,同上
        tabNames.add(" ");
        tabNames.add(" ");

        /*tabIcs = new ArrayList<>(); 此處尚不明確是否有,使用spanstring或其他方法此處是否需要
        tabIcs.add(R.drawable.tab_xxx);
        tabIcs.add(R.drawable.tab_xxx);*/
        
        //給tabLayout添加選項卡
        for(int i=0;i< fragments.size();i++){
            tabLayout.addTab(tabLayout.newTab().setText((CharSequence) fragments.get(i)));
        }

        FragmentViewPagerAdapter adapter = new FragmentViewPagerAdapter
        (getSupportFragmentManager(), fragments, tabNames,tabIcs); 
        // 初始化ViewPager適配器        //此處需要增加與添加的集合以及上述定義的值匹配,若未定義則無需添加

        viewPager.setAdapter(adapter); //給ViewPager設置適配器
        tabLayout.setupWithViewPager(viewPager);  //將TabLayout和ViewPager關聯起來      
        /*setupWithViewPager這個方法會先將tab清除然後再根據ViewPager的adapter裏的count去取pagetitle,這也就是有時遇到用addTab方法添加tab不起作用的問題。*/

        //setupTabIcons();
        viewPager.setCurrentItem(1);
        viewPager.setCurrentItem(0);
    }

此處的setupTabIcons()方法,在下文添加圖片會提到。[參考鏈接]()

默認顯示第一個Tab3

tab.addTab(tab,i == 0, ? true:false);

FragmentPagerAdapter

需要使用Fragment的話就需要這個適配器

public class一個自定義的適配器名稱繼承自FragmentPagerAdapter。

    List<Fragment> xxxfragment;
    List<String> titleList;

public MyTableViewAdapter(FragmentManager fm , List<Fragment> pagerList , List<String> titleList) {
        super(fm);
    this.pagerList = pagerList; // 此處使用this.與上述定義匹配
  
}
    
public Fragment getItem(int poition)
    super.

public int getCount(int poition) { return (tab個數) } 
   return xxxfragment.get(position); //普通情況
   return xxxfragment != null ? pagerList.size() : 0; //設置不等於null的情況,參考[^4]

public long getItemId(int poition)  { return super.getItemId(position) }
return xxxfragment.get(position);

此處可能還有,參考 3

public destoryItemId(View view contain,int poition,Object object)

點擊切換Tab的操作(兩種方式)

  1. .setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() 方法3

當tab頁面被選中時,會調用這個方法,當tab頁面被選中時,切換目前的fragment:

@Override
public void onTabSelected(TabLayout.Tab tab) {
int position = tab.getPosition();
    
Fragment fragment = (Fragment)adapter.instantiateItem(container, position);
    
adapter.setPrimaryItem(container, pos, fragment);
adapter.finishUpdate(container);
    
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
  1. 使用selector代替4

高級

在TabLayout中添加圖片

方法

getTabView()4

此方法爲我首先嚐試使用,可以更改圖標顏色以及狀態。

步驟:

  1. 在Activity.java中設置圖片點擊(使用selector)數組public int[]
  2. 設置setupTabIcons();
  3. 創建getTabView()方法

這裏52把此方法放到了FragmentAdapter中,個人猜測原因可能是一同將getTabView()或imagespan使用。

SpannableString

更多支持:介紹參考鏈接6

SpannableString這個類實現了CharSequence這個接口,所以可以在Adapter中的getPageTitle()中返回。

SpannableString的構造方法需要一個參數:CharSequence(超級字符串的基本顯示內容),

setSpan爲核心方法

方法值:

public void setSpan(Object what, int start, int end, int flags) {
    super.setSpan(what, start, end, flags);
          //what:向這個超級字符串中添加的內容。例如:前景色、背景色、圖片、鏈接、下劃線等
          //start:開始的位置(0爲開始)
          //結束的位置
          //flags:標識在span範圍內的文本前後輸入新的字符時是否也應用這個效果
}

SpanString舉例由於衆多,表格與文末7

經搜索:

其中使用ImageSpan的兩種方法,發現以下兩種均爲僅添加圖標方法,而不適用於點擊切換顏色:

使用SpanString和Imagespan:2
  1. 在SimpleFragmentPagerAdapter中設置數組int[]
  2. 樣式文件定義
保留字符串並設置空,添加圖片方法8
  1. 修改Adapter的構造方法:設置tabName和tabIcons變量:每個Tab上的文字和圖標的變量
  2. 修改getPageTitle()方法:if-else語句:如果不設置文字,則保留一個字符,如果設置圖標,則使用span
  3. 添加定義style(關鍵):textAllCaps、android:textAllCaps必須設置爲false,之後XML中TabLayout設置style。

SpanString舉例,示例代碼7,項目完整地址9.

可更改屬性 屬性說明
AbsoluteSizeSpan 單位爲物理像素
AlignmentSpan 支持ALIGN_NORMAL,ALIGN_OPPOSITE,ALIGN_CENTER
BackgroundColorSpan 文字背景色改變
BulletSpan 小圓圈
ClickableSpan 可點擊
DrawableMarginSpan Drawable,不佔位
DynamicDrawableSpan DynamicDrawable,佔位
ForegroundColorSpan 前景色
IconMarginSpan 圖標margin,不佔位
ImageSpan 圖片,佔位
LeadingMarginSpan 控制行前空隙
QuoteSpan 左側出現引用符號 豎線
RelativeSizeSpan 字體放大
ScaleXSpan 字體寬度放大
StrikethroughSpan 刪除線
StyleSpan 主要由正常、粗體、斜體和同時加粗傾斜四種樣式,常量值定義在Typeface類中
SubscriptSpan 下標
SuperscriptSpan 上標
TextAppearanceSpan Sets the text color, size, style, and typeface to match a TextAppearance
TypefaceSpan 字體設置
UnderlineSpan 下劃線
URLSpan URL


  1. Android Design Support Library(一)用TabLayout實現類似網易選項卡動態滑動效果
  2. android design library提供的TabLayout的用法,很多教程都參考了此文章。
  3. 利用TabLayout和fragment搭建app框架
  4. Android TabLayout setCustomView 實現帶圖標的tab
  5. 4
  6. android設計庫提供的TabLayout的簡單使用(TabLayout + ViewPager + Fragment)
  7. SpannableString
  8. TabLayout與ViewPager的聯合使用
  9. onlyloveyd/SpannableDemo
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章