日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android 原生 TabLayout 使用全解析

發(fā)布時(shí)間:2023/12/29 Android 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 原生 TabLayout 使用全解析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

為什么會(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也在不斷的迭代,目前為止,常見的樣式都能滿足。

效果圖

簡介

TabLayout:一個(gè)橫向可滑動(dòng)的菜單導(dǎo)航ui組件。

Tab:TabLayout中的item,可以通過newTab()創(chuàng)建。

TabView:Tab的實(shí)例,是一個(gè)包含ImageView和TextView的線性布局。

TabItem:一種特殊的“視圖”,在TabLayout中可以顯式聲明Tab。

官方文檔

https://developer.android.google.cn/reference/com/google/android/material/tabs/TabLayout?hl=en

功能拆解

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.TabLayoutandroid: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.TabLayoutandroid:layout_height="wrap_content"android:layout_width="match_parent"><com.google.android.material.tabs.TabItemandroid:text="@string/tab_text"/><com.google.android.material.tabs.TabItemandroid: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è)TextView和ImageView,添加圖標(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長按提示文字

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

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

可以取消長按事件,在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"><itemandroid: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è),我們可以簡單的設(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? LinearLayoutlinearLayout?.let {it.showDividers = LinearLayout.SHOW_DIVIDER_MIDDLEit.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è)長條,這個(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.TabLayoutandroid: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í)添加起來也非常簡單,難在未知。

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

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

// 數(shù)字 mBinding.tabLayout5.getTabAt(defaultIndex)?.let { tab ->tab.orCreateBadge.apply {backgroundColor = Color.REDmaxCharacterCount = 3number = 99999badgeTextColor = 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

https://blog.csdn.net/yechaoa/article/details/122272822?spm=1001.2014.3001.5501

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 = 0var tipCount = 0companyMap.keys.forEachIndexed { index, _ ->mBinding.tabLayout7.getTabAt(index)?.let { tab ->val tabView = tab.view as LinearLayoutval 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 = showIndexreturn 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.INVISIBLEmBinding.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 itreturn requestedTabMinWidth;}// Else, we'll use the default valuereturn (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的兩種方式:

1. public Tab setCustomView(@Nullable View view)

2. public Tab setCustomView(@LayoutRes int resId)

我們先編寫一個(gè)自定義的布局文件,布局文件比較簡單,一個(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 = stab.customView = viewmBinding.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.LottieAnimationViewandroid:id="@+id/lav_tab_img"android:layout_width="30dp"android:layout_height="30dp"app:lottie_colorFilter="@color/black"app:lottie_rawRes="@raw/anim_confetti" /><TextViewandroid: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)。

1. 選中狀態(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)}}

2. 未選中狀態(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.blackval 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

https://lordicon.com/

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)

以上即可把TabLayout和ViewPager關(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) {// 步驟1this.pageChangeListener = new TabLayout.TabLayoutOnPageChangeListener(this);}this.pageChangeListener.reset();viewPager.addOnPageChangeListener(this.pageChangeListener);// 步驟2this.currentVpSelectedListener = new TabLayout.ViewPagerOnTabSelectedListener(viewPager);// 步驟3this.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);// 步驟4viewPager.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)起來了…

另外,FragmentPagerAdapter已經(jīng)廢棄了,官方推薦使用viewpager2 和 FragmentStateAdapter 代替。

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

16.常用API整理

16.1 TabLayout

16.2 TabLayout.Tab

16.3 BadgeDrawable

Github:

https://github.com/yechaoa/MaterialDesign

總結(jié)

以上是生活随笔為你收集整理的Android 原生 TabLayout 使用全解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 麻豆出品 | 奇米精品一区二区三区在线观看 | 青青草狠狠操 | 一区二区www | 国语对白少妇spa私密按摩 | 久操青青 | 东方影库av | 伊人快播 | 狠狠gao | 一级黄色大片免费观看 | 男人的天堂视频 | 欧美性生活一区二区三区 | 欧美视频一区二区在线 | 五月天导航 | 日韩成人一级 | 亚洲免费观看 | 国产精品久久久久久久久免费相片 | 欧美色图自拍 | 91av在线免费视频 | 午夜视频色 | 男人的天堂视频 | 久久久男女 | 久久综合亚洲 | 日本黄色美女视频 | 国产在线一二区 | 国精品一区二区三区 | 欧美激情性做爰免费视频 | 浴室里强摁做开腿呻吟男男 | 久久国产精品精品国产色婷婷 | 久久国产麻豆 | av资源中文在线 | 久操视频免费 | 18一20岁毛毛片 | 免费国产黄色 | 国产人人射 | 国产jizz18女人高潮 | 欧美大片高清免费观看 | 国产精品丝袜黑色高跟鞋的设计特点 | 精品一区二区三区不卡 | 亚洲欧美另类国产 | 国产人妻精品一区二区三 | 国产一级淫 | 国产91白丝在一线播放 | 青草在线视频 | jizz一区二区 | 欧美日韩精品在线观看视频 | 成人1区2区3区 | 亚洲一区二区高清视频 | 欧美极品videos精品 | 精品色哟哟 | 成人黄色小说在线观看 | 男女野外做受全过程 | 欧洲xxxxx| 性高潮视频在线观看 | 亚洲男人的天堂在线观看 | 国产欧美一区二 | 色av一区二区 | 成年人www | 91久久精品国产91性色tv | 玖操 | 女人天堂网站 | 精品人妻一区二区三区浪潮在线 | 人妻互换一区二区三区四区五区 | 神马影院午夜伦理 | 黄色福利网站 | 久久亚洲国产成人精品性色 | 亲子乱一区二区三区 | 自拍偷拍第一页 | 国产一区欧美一区 | 青青视频网 | 亚洲精品888| 国产欧美久久久 | 日韩伦理一区二区三区 | 日韩精品卡通动漫网站 | 一级特黄免费视频 | 天天摸天天操天天射 | 国产精品作爱 | 中文字幕啪啪 | 视频在线观看一区 | 91av在线免费 | 国产五月天婷婷 | 黑巨茎大战欧美白妞 | 日本精品成人 | 日本黄色一区二区三区 | 91极品尤物 | 免费中文av | 中文字幕免费一区二区 | 91美女片黄在线观看 | 午夜不卡视频 | 无码人妻精品一区二区三应用大全 | 五月婷婷网站 | 欧美精品一线 | 怡春院一区二区 | 少妇熟女一区二区 | av一二三区| www.激情 | 日韩高清欧美 | 男女无遮挡xx00动态图120秒 | 免费av网站在线看 |