亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android原生TabLayout使用的超全解析(看這篇就夠了)

 更新時(shí)間:2022年09月03日 08:51:42   作者:yechaoa  
現(xiàn)在很多app都有頂部可左右切換的導(dǎo)航欄,并且還帶動(dòng)畫效果,要實(shí)現(xiàn)這種導(dǎo)航欄,可以使用Android原生的Tablayout也可以借助第三方框架實(shí)現(xiàn),這篇文章主要給大家介紹了關(guān)于Android原生TabLayout使用的相關(guān)資料,需要的朋友可以參考下

前言

為什么會(huì)有這篇文章呢,是因?yàn)橹瓣P(guān)于TabLayout的使用陸陸續(xù)續(xù)也寫了好幾篇了,感覺比較分散,且不成體系,寫這篇文章的目的就是希望能把各種效果的實(shí)現(xiàn)一次性講齊,所以也有了標(biāo)題的「看這篇就夠了」。

TabLayout作為導(dǎo)航組件來說,使用場(chǎng)景非常的多,也意味著要滿足各種各樣的需求。

在效果實(shí)現(xiàn)上,有同學(xué)會(huì)選擇自定義View來做,定制性高,但易用性、穩(wěn)定性、維護(hù)性不敢保證,使用官方組件能避免這些不確定性,一是開源,有很多大佬共建,會(huì)不停的迭代;二是經(jīng)過大型app驗(yàn)證,比如google play;有了這兩點(diǎn),基本可以放心大膽的使用官方組件了。

那可能有的同學(xué)又會(huì)說,道理我都懂,可是不滿足需求啊,只能自定義了。是的,早期的api確實(shí)不夠豐富,在某些需求的實(shí)現(xiàn)上顯得捉襟見肘,但是google也在不斷的迭代,目前為止,常見的樣式都能滿足。

效果圖

簡(jiǎn)介

  • TabLayout:一個(gè)橫向可滑動(dòng)的菜單導(dǎo)航ui組件
  • Tab:TabLayout中的item,可以通過newTab()創(chuàng)建
  • TabView:Tab的實(shí)例,是一個(gè)包含ImageView和TextView的線性布局
  • TabItem:一種特殊的“視圖”,在TabLayout中可以顯式聲明Tab

官方文檔

功能拆解

Material Design 組件最新正式版依賴:

implementation 'com.google.android.material:material:1.5.0'

1.基礎(chǔ)實(shí)現(xiàn)

1.1 xml動(dòng)態(tài)寫法

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_layout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        app:tabIndicatorColor="@color/colorPrimary"
        app:tabMaxWidth="200dp"
        app:tabMinWidth="100dp"
        app:tabMode="fixed"
        app:tabSelectedTextColor="@color/colorPrimary"
        app:tabTextColor="@color/gray" />

只寫一個(gè)Layout,item可以配合ViewPager來生成。

1.2 xml靜態(tài)寫法

 <com.google.android.material.tabs.TabLayout
         android:layout_height="wrap_content"
         android:layout_width="match_parent">

     <com.google.android.material.tabs.TabItem
             android:text="@string/tab_text"/>

     <com.google.android.material.tabs.TabItem
             android:icon="@drawable/ic_android"/>

 </com.google.android.material.tabs.TabLayout>

屬于固定寫法,比如我們非常確定item有幾個(gè),可以通過TabItem顯式聲明。

1.3 kotlin/java代碼寫法

    val tab = mBinding.tabLayout7.newTab()
    tab.text = it.key
    //...
    mBinding.tabLayout7.addTab(tab)

這種情況適合Tab的數(shù)據(jù)是動(dòng)態(tài)的,比如接口數(shù)據(jù)回來之后,再創(chuàng)建Tab并添加到TabLayout中。

2.添加圖標(biāo)

mBinding.tabLayout2.getTabAt(index)?.setIcon(R.mipmap.ic_launcher)

獲取Tab然后設(shè)置icon。

Tab內(nèi)部其實(shí)是一個(gè)TextViewImageView,添加圖標(biāo)就是給ImageView設(shè)置icon。

3.字體大小、加粗

通過app:tabTextAppearance給TabLayout設(shè)置文本樣式

    <com.google.android.material.tabs.TabLayout
		...
        app:tabTextAppearance="@style/MyTabLayout"
		/>

style:

    <style name="MyTabLayout">
        <item name="android:textSize">20sp</item>
        <item name="android:textStyle">bold</item>
        <item name="android:textAllCaps">false</item>
    </style>

比如這里設(shè)置了字體大小和加粗。

默認(rèn)字體大小14sp

<dimen name="design_tab_text_size">14sp</dimen>

4.去掉Tab長(zhǎng)按提示文字

長(zhǎng)按Tab時(shí)會(huì)有一個(gè)提示文字,類似Toast一樣。

    /**
     * 隱藏長(zhǎng)按顯示文本
     */
    private fun hideToolTipText(tab: TabLayout.Tab) {
        // 取消長(zhǎng)按事件
        tab.view.isLongClickable = false
        // api 26 以上 設(shè)置空text
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
            tab.view.tooltipText = ""
        }
    }

可以取消長(zhǎng)按事件,在api26以上也可以設(shè)置提示文本為空。

5.去掉下劃線indicator

app:tabIndicatorHeight="0dp"

設(shè)置高度為0即可。

注意,單純?cè)O(shè)置tabIndicatorColor為透明,其實(shí)不準(zhǔn)確,默認(rèn)還是有2dp的,根本瞞不過射雞師的眼睛。

6.下劃線的樣式

通過app:tabIndicator可以設(shè)置自定義的樣式,比如通過shape設(shè)置圓角和寬度。

    <com.google.android.material.tabs.TabLayout
        ...
        app:tabIndicator="@drawable/shape_tab_indicator"
        app:tabIndicatorColor="@color/colorPrimary"
		/>

注意:Indicator的顏色在shape中設(shè)置是無效的,需要通過app:tabIndicatorColor設(shè)置才可以

shape:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:width="15dp"
        android:height="5dp"
        android:gravity="center">
        <shape>
            <corners android:radius="5dp" />
            <!--color無效,源碼用tabIndicatorColor-->
            <solid android:color="@color/colorPrimary" />
        </shape>
    </item>
</layer-list>

7.下劃線的寬度

默認(rèn)情況下,tabIndicator的寬度是填充整個(gè)Tab的,比如上圖中的第一個(gè),我們可以簡(jiǎn)單的設(shè)置不填充,與文本對(duì)齊,即第二個(gè)效果

app:tabIndicatorFullWidth="false"

也可以像上一節(jié)那樣,通過shape自定義tabIndicator的寬度。

8.Tab分割線

  /** A {@link LinearLayout} containing {@link Tab} instances for use with {@link TabLayout}. */
  public final class TabView extends LinearLayout {
  }

通過源碼可以看到內(nèi)部實(shí)現(xiàn)TabView繼承至LinearLayout,我們知道LinearLayout是可以給子view設(shè)置分割線的,那我們就可以通過遍歷來添加分割線

        //設(shè)置 分割線
        for (index in 0..mBinding.tabLayout4.tabCount) {
            val linearLayout = mBinding.tabLayout4.getChildAt(index) as? LinearLayout
            linearLayout?.let {
                it.showDividers = LinearLayout.SHOW_DIVIDER_MIDDLE
                it.dividerDrawable = ContextCompat.getDrawable(this, R.drawable.shape_tab_divider)
                it.dividerPadding = 30
            }
        }

shape_tab_divider:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/colorPrimary" />
    <size android:width="1dp" android:height="10dp" />
</shape>

9.TabLayout樣式

上圖中的效果其實(shí)是TabLayout樣式+tabIndicator樣式形成的一個(gè)「整體」的效果。

TabLayout是兩邊半圓的一個(gè)長(zhǎng)條,這個(gè)我們通過編寫shape設(shè)置給其背景即可實(shí)現(xiàn)。

shape_tab_bg:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="999dp" />
    <solid android:color="@color/colorPrimary" />
</shape>

這個(gè)效果的關(guān)鍵在于tabIndicator的高度與TabLayout的高度相同,所以二者高度設(shè)置一致即可。

shape_full_tab_indicator:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:gravity="center" android:top="0.5dp" android:bottom="0.5dp">
        <shape>
            <!-- 上下邊距合計(jì)1dp 高度減少1dp -->
            <size android:height="41dp" />
            <corners android:radius="999dp" />
            <solid android:color="@color/white" />
        </shape>
    </item>
</layer-list>

TabLayout:

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_layout6"
        android:layout_width="wrap_content"
        android:layout_height="42dp"
        android:layout_gravity="center"
        android:layout_marginTop="10dp"
        android:background="@drawable/shape_tab_bg"
        app:tabIndicator="@drawable/shape_full_tab_indicator"
        app:tabIndicatorColor="@color/white"
        app:tabIndicatorFullWidth="true"
        app:tabIndicatorHeight="42dp"
        app:tabMinWidth="96dp"
        app:tabMode="fixed"
        app:tabSelectedTextColor="@color/colorPrimary"
        app:tabTextColor="@color/black" />

10.Tab添加小紅點(diǎn)

添加小紅點(diǎn)的功能還是比較常見的,好在TabLayout也提供了這種能力,其實(shí)添加起來也非常簡(jiǎn)單,難在未知。

可以設(shè)置帶數(shù)字的紅點(diǎn),也可以設(shè)置沒有數(shù)字單純的一個(gè)點(diǎn)。

通過getOrCreateBadge可以對(duì)紅點(diǎn)進(jìn)行簡(jiǎn)單的配置:

        // 數(shù)字
        mBinding.tabLayout5.getTabAt(defaultIndex)?.let { tab ->
            tab.orCreateBadge.apply {
                backgroundColor = Color.RED
                maxCharacterCount = 3
                number = 99999
                badgeTextColor = Color.WHITE
            }
        }

        // 紅點(diǎn)
        mBinding.tabLayout5.getTabAt(1)?.let { tab ->
            tab.orCreateBadge.backgroundColor = ContextCompat.getColor(this, R.color.orange)
        }

getOrCreateBadge實(shí)際上是獲取或創(chuàng)建BadgeDrawable。

通過源碼發(fā)現(xiàn),BadgeDrawable除了TabLayout引用之外,還有NavigationBarItemView、NavigationBarMenuView、NavigationBarView,意味著它們也同樣具備著小紅點(diǎn)這種能力。其實(shí)別的view也是可以具備的。

關(guān)于小紅點(diǎn)這里就不展開了,非常推薦查看我之前寫的這篇:【漲姿勢(shì)】你沒用過的BadgeDrawable

11.獲取隱藏的Tab

上一節(jié)中我們實(shí)現(xiàn)了小紅點(diǎn)效果,那如果一屏顯示不夠的情況下,如何提示未展示的信息呢,比如上面我們?nèi)绾伟盐达@示的tab且有數(shù)字的Tab提示出來呢?常見的解決方案都是在尾部加一個(gè)紅點(diǎn)提示。

那么問題來了,如何判斷某一個(gè)Tab是否可見呢,翻看了源碼,可惜并沒有提供相應(yīng)的api,那只能我們自己實(shí)現(xiàn)了。

我們前面添加小紅點(diǎn)是根據(jù)Tab添加的,Tab內(nèi)部實(shí)現(xiàn)也是一個(gè)view,那view就可以判斷其是否可見。

    private fun isShowDot(): Boolean {
        var showIndex = 0
        var tipCount = 0
        companyMap.keys.forEachIndexed { index, _ ->
            mBinding.tabLayout7.getTabAt(index)?.let { tab ->
                val tabView = tab.view as LinearLayout
                val rect = Rect()
                val visible = tabView.getLocalVisibleRect(rect)
                // 可見范圍小于80%也在計(jì)算范圍之內(nèi),剩下20%寬度足夠紅點(diǎn)透出(可自定義)
                if (visible && rect.right > tab.view.width * 0.8) {
                    showIndex = index
                } else {
                    //if (index > showIndex) // 任意一個(gè)有count的tab隱藏就會(huì)顯示,比如第一個(gè)在滑動(dòng)過程中會(huì)隱藏,也在計(jì)算范圍之內(nèi)
                    if (index > lastShowIndex) { // 只檢測(cè)右側(cè)隱藏且有count的tab 才在計(jì)算范圍之內(nèi)
                        tab.badge?.let { tipCount += it.number }
                    }
                }

            }
        }
        lastShowIndex = showIndex
        return tipCount > 0
    }

上面的方法中就是判斷是否需要顯示右側(cè)提示的小紅點(diǎn)。

計(jì)算規(guī)則:Tab不可見,且Tab上的紅點(diǎn)數(shù)字大于0的即在計(jì)算范圍之內(nèi)。

這里有一個(gè)優(yōu)化的點(diǎn),比如上圖中的“騰訊”Tab,它是可見的,但是紅點(diǎn)不可見,那么問題就來了,如果我們沒有提示到,是很容易產(chǎn)生客訴的,所以這里在計(jì)算的時(shí)候也加了一個(gè)條件,就是可見范圍小于80%也在計(jì)算范圍之內(nèi),剩下20%的寬度是足夠Tab上的紅點(diǎn)透出的(也可自定義)。

同時(shí)在TabLayout滑動(dòng)的過程中也應(yīng)該加上判斷顯示的邏輯:

        // mBinding.tabLayout7.setOnScrollChangeListener() // min api 23 (6.0)
        // 適配 5.0  滑動(dòng)過程中判斷右側(cè)小紅點(diǎn)是否需要顯示
        mBinding.tabLayout7.viewTreeObserver.addOnScrollChangedListener {
            mBinding.vArrowDot.visibility = if (isShowDot()) View.VISIBLE else View.INVISIBLE
        }

還有初始化時(shí)的判斷邏輯:

    override fun onResume() {
        super.onResume()
        // 初始化判斷右側(cè)小紅點(diǎn)是否需要顯示
        mBinding.tabLayout7.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                mBinding.vArrowDot.visibility = if (isShowDot()) View.VISIBLE else View.INVISIBLE
                mBinding.tabLayout7.viewTreeObserver.removeOnGlobalLayoutListener(this)
            }
        })
    }

12.Tab寬度自適應(yīng)

細(xì)心的同學(xué)會(huì)發(fā)現(xiàn),這個(gè)TabLayout的item左右間距都是一樣的,不管標(biāo)題是兩個(gè)字還是四個(gè)字的,左右間距都是相等的,而實(shí)際上的效果是兩個(gè)字的Tab要比四個(gè)字的Tab左右間距要大一些的,那這個(gè)效果是怎么實(shí)現(xiàn)的呢?

實(shí)際上是我們?cè)O(shè)置了tabMinWidth

app:tabMinWidth="50dp"

源碼中默認(rèn)的是:

  private int getTabMinWidth() {
    if (requestedTabMinWidth != INVALID_WIDTH) {
      // If we have been given a min width, use it
      return requestedTabMinWidth;
    }
    // Else, we'll use the default value
    return (mode == MODE_SCROLLABLE || mode == MODE_AUTO) ? scrollableTabMinWidth : 0;
  }
  • requestedTabMinWidth是根據(jù)xml設(shè)置獲取的。
  • 假如xml沒設(shè)置tabMinWidth的情況下,且tabMode是scrollable的情況下,會(huì)返回默認(rèn)配置,否則為0,即tabMode為fixed的情況。

系統(tǒng)默認(rèn)配置scrollableTabMinWidth:

<dimen name="design_tab_scrollable_min_width">72dp</dimen>

在兩個(gè)字和四個(gè)字的標(biāo)題都存在的情況下,兩個(gè)字用這個(gè)默認(rèn)寬度就會(huì)有多余的間距,所以會(huì)出現(xiàn)間距不均等的情況,通過設(shè)置覆蓋默認(rèn)即可解決。

13.自定義Item View

前面講到Tab內(nèi)部實(shí)現(xiàn)是一個(gè)View,那我們就可以通過官方提供api(setCustomView)來自定義這個(gè)view。

setCustomView的兩種方式:

  • public Tab setCustomView(@Nullable View view)
  • public Tab setCustomView(@LayoutRes int resId)

我們先編寫一個(gè)自定義的布局文件,布局文件比較簡(jiǎn)單,一個(gè)LottieAnimationView和TextView。

再通過Tab添加進(jìn)去即可。

        val animMap = mapOf("party" to R.raw.anim_confetti, "pizza" to R.raw.anim_pizza, "apple" to R.raw.anim_apple)

        animMap.keys.forEach { s ->
            val tab = mBinding.tabLayout8.newTab()
            val view = LayoutInflater.from(this).inflate(R.layout.item_tab, null)
            val imageView = view.findViewById<LottieAnimationView>(R.id.lav_tab_img)
            val textView = view.findViewById<TextView>(R.id.tv_tab_text)
            imageView.setAnimation(animMap[s]!!)
            imageView.setColorFilter(Color.BLUE)
            textView.text = s
            tab.customView = view
            mBinding.tabLayout8.addTab(tab)
        }

14.使用Lottie

Lottie是一個(gè)可以在多平臺(tái)展示動(dòng)畫的庫,相信很多同學(xué)都已經(jīng)用過了,就不詳細(xì)展開了,感興趣的可以查看Lottie官方文檔。

Lottie依賴:

implementation "com.airbnb.android:lottie:5.0.1"

上一節(jié)中我們實(shí)現(xiàn)了自定義TabLayout的Item View,在這個(gè)自定義的布局中,我們用LottieAnimationView來承載動(dòng)畫的展示。

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/item_tab"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="vertical">

    <com.airbnb.lottie.LottieAnimationView
        android:id="@+id/lav_tab_img"
        android:layout_width="30dp"
        android:layout_height="30dp"
        app:lottie_colorFilter="@color/black"
        app:lottie_rawRes="@raw/anim_confetti" />

    <TextView
        android:id="@+id/tv_tab_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/app_name"
        android:textColor="@color/black"
        android:textSize="14sp" />

</androidx.appcompat.widget.LinearLayoutCompat>

添加的方式也在上一節(jié)中講過了,我們只需要控制好選中、未選中的狀態(tài)即可。

        mBinding.tabLayout8.addOnTabSelectedListener(object : OnTabSelectedListener {
            override fun onTabSelected(tab: TabLayout.Tab?) {
                tab?.setSelected()
                tab?.let { mBinding.viewPager.currentItem = it.position }
            }

            override fun onTabUnselected(tab: TabLayout.Tab?) {
                tab?.setUnselected()
            }

            override fun onTabReselected(tab: TabLayout.Tab?) {

            }
        })

這里通過兩個(gè)擴(kuò)展方法分別處理不同的狀態(tài)。

選中狀態(tài),播放動(dòng)畫并設(shè)置icon顏色

    /**
     * 選中狀態(tài)
     */
    fun TabLayout.Tab.setSelected() {
        this.customView?.let {
            val textView = it.findViewById<TextView>(R.id.tv_tab_text)
            val selectedColor = ContextCompat.getColor(this@TabLayoutActivity, R.color.colorPrimary)
            textView.setTextColor(selectedColor)

            val imageView = it.findViewById<LottieAnimationView>(R.id.lav_tab_img)
            if (!imageView.isAnimating) {
                imageView.playAnimation()
            }
            setLottieColor(imageView, true)
        }
    }

未選中狀態(tài),停止動(dòng)畫并還原初始狀態(tài),然后設(shè)置icon顏色

    /**
     * 未選中狀態(tài)
     */
    fun TabLayout.Tab.setUnselected() {
        this.customView?.let {
            val textView = it.findViewById<TextView>(R.id.tv_tab_text)
            val unselectedColor = ContextCompat.getColor(this@TabLayoutActivity, R.color.black)
            textView.setTextColor(unselectedColor)

            val imageView = it.findViewById<LottieAnimationView>(R.id.lav_tab_img)
            if (imageView.isAnimating) {
                imageView.cancelAnimation()
                imageView.progress = 0f // 還原初始狀態(tài)
            }
            setLottieColor(imageView, false)
        }
    }

關(guān)于修改lottie icon的顏色,目前網(wǎng)上的答案參差不齊,還是源碼來的直接。

源碼:

    if (ta.hasValue(R.styleable.LottieAnimationView_lottie_colorFilter)) {
      int colorRes = ta.getResourceId(R.styleable.LottieAnimationView_lottie_colorFilter, -1);
      ColorStateList csl = AppCompatResources.getColorStateList(getContext(), colorRes);
      SimpleColorFilter filter = new SimpleColorFilter(csl.getDefaultColor());
      KeyPath keyPath = new KeyPath("**");
      LottieValueCallback<ColorFilter> callback = new LottieValueCallback<>(filter);
      addValueCallback(keyPath, LottieProperty.COLOR_FILTER, callback);
    }

所以直接借鑒即可:

    /**
     * set lottie icon color
     */
    private fun setLottieColor(imageView: LottieAnimationView?, isSelected: Boolean) {
        imageView?.let {
            val color = if (isSelected) R.color.colorPrimary else R.color.black
            val csl = AppCompatResources.getColorStateList(this@TabLayoutActivity, color)
            val filter = SimpleColorFilter(csl.defaultColor)
            val keyPath = KeyPath("**")
            val callback = LottieValueCallback<ColorFilter>(filter)
            it.addValueCallback(keyPath, LottieProperty.COLOR_FILTER, callback)
        }
    }

動(dòng)畫文件的下載網(wǎng)站推薦: lordicon

15.關(guān)聯(lián)ViewPager

15.1 編寫FragmentPagerAdapter

    private inner class SimpleFragmentPagerAdapter constructor(fm: FragmentManager) :
        FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {

        private val tabTitles = arrayOf("Android", "Kotlin", "Flutter")
        private val fragment = arrayOf(Fragment1(), Fragment2(), Fragment3())

        override fun getItem(position: Int): Fragment {
            return fragment[position]
        }

        override fun getCount(): Int {
            return fragment.size
        }

        override fun getPageTitle(position: Int): CharSequence {
            return tabTitles[position]
        }
    }

15.2 給ViewPager設(shè)置Adapter

mBinding.viewPager.adapter = SimpleFragmentPagerAdapter(supportFragmentManager)

15.3 給TabLayout關(guān)聯(lián)ViewPager

mBinding.tabLayout1.setupWithViewPager(mBinding.viewPager)

以上即可把TabLayoutViewPager關(guān)聯(lián)起來,TabLayout的Tab也會(huì)由FragmentPagerAdapter中的標(biāo)題自動(dòng)生成。

15.4 setupWithViewPager源碼分析

究竟是怎么關(guān)聯(lián)起來的呢?

下面是setupWithViewPager中的部分源碼:

        if (viewPager != null) {
            this.viewPager = viewPager;
            if (this.pageChangeListener == null) {
            	// 步驟1
                this.pageChangeListener = new TabLayout.TabLayoutOnPageChangeListener(this);
            }

            this.pageChangeListener.reset();
            viewPager.addOnPageChangeListener(this.pageChangeListener);
            // 步驟2
            this.currentVpSelectedListener = new TabLayout.ViewPagerOnTabSelectedListener(viewPager);
            // 步驟3
            this.addOnTabSelectedListener(this.currentVpSelectedListener);
            PagerAdapter adapter = viewPager.getAdapter();
            if (adapter != null) {
                this.setPagerAdapter(adapter, autoRefresh);
            }

            if (this.adapterChangeListener == null) {
                this.adapterChangeListener = new TabLayout.AdapterChangeListener();
            }

            this.adapterChangeListener.setAutoRefresh(autoRefresh);
            // 步驟4
            viewPager.addOnAdapterChangeListener(this.adapterChangeListener);
            this.setScrollPosition(viewPager.getCurrentItem(), 0.0F, true);
        }
  1. 先是創(chuàng)建了TabLayout.TabLayoutOnPageChangeListener,并設(shè)置給了viewPager.addOnPageChangeListener。
  2. 然后又創(chuàng)建了TabLayout.ViewPagerOnTabSelectedListener(viewPager),并傳入當(dāng)前viewPager,然后設(shè)置給了addOnTabSelectedListener。
  3. 所以,經(jīng)過這種你來我往的操作之后,設(shè)置TabLayout的選中下標(biāo)和設(shè)置ViewPager的選中下標(biāo),其實(shí)效果是一毛一樣的,因?yàn)槁?lián)動(dòng)起來了…

另外,F(xiàn)ragmentPagerAdapter已經(jīng)廢棄了,官方推薦使用viewpager2FragmentStateAdapter 代替。

Deprecated Switch to androidx.viewpager2.widget.ViewPager2 and use androidx.viewpager2.adapter.FragmentStateAdapter instead.

16.常用API整理

16.1 TabLayout

API含義
backgroundTabLayout背景顏色
tabIndicator指示器(一般下劃線)
tabIndicatorColor指示器顏色
tabIndicatorHeight指示器高度,不顯示寫0dp
tabIndicatorFullWidth指示器寬度是否撐滿item
tabModetab顯示形式,1.auto自動(dòng),2.fixed固定寬度,3.scrollable可滑動(dòng)
tabSelectedTextColortab選中文字顏色
tabTextColortab未選中文字顏色
tabRippleColortab點(diǎn)擊效果顏色
tabGravitytab對(duì)齊方式
tabTextAppearancetab文本樣式,可引用style
tabMaxWidthtab最大寬度
tabMinWidthtab最小寬度
setupWithViewPagertabLayout關(guān)聯(lián)ViewPager
addOnTabSelectedListenertab選中監(jiān)聽事件

16.2 TabLayout.Tab

API含義
setCustomView設(shè)置tab自定義view
setIcon設(shè)置tab icon
setText設(shè)置tab文本
getOrCreateBadge獲取或創(chuàng)建badge(小紅點(diǎn))
removeBadge移除badge(小紅點(diǎn))
select設(shè)置tab選中
isSelected獲取tab選中狀態(tài)

16.3 BadgeDrawable

API含義
setVisible設(shè)置顯示狀態(tài)
setBackgroundColor設(shè)置小紅點(diǎn)背景顏色
getBadgeTextColor設(shè)置小紅點(diǎn)文本顏色
setNumber設(shè)置小紅點(diǎn)顯示數(shù)量
clearNumber清除小紅點(diǎn)數(shù)量
setBadgeGravity設(shè)置小紅點(diǎn)位置對(duì)齊方式

https://github.com/yechaoa/MaterialDesign

最后

到此這篇關(guān)于Android原生TabLayout使用解析的文章就介紹到這了,更多相關(guān)Android原生TabLayout使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論