開(kāi)源項(xiàng)目: FlycoTabLayout

開(kāi)源項(xiàng)目效果

調(diào)用實(shí)例

必練基本功

Android studio 項(xiàng)目導(dǎo)入依賴compile路徑

dependencies{? ? compile'com.android.support:support-v4:23.1.1'compile'com.flyco.tablayout:FlycoTabLayout_Lib:2.0.2@aar'}

1

2

3

4

FlycoTabLayout是一個(gè)Android TabLayout庫(kù),目前有3個(gè)TabLayout

SlidingTabLayout:參照PagerSlidingTabStrip進(jìn)行大量修改.關(guān)于PagerSlidingTabStrip源碼分析可以參照我以前的一篇博文http://blog.csdn.net/analyzesystem/article/details/50316745?

新增部分屬性

新增支持多種Indicator顯示器

新增支持未讀消息顯示

新增方法setViewPager

/** 關(guān)聯(lián)ViewPager,用于不想在ViewPager適配器中設(shè)置titles數(shù)據(jù)的情況 */public void setViewPager(ViewPager vp, String[] titles)/** 關(guān)聯(lián)ViewPager,用于連適配器都不想自己實(shí)例化的情況 */public void setViewPager(ViewPager vp, String[] titles, FragmentActivity fa, ArrayList fragments)

1

2

3

4

5

CommonTabLayout:不同于SlidingTabLayout對(duì)ViewPager依賴,它是一個(gè)不依賴ViewPager可以與其他控件自由搭配使用的TabLayout.

支持多種Indicator顯示器,以及Indicator動(dòng)畫(huà)

支持未讀消息顯示

支持Icon以及Icon位置

新增方法

/** 關(guān)聯(lián)數(shù)據(jù)支持同時(shí)切換fragments */publicvoidsetTabData(ArrayList tabEntitys, FragmentManager fm,intcontainerViewId, ArrayList fragments)

1

2

SegmentTabLayout:仿照QQ消息列表頭部tab切換的控件

自定義屬性表

tl_indicator_colorcolor設(shè)置顯示器顏色tl_indicator_height? ? ? ? dimension? 設(shè)置顯示器高度tl_indicator_width? ? ? ? ? dimension? 設(shè)置顯示器固定寬度tl_indicator_margin_left? ? dimension? 設(shè)置顯示器margin,當(dāng)indicator_width大于0,無(wú)效tl_indicator_margin_top? ? dimension? 設(shè)置顯示器margin,當(dāng)indicator_width大于0,無(wú)效tl_indicator_margin_right? dimension? 設(shè)置顯示器margin,當(dāng)indicator_width大于0,無(wú)效tl_indicator_margin_bottom? dimension? 設(shè)置顯示器margin,當(dāng)indicator_width大于0,無(wú)效tl_indicator_corner_radius? dimension? 設(shè)置顯示器圓角弧度tl_indicator_gravity? ? ? ? enum? ? ? ? 設(shè)置顯示器上方(TOP)還是下方(BOTTOM),只對(duì)常規(guī)顯示器有用tl_indicator_style? ? ? ? ? enum? ? ? ? 設(shè)置顯示器為常規(guī)(NORMAL)或三角形(TRIANGLE)或背景色塊(BLOCK)tl_underline_colorcolor設(shè)置下劃線顏色tl_underline_height? ? ? ? dimension? 設(shè)置下劃線高度tl_underline_gravity? ? ? ? enum? ? ? ? 設(shè)置下劃線上方(TOP)還是下方(BOTTOM)tl_divider_colorcolor設(shè)置分割線顏色tl_divider_width? ? ? ? ? ? dimension? 設(shè)置分割線寬度tl_divider_padding? ? ? ? ? dimension? 設(shè)置分割線的paddingTop和paddingBottomtl_tab_padding? ? ? ? ? ? ? dimension? 設(shè)置tab的paddingLeft和paddingRighttl_tab_space_equal? ? ? ? ? boolean? ? 設(shè)置tab大小等分tl_tab_width? ? ? ? ? ? ? ? dimension? 設(shè)置tab固定大小tl_textsize? ? ? ? ? ? ? ? dimension? 設(shè)置字體大小tl_textSelectColorcolor設(shè)置字體選中顏色tl_textUnselectColorcolor設(shè)置字體未選中顏色tl_textBold? ? ? ? ? ? ? ? boolean? ? 設(shè)置字體加粗tl_iconWidth? ? ? ? ? ? ? ? dimension? 設(shè)置icon寬度(僅支持CommonTabLayout)tl_iconHeight? ? ? ? ? ? ? dimension? 設(shè)置icon高度(僅支持CommonTabLayout)tl_iconVisible? ? ? ? ? ? ? boolean? ? 設(shè)置icon是否可見(jiàn)(僅支持CommonTabLayout)tl_iconGravity? ? ? ? ? ? ? enum? ? ? ? 設(shè)置icon顯示位置,對(duì)應(yīng)Gravity中常量值,左上右下(僅支持CommonTabLayout)tl_iconMargin? ? ? ? ? ? ? dimension? 設(shè)置icon與文字間距(僅支持CommonTabLayout)tl_indicator_anim_enable? ? boolean? ? 設(shè)置顯示器支持動(dòng)畫(huà)(only for CommonTabLayout)tl_indicator_anim_duration? integer? ? 設(shè)置顯示器動(dòng)畫(huà)時(shí)間(only for CommonTabLayout)tl_indicator_bounce_enable? boolean? ? 設(shè)置顯示器支持動(dòng)畫(huà)回彈效果(only for CommonTabLayout)tl_indicator_width_equal_title? boolean 設(shè)置顯示器與標(biāo)題一樣長(zhǎng)(only for SlidingTabLayout)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

該庫(kù)依賴于動(dòng)畫(huà)兼容庫(kù)NineOldAndroidsFlycoRoundView硕勿,稍后在源碼分析里簡(jiǎn)單了解一下FlycoRoundView。

SlidingTabLayout調(diào)用

SlidingTabLayout自定義屬性支持下劃線設(shè)置僧须,控制下劃線顯示方向?qū)捀撸梢宰尵€寬=文字寬度传惠,也可以固定比例寬度,可以設(shè)置未讀消息的小紅點(diǎn)诗宣,也可以設(shè)置未讀消息數(shù)量掷豺,當(dāng)前這一切的前提都是基于ViewPager來(lái)實(shí)現(xiàn),都需要綁定ViewPager赎瑰,通過(guò)多種綁定方法

/**關(guān)聯(lián)ViewPager,Adapter重寫(xiě)了getPageTitle方法*/tabLayout.setViewPager(vp);/**關(guān)聯(lián)ViewPager,用于不想在ViewPager適配器中設(shè)置titles數(shù)據(jù)的情況*/tabLayout.setViewPager(vp, mTitles);/**關(guān)聯(lián)ViewPager,用于連適配器都不想自己實(shí)例化的情況王悍,內(nèi)部幫助實(shí)例化了一個(gè)InnerPagerAdapter*/tabLayout.setViewPager(vp, mTitles,this, mFragments);

1

2

3

4

5

6

7

8

下面我們來(lái)看看tabLayout提供幾個(gè)對(duì)我們比較有用的方法

/**顯示指定位置未讀紅點(diǎn)*/tabLayout.showDot(4);/**隱藏指定位置未讀紅點(diǎn)或消息*/tabLayout.hideMsg(5);/**showMsg(int position, int num):position位置,num小于等于0顯示紅點(diǎn),num大于0顯示數(shù)字餐曼,作用:顯示未讀消息压储,如果消息數(shù)量>99,顯示效果99+*/tabLayout.showMsg(3,5);/**? setMsgMargin(int position, float leftPadding, float bottomPadding)設(shè)置未讀消息偏移,原點(diǎn)為文字的右上角.當(dāng)控件高度固定,消息提示位置易控制,顯示效果佳 */tabLayout.setMsgMargin(3,0,10);/**設(shè)置未讀消息消息的背景*/MsgView msgView = tabLayout.getMsgView(3);if(msgView !=null) {? ? msgView.setBackgroundColor(Color.parseColor("#6D8FB0"));? }//...................略...........

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

自定義的屬性那么多,對(duì)應(yīng)的set方法自然也不少源譬,不過(guò)對(duì)照上面自定義屬性xml引用就好集惋,一般情況下哪些方法都用不到了。

CommonTabLayout調(diào)用

SlidingTabLayout對(duì)應(yīng)的方法在這里都適用不再重復(fù)踩娘,CommonTabLayout最重要的就是setTabData(ArrayList tabEntitys)方法刮刑,使得CommonTabLayout不再依賴于ViewPager完成初始化,實(shí)現(xiàn)底部導(dǎo)航或者頭部導(dǎo)航效果养渴,讓我們告別RadioButton+ViewPager的時(shí)代雷绢,CustomTabEntity的命名有點(diǎn)問(wèn)題哈,命名是一個(gè)接口非要定義Entity結(jié)尾理卑,TabEntity實(shí)現(xiàn)該接口翘紊,修改構(gòu)造方法,初始化內(nèi)部參數(shù)藐唠,下面是一個(gè)配合CommonTabLayout+ViewPager的導(dǎo)航實(shí)例

mFragmentList = addFragmentList(R.id.home_frameLayout, fragmentClasses);for(inti =0; i < titles.length; i++) {? ? ? ? ? ? mTabEntities.add(newTabEntity(titles[i], checkeds[i], normals[i]));? ? ? ? }? ? ? ? commonTabLayout.setTabData(mTabEntities);? ? ? ? commonTabLayout.setOnTabSelectListener(newOnTabSelectListener() {@OverridepublicvoidonTabSelect(intposition) {if(position ==1) {? ? ? ? ? ? ? ? ? ? topBarBuilder.configSearchStyle(titles[position], R.drawable.ic_action_search);? ? ? ? ? ? ? ? }else{? ? ? ? ? ? ? ? ? ? topBarBuilder.configTitle(titles[position]);? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? showFragment(R.id.home_frameLayout, position, mFragmentList);? ? ? ? ? ? ? ? onLoggerD("initial callback ,show fragment with position "+ position +";FragmentName:"+ mFragmentList.get(position).toString());? ? ? ? ? ? }@OverridepublicvoidonTabReselect(intposition) {//TODO 重選}? ? ? ? });

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

SegmentTabLayout調(diào)用

SegmentTabLayout實(shí)現(xiàn)效果就像qq消息列表頂部的切換效果霞溪,統(tǒng)一支持setTabData(mTitles)不過(guò)這里傳入標(biāo)題數(shù)組孵滞,tabLayout配合ViewPager切換調(diào)用tabLayout提供的方法setCurrentTab,SegmentTabLayout提供的 setTabData(String[] titles, FragmentActivity fa, int containerViewId, ArrayList fragments)方法在我們frameLayout+fragment布局切換Fragment比較實(shí)用的

源碼分析

FlycoRoundView源碼分析

粗略看過(guò)這個(gè)庫(kù)的自定義屬性文件鸯匹,明悟了件事:自定義屬性的自動(dòng)提示如下(以前我自定義屬性都放在declare-styleable直接定義的)

下面是這些自定義屬性的具體含義(attrs里面有具體說(shuō)明)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

Round系列的View控件自定義 RoundTextView 、RoundFrameLayout 泄伪、RoundLinearLayout RoundRelativeLayout殴蓬,這幾個(gè)控件內(nèi)部源碼實(shí)現(xiàn)并不復(fù)雜,可以說(shuō)簡(jiǎn)單之極蟋滴,構(gòu)造函數(shù)通過(guò)RoundViewDelegate代理解析自定義屬性染厅,其次就是onMeasure和onLayout的測(cè)量相關(guān)的,ToggleButton源碼分析一篇有提到這里使用EXACTLY

@OverrideprotectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);if(delegate.isWidthHeightEqual() && getWidth() >0&& getHeight() >0) {intmax = Math.max(getWidth(), getHeight());intmeasureSpec = MeasureSpec.makeMeasureSpec(max, MeasureSpec.EXACTLY);super.onMeasure(measureSpec, measureSpec);return;? ? ? ? }super.onMeasure(widthMeasureSpec, heightMeasureSpec);? ? }@OverrideprotectedvoidonLayout(booleanchanged,intleft,inttop,intright,intbottom) {super.onLayout(changed, left, top, right, bottom);if(delegate.isRadiusHalfHeight()) {//如果弧度是高度的一半津函,直接設(shè)置radio為高度一半肖粮,否則調(diào)用delegate.setCornerRadius(getHeight() /2);? ? ? ? }else{? ? ? ? ? ? delegate.setBgSelector();// Ripple效果兼容21+,Ripple效果的實(shí)現(xiàn)有多重尔苦,這里使用的RippleDrawable涩馆,具體使用方法請(qǐng)參考api,這里不是本篇重點(diǎn)}? ? }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

setBgSelector 方法使用到了GradientDrawable允坚、StateListDrawable魂那,沒(méi)了解過(guò)的可以參考Drawable系列這篇博客有相應(yīng)的簡(jiǎn)單介紹,RoundViewDelegate提供了這些自定義屬性的set get方法稠项,我們代碼調(diào)用通過(guò)自定義控件getDelegate獲取構(gòu)造函數(shù)初始化的實(shí)例進(jìn)行設(shè)置和獲取對(duì)應(yīng)屬性涯雅。

FlycoTabLayout Lib庫(kù)源碼分析

MsgView仿照FlycoRoundView庫(kù)編寫(xiě)的一個(gè)自定義控件,主要用于未讀消息的展示展运,大同小異的代碼就此略過(guò)活逆。

SlidingTabLayout自定義控件千篇一律的自定義屬性飄過(guò),來(lái)到必經(jīng)之路setViewPager拗胜,發(fā)現(xiàn)新大陸notifyDataSetChanged()調(diào)用蔗候,通過(guò)dapter的getPageTitle方法獲取標(biāo)題,并inflate添加一個(gè)布局到HorizontalScrollView的子View LinearLayout,并綁定Tab想的監(jiān)聽(tīng)回調(diào)挤土。

/** 更新數(shù)據(jù) */publicvoidnotifyDataSetChanged() {? ? ? ? mTabsContainer.removeAllViews();this.mTabCount = mTitles ==null? mViewPager.getAdapter().getCount() : mTitles.length;? ? ? ? View tabView;for(inti =0; i < mTabCount; i++) {if(mViewPager.getAdapter()instanceofCustomTabProvider) {? ? ? ? ? ? ? ? tabView = ((CustomTabProvider) mViewPager.getAdapter()).getCustomTabView(this, i);? ? ? ? ? ? }else{? ? ? ? ? ? ? ? tabView = View.inflate(mContext, R.layout.layout_tab,null);? ? ? ? ? ? }? ? ? ? ? ? CharSequence pageTitle = mTitles ==null? mViewPager.getAdapter().getPageTitle(i) : mTitles[i];? ? ? ? ? ? addTab(i, pageTitle.toString(), tabView);? ? ? ? }? ? ? ? updateTabStyles();? ? }/** 創(chuàng)建并添加tab */privatevoidaddTab(finalintposition, String title, View tabView) {? ? ? ? TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title);if(tv_tab_title !=null) {if(title !=null) tv_tab_title.setText(title);? ? ? ? }? ? ? ? tabView.setOnClickListener(newOnClickListener() {@OverridepublicvoidonClick(View v) {if(mViewPager.getCurrentItem() != position) {? ? ? ? ? ? ? ? ? ? mViewPager.setCurrentItem(position);if(mListener !=null) {? ? ? ? ? ? ? ? ? ? ? ? mListener.onTabSelect(position);? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }else{if(mListener !=null) {? ? ? ? ? ? ? ? ? ? ? ? mListener.onTabReselect(position);? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? });/** 每一個(gè)Tab的布局參數(shù) */LinearLayout.LayoutParams lp_tab = mTabSpaceEqual ?newLinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT,1.0f) :newLinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);if(mTabWidth >0) {? ? ? ? ? ? lp_tab =newLinearLayout.LayoutParams((int) mTabWidth, LayoutParams.MATCH_PARENT);? ? ? ? }? ? ? ? mTabsContainer.addView(tabView, position, lp_tab);? ? }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

calcIndicatorRect方法根據(jù)不同的屬性計(jì)算出Rect范圍以便以繪制琴庵,具體繪制方法參考Canvas API,這里提一點(diǎn)下面這個(gè)方法非常有必要仰美,如果在自定義控件的構(gòu)造函數(shù)或者其他繪制相關(guān)地方使用系統(tǒng)依賴的代碼迷殿,會(huì)導(dǎo)致可視化編輯器無(wú)法報(bào)錯(cuò)并提示:Use View.isInEditMode() in your custom views to skip code when shown in Eclipseis,加上了isInEditMode的判斷就不會(huì)再報(bào)錯(cuò)了咖杂。

if(isInEditMode() || mTabCount <=0) {return;? ? ? ? }

1

2

3

對(duì)于代碼設(shè)置自定義的屬性值庆寺,會(huì)調(diào)用下面這兩個(gè)方法 invalidate()和 updateTabStyles();涉及到了繪制的則調(diào)用invalidate,可以直接修改的則調(diào)用updateTabStyles(個(gè)人感覺(jué)不太友好,比如代碼設(shè)置一個(gè)屬性值诉字,就需要遍歷所有view,同時(shí)重新調(diào)用屬性賦值懦尝,關(guān)鍵只修改了其中一個(gè)屬性V住!)

private void updateTabStyles() {? ? ? ? for (int i =0; i < mTabCount; i++) {View v = mTabsContainer.getChildAt(i);//? ? ? ? ? ? v.setPadding((int) mTabPadding, v.getPaddingTop(), (int) mTabPadding, v.getPaddingBottom());TextView tv_tab_title = (TextView) v.findViewById(R.id.tv_tab_title);if (tv_tab_title != null) {? ? ? ? ? ? ? ? tv_tab_title.setTextColor(i == mCurrentTab ? mTextSelectColor : mTextUnselectColor);tv_tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextsize);tv_tab_title.setPadding((int) mTabPadding,0, (int) mTabPadding,0);if (mTextAllCaps) {? ? ? ? ? ? ? ? ? ? tv_tab_title.setText(tv_tab_title.getText().toString().toUpperCase());}? ? ? ? ? ? ? ? if (mTextBold) {? ? ? ? ? ? ? ? ? ? tv_tab_title.getPaint().setFakeBoldText(mTextBold);}? ? ? ? ? ? }? ? ? ? }? ? }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

setMsg 陵霉、setDot方法在調(diào)用示例有提到用法琅轧,這里的show hide狀態(tài)如何保存的呢?這里有用到和AbsListView內(nèi)部狀態(tài)保持一樣的方法:SparseArray來(lái)保存對(duì)應(yīng)位置的狀態(tài)

/**? ? * 顯示未讀消息? ? *? ? * @paramposition 顯示tab位置? ? * @paramnum? ? ? num小于等于0顯示紅點(diǎn),num大于0顯示數(shù)字? ? */publicvoidshowMsg(intposition,intnum) {if(position >= mTabCount) {? ? ? ? ? ? position = mTabCount -1;? ? ? ? }? ? ? ? View tabView = mTabsContainer.getChildAt(position);? ? ? ? MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip);if(tipView !=null) {? ? ? ? ? ? UnreadMsgUtils.show(tipView, num);if(mInitSetMap.get(position) !=null&& mInitSetMap.get(position)) {return;? ? ? ? ? ? }? ? ? ? ? ? setMsgMargin(position,4,2);? ? ? ? ? ? mInitSetMap.put(position,true);? ? ? ? }? ? }/**? ? * 顯示未讀紅點(diǎn)? ? *? ? * @paramposition 顯示tab位置? ? */publicvoidshowDot(intposition) {if(position >= mTabCount) {? ? ? ? ? ? position = mTabCount -1;? ? ? ? }? ? ? ? showMsg(position,0);? ? }/** 隱藏未讀消息 */publicvoidhideMsg(intposition) {if(position >= mTabCount) {? ? ? ? ? ? position = mTabCount -1;? ? ? ? }? ? ? ? View tabView = mTabsContainer.getChildAt(position);? ? ? ? MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip);if(tipView !=null) {? ? ? ? ? ? tipView.setVisibility(View.GONE);? ? ? ? }? ? }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

細(xì)心的你一定會(huì)發(fā)現(xiàn)show并沒(méi)有直接控制View的Visibility顯示隱藏踊挠,而是用了UnreadMsgUtils乍桂,這個(gè)類提供了兩個(gè)方法setSize和show方法,show方法對(duì)show的countSize進(jìn)行了一次判斷轉(zhuǎn)換0為點(diǎn)效床,1-99圓+數(shù)字睹酌,>99則顯示99+,背景的弧度為寬度的一半

再回到setViewPager(ViewPager vp, String[] titles, FragmentActivity fa, ArrayList fragments)方法剩檀,在我們調(diào)用該方法時(shí)內(nèi)部幫我們創(chuàng)建了內(nèi)部定義的InnerPagerAdapter適配器憋沿,如果你想偷懶不想寫(xiě)適配器就可以調(diào)用這個(gè)方法。InnerPagerAdapter重寫(xiě)了getPageTitle,以便于notifyDataSetChanged方法調(diào)用動(dòng)態(tài)添加tab項(xiàng)沪猴。

class InnerPagerAdapter extends FragmentPagerAdapter {privateArrayList fragments =newArrayList<>();privateString[] titles;publicInnerPagerAdapter(FragmentManager fm, ArrayList fragments, String[] titles) {super(fm);this.fragments = fragments;this.titles = titles;? ? ? ? }@OverridepublicintgetCount() {returnfragments.size();? ? ? ? }@OverridepublicCharSequencegetPageTitle(intposition) {returntitles[position];? ? ? ? }@OverridepublicFragmentgetItem(intposition) {returnfragments.get(position);? ? ? ? }@OverridepublicvoiddestroyItem(ViewGroup container,intposition, Object object) {// 覆寫(xiě)destroyItem并且空實(shí)現(xiàn),這樣每個(gè)Fragment中的視圖就不會(huì)被銷毀// super.destroyItem(container, position, object);}@OverridepublicintgetItemPosition(Object object) {returnPagerAdapter.POSITION_NONE;? ? ? ? }? ? }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

CommonTabLayout與上面SlidingTabLayout百分之99的相似度辐啄,重復(fù)的不在敘述,區(qū)別點(diǎn)在于setTabData和notifyDataSetChanged方法字币,notifyDataSetChanged根據(jù)Icon的Gravity屬性進(jìn)入不同布局的View做Tab,雖然TextView有drawableLeftRightTopBottom的相關(guān)屬性则披,但是并不能讓我們那么自由的控制Ui。

/** 更新數(shù)據(jù) */publicvoidnotifyDataSetChanged() {? ? ? ? mTabsContainer.removeAllViews();this.mTabCount = mTabEntitys.size();? ? ? ? View tabView;for(inti =0; i < mTabCount; i++) {if(mIconGravity == Gravity.LEFT) {? ? ? ? ? ? ? ? tabView = View.inflate(mContext, R.layout.layout_tab_left,null);? ? ? ? ? ? }elseif(mIconGravity == Gravity.RIGHT) {? ? ? ? ? ? ? ? tabView = View.inflate(mContext, R.layout.layout_tab_right,null);? ? ? ? ? ? }elseif(mIconGravity == Gravity.BOTTOM) {? ? ? ? ? ? ? ? tabView = View.inflate(mContext, R.layout.layout_tab_bottom,null);? ? ? ? ? ? }else{? ? ? ? ? ? ? ? tabView = View.inflate(mContext, R.layout.layout_tab_top,null);? ? ? ? ? ? }? ? ? ? ? ? tabView.setTag(i);? ? ? ? ? ? addTab(i, tabView);? ? ? ? }? ? ? ? updateTabStyles();? ? }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

setTabData(ArrayList tabEntitys, FragmentActivity fa, int containerViewId, ArrayList fragments)方法內(nèi)部初始化了一個(gè)Fragment的管理輔助類FragmentChangeManager洗出,該類在構(gòu)造函數(shù)動(dòng)態(tài)添加隱藏了fragment士复,對(duì)外提供setFragments(int index)顯示指定位置的Fragment,這個(gè)在frameLayout+Fragment+commonTabLayout布局里面免去了我們管理fagment的煩惱

SegmentTabLayout相比較于CommonTabLayout多了動(dòng)畫(huà)這塊的處理,點(diǎn)擊了某一項(xiàng)Tab翩活,調(diào)用setCurrentTab,間接調(diào)用calcOffset開(kāi)啟了動(dòng)畫(huà)阱洪,動(dòng)畫(huà)的執(zhí)行過(guò)程中onAnimationUpdate重新重繪,調(diào)整位置。

tabView.setOnClickListener(newOnClickListener() {@OverridepublicvoidonClick(View v) {intposition = (Integer) v.getTag();if(mCurrentTab != position) {? ? ? ? ? ? ? ? ? ? setCurrentTab(position);if(mListener !=null) {? ? ? ? ? ? ? ? ? ? ? ? mListener.onTabSelect(position);? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }else{if(mListener !=null) {? ? ? ? ? ? ? ? ? ? ? ? mListener.onTabReselect(position);? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? });//setter and getterpublicvoidsetCurrentTab(intcurrentTab) {? ? ? ? mLastTab =this.mCurrentTab;this.mCurrentTab = currentTab;? ? ? ? updateTabSelection(currentTab);if(mFragmentChangeManager !=null) {? ? ? ? ? ? mFragmentChangeManager.setFragments(currentTab);? ? ? ? }if(mIndicatorAnimEnable) {? ? ? ? ? ? calcOffset();? ? ? ? }else{? ? ? ? ? ? invalidate();? ? ? ? }? ? }@OverridepublicvoidonAnimationUpdate(ValueAnimator animation) {? ? ? ? IndicatorPoint p = (IndicatorPoint) animation.getAnimatedValue();? ? ? ? mIndicatorRect.left = (int) p.left;? ? ? ? mIndicatorRect.right = (int) p.right;? ? ? ? invalidate();? ? }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

小結(jié)

首先說(shuō)一點(diǎn)這里不提供demo菠镇,需要去官方https://github.com/H07000223/FlycoTabLayout?down ,其次呢這個(gè)庫(kù)看了之后還是有很大收獲的冗荸,比如自定義屬性的運(yùn)用, setViewPager(ViewPager vp, String[] titles, FragmentActivity fa, ArrayList fragments)內(nèi)部實(shí)例一個(gè)adapter適配器利耍,最重要的是自定義屬性解析和屬性值代碼設(shè)置通過(guò)一個(gè)類來(lái)代理完成蚌本。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市隘梨,隨后出現(xiàn)的幾起案子程癌,更是在濱河造成了極大的恐慌,老刑警劉巖轴猎,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嵌莉,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡捻脖,警方通過(guò)查閱死者的電腦和手機(jī)锐峭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門中鼠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人沿癞,你說(shuō)我怎么就攤上這事援雇。” “怎么了椎扬?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵熊杨,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我盗舰,道長(zhǎng),這世上最難降的妖魔是什么桂躏? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任钻趋,我火速辦了婚禮,結(jié)果婚禮上剂习,老公的妹妹穿的比我還像新娘蛮位。我一直安慰自己,他們只是感情好鳞绕,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布失仁。 她就那樣靜靜地躺著,像睡著了一般们何。 火紅的嫁衣襯著肌膚如雪萄焦。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,785評(píng)論 1 290
  • 那天冤竹,我揣著相機(jī)與錄音拂封,去河邊找鬼。 笑死鹦蠕,一個(gè)胖子當(dāng)著我的面吹牛冒签,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播钟病,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼萧恕,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了肠阱?” 一聲冷哼從身側(cè)響起票唆,我...
    開(kāi)封第一講書(shū)人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辖所,沒(méi)想到半個(gè)月后惰说,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡缘回,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年吆视,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了典挑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡啦吧,死狀恐怖您觉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情授滓,我是刑警寧澤琳水,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站般堆,受9級(jí)特大地震影響在孝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜淮摔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一私沮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧和橙,春花似錦仔燕、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至办斑,卻和暖如春外恕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背俄周。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工吁讨, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人峦朗。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓建丧,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親波势。 傳聞我的和親對(duì)象是個(gè)殘疾皇子翎朱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容