Files
assistant-android/app/src/main/java/com/gh/gamecenter/wrapper/BaseTabWrapperFragment.kt
2024-09-26 17:42:44 +08:00

687 lines
29 KiB
Kotlin

package com.gh.gamecenter.wrapper
import android.graphics.Typeface
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewStub
import android.widget.LinearLayout
import androidx.core.graphics.ColorUtils
import androidx.core.view.updateLayoutParams
import androidx.fragment.app.Fragment
import androidx.viewpager.widget.ViewPager
import com.gh.common.iinterface.IMultiTab
import com.gh.common.iinterface.ISmartRefreshContent
import com.gh.common.iinterface.ISuperiorChain
import com.gh.common.prioritychain.PriorityChain
import com.gh.common.util.ViewPagerFragmentHelper
import com.gh.gamecenter.R
import com.gh.gamecenter.common.base.adapter.FragmentAdapter
import com.gh.gamecenter.common.base.fragment.BaseLazyFragment
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
import com.gh.gamecenter.common.constant.EntranceConsts
import com.gh.gamecenter.common.databinding.ReuseLoadingBinding
import com.gh.gamecenter.common.databinding.ReuseNoConnectionBinding
import com.gh.gamecenter.common.databinding.ReuseNoneDataBinding
import com.gh.gamecenter.common.exposure.ExposureSource
import com.gh.gamecenter.common.json.json
import com.gh.gamecenter.common.utils.*
import com.gh.gamecenter.common.view.TabIndicatorView
import com.gh.gamecenter.common.view.WrapContentDraweeView
import com.gh.gamecenter.databinding.TabItemMainBinding
import com.gh.gamecenter.entity.BottomTab
import com.gh.gamecenter.entity.MultiTabNav
import com.gh.gamecenter.fragment.ReloadFragment
import com.gh.gamecenter.home.custom.CustomPageFragment
import com.google.android.material.tabs.TabLayout
import kotlin.math.abs
/**
* 多Tab导航页 基类
*/
abstract class BaseTabWrapperFragment : BaseLazyFragment(), IMultiTab {
protected var viewPager: ViewPager? = null
protected var tabLayout: TabLayout? = null
protected var indicatorView: TabIndicatorView? = null
protected var noDataStub: ViewStub? = null
protected var noConnectionStub: ViewStub? = null
protected var loadingStub: ViewStub? = null
protected var noConnectionBinding: ReuseNoConnectionBinding? = null
protected var noDataBinding: ReuseNoneDataBinding? = null
protected var loadingBinding: ReuseLoadingBinding? = null
protected var tabBindingList = arrayListOf<TabItemMainBinding>()
protected var tabImageStyleList = arrayListOf<Int>()
protected var fragmentList = ArrayList<Fragment>()
protected var multiTabNavId = ""
protected var multiTabNavName = ""
protected var bottomTabId = ""
protected var bottomTabName = ""
protected var defaultSelectedTab = -1
protected var lastSelectedPosition = 0
protected var backgroundColor: Int = 0
protected var backgroundWhiteColor: Int = 0
protected var amwayPrimaryColor: Int = 0
protected var tabDefaultColor: Int = 0
protected var tabSelectedColor: Int = 0
protected var tabDefaultLightColor: Int = 0
abstract fun provideViewModel(): TabWrapperViewModel
protected open fun provideTabLayout(): TabLayout? = mCachedView.findViewById(R.id.tabLayout)
protected open fun provideViewPager(): ViewPager? = mCachedView.findViewById(R.id.viewPager)
protected open fun provideIndicatorView(): TabIndicatorView? = mCachedView.findViewById(R.id.indicatorView)
protected open fun provideIndicatorWidth(): Int = DEFAULT_INDICATOR_WIDTH
protected open fun provideTabTextSize(): Float = DEFAULT_TAB_TEXT_SIZE
protected open fun provideTabDefaultColor(): Int = TAB_DEFAULT_COLOR
protected open fun provideTabSelectedColor(): Int = TAB_SELECTED_COLOR
override fun provideMultiTabId(): String = multiTabNavId
override fun provideMultiTabName(): String = multiTabNavName
override fun provideCurrentTabEntity(): MultiTabNav.LinkMultiTabNav? = getCurrentTabEntity()
override fun provideLastSelectedPosition(): Int = lastSelectedPosition
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
savedInstanceState?.let { defaultSelectedTab = it.getInt(LAST_SELECTED_POSITION) }
multiTabNavId = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_ID, "") ?: ""
multiTabNavName = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_NAME, "") ?: ""
bottomTabName = arguments?.getString(EntranceConsts.KEY_BOTTOM_TAB_NAME, "") ?: ""
bottomTabId = arguments?.getString(EntranceConsts.KEY_BOTTOM_TAB_ID, "") ?: ""
}
override fun onSaveInstanceState(outState: Bundle) {
viewPager?.let { outState.putInt(LAST_SELECTED_POSITION, it.currentItem) }
super.onSaveInstanceState(outState)
}
override fun onFragmentFirstVisible() {
super.onFragmentFirstVisible()
noDataStub = mCachedView.findViewById(R.id.reuse_no_data_stub)
noConnectionStub = mCachedView.findViewById(R.id.reuse_no_connection_stub)
loadingStub = mCachedView.findViewById(R.id.reuse_loading_stub)
backgroundColor = com.gh.gamecenter.common.R.color.ui_background.toColor(requireContext())
backgroundWhiteColor = com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext())
amwayPrimaryColor = com.gh.gamecenter.common.R.color.amway_primary_color.toColor(requireContext())
tabDefaultColor = provideTabDefaultColor().toColor(requireContext())
tabSelectedColor = provideTabSelectedColor().toColor(requireContext())
tabDefaultLightColor = TAB_DEFAULT_COLOR_LIGHT.toColor(requireContext())
if (multiTabNavId.isNotEmpty()) {
provideViewModel().tabListLiveData.observe(viewLifecycleOwner) {
if (defaultSelectedTab == -1) {
defaultSelectedTab = provideViewModel().defaultTabPosition
}
initViewPager(ArrayList(it))
// 当 tab 少于或等于一个的时候隐藏顶部 tab 栏,停用 nestedScroll
if (it.size <= 1) {
hideTab()
}
showNoConnection(false)
showLoading(false)
showNoData(it.isEmpty())
}
provideViewModel().errorLiveData.observe(viewLifecycleOwner) {
showLoading(false)
showNoData(false)
showNoConnection(true)
}
SensorsBridge.trackEvent(
"ViewSeveralTabPage",
"bottom_tab",
bottomTabName,
"several_tab_page_name",
multiTabNavName,
"several_tab_page_id",
multiTabNavId
)
}
}
private fun showNoConnection(show: Boolean) {
if (show) {
if (noConnectionBinding == null) {
noConnectionStub?.setOnInflateListener { _, inflated ->
noConnectionBinding = ReuseNoConnectionBinding.bind(inflated)
noConnectionBinding?.root?.visibility = View.VISIBLE
noConnectionBinding?.connectionReloadTv?.setOnClickListener {
provideViewModel().getMultiTabNav()
showNoData(false)
showNoConnection(false)
showLoading(true)
}
}
noConnectionStub?.inflate()
} else {
noConnectionBinding?.root?.visibility = View.VISIBLE
}
} else {
noConnectionBinding?.root?.visibility = View.GONE
}
}
private fun showNoData(show: Boolean) {
if (show) {
if (noDataBinding == null) {
noDataStub?.setOnInflateListener { _, inflated ->
noDataBinding = ReuseNoneDataBinding.bind(inflated)
noDataBinding?.root?.visibility = View.VISIBLE
}
noDataStub?.inflate()
} else {
noDataBinding?.root?.visibility = View.VISIBLE
}
} else {
noDataBinding?.root?.visibility = View.GONE
}
}
private fun showLoading(show: Boolean) {
if (show) {
if (loadingBinding == null) {
loadingStub?.setOnInflateListener { _, inflated ->
loadingBinding = ReuseLoadingBinding.bind(inflated)
loadingBinding?.root?.visibility = View.VISIBLE
}
loadingStub?.inflate()
} else {
loadingBinding?.root?.visibility = View.VISIBLE
}
} else {
loadingBinding?.root?.visibility = View.GONE
}
}
abstract fun hideTab()
override fun onBackPressed(): Boolean {
viewPager?.run {
val currentFragment = fragmentList.safelyGetInRelease(currentItem)
if (currentFragment is ToolbarFragment) {
return currentFragment.onBackPressed()
}
}
return super.onBackPressed()
}
protected open fun initViewPager(tabEntityList: ArrayList<MultiTabNav.LinkMultiTabNav>) {
viewPager = provideViewPager()
tabLayout = provideTabLayout()
indicatorView = provideIndicatorView()
val fragmentList = generateFragments(tabEntityList).apply { fragmentList = this }
val tabTitleList = arrayListOf<String>()
tabEntityList.forEach { tabTitleList.add(it.name) }
viewPager?.run {
offscreenPageLimit = fragmentList.size
doOnScroll(
onPageSelected = { position ->
onPageSelected(position)
tabEntityList.safelyGetInRelease(position)?.let { logTabSelected(it, position) }
},
onPageScrolled = { position, positionOffset, _ ->
onPageScrolled(position, positionOffset, tabEntityList)
}
)
setRestoredCurItem(this)
adapter = FragmentAdapter(childFragmentManager, fragmentList, tabTitleList)
}
tabLayout?.setupWithViewPager(viewPager)
indicatorView?.setupWithTabLayout(tabLayout)
indicatorView?.setupWithViewPager(viewPager)
indicatorView?.setIndicatorWidth(provideIndicatorWidth())
initTabView(tabEntityList)
showTabGuideIfExists(tabEntityList)
}
private fun showTabGuideIfExists(tabEntityList: ArrayList<MultiTabNav.LinkMultiTabNav>) {
val guidePosition = tabEntityList.indexOfFirst { it.guide != null }
if (guidePosition != -1) {
val tabEntity = tabEntityList[guidePosition]
val guide = tabEntity.guide
guide?.bottomTabId = bottomTabId
guide?.multiTabId = tabEntity.id
showTabGuide(true, guide, guidePosition)
} else {
showTabGuide(false)
}
}
abstract fun showTabGuide(shouldShow: Boolean, guide: BottomTab.Guide? = null, guidePosition: Int = -1)
protected open fun generateFragments(tabEntityList: ArrayList<MultiTabNav.LinkMultiTabNav>): ArrayList<Fragment> {
val fragmentList = arrayListOf<Fragment>()
for ((index, tabEntity) in tabEntityList.withIndex()) {
val bundle = Bundle()
bundle.putAll(arguments)
bundle.putBoolean(EntranceConsts.KEY_IS_FROM_MAIN_WRAPPER, false)
bundle.putBoolean(EntranceConsts.KEY_IS_FROM_TAB_WRAPPER, true)
bundle.putInt(EntranceConsts.KEY_TAB_COUNT, tabEntityList.size)
bundle.putInt(EntranceConsts.KEY_TAB_INDEX, index)
bundle.putString(EntranceConsts.KEY_TAB_NAME, tabEntity.name)
bundle.putInt(EntranceConsts.KEY_POSITION, index)
val bottomTabExposureSource = arguments?.getParcelableArrayList<ExposureSource>(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST)
val multiTabNavId = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_ID, "") ?: ""
val multiTabNavName = arguments?.getString(EntranceConsts.KEY_MULTI_TAB_NAV_NAME, "") ?: ""
val multiTabNavExposureSource = ExposureSource("多tab导航页", "${multiTabNavName}+${multiTabNavId}")
val tabExposureSource = ExposureSource("顶部tab", tabEntity.name)
val exposureSourceList = if (bottomTabExposureSource != null) {
bottomTabExposureSource + multiTabNavExposureSource + tabExposureSource
} else {
arrayListOf(multiTabNavExposureSource, tabExposureSource)
}
bundle.putParcelableArrayList(EntranceConsts.KEY_EXPOSURE_SOURCE_LIST, exposureSourceList.toArrayList())
val fragment = when (tabEntity.link?.type) {
ViewPagerFragmentHelper.TYPE_CUSTOM_PAGE -> {
val superiorChain = if (this is ISuperiorChain) this else null
bundle.putString(EntranceConsts.KEY_CUSTOM_PAGE_ID, tabEntity.link.link)
bundle.putString(EntranceConsts.KEY_CUSTOM_PAGE_NAME, tabEntity.link.text)
CustomPageFragment().setSuperiorChain(superiorChain).with(bundle)
}
else -> tabEntity.link?.let { ViewPagerFragmentHelper.createFragment(this, bundle, it, true) }
?: ReloadFragment()
}
fragmentList.add(fragment)
}
return fragmentList
}
/**
* 设置 ViewPager 默认的选中项
*/
protected open fun setRestoredCurItem(viewPager: ViewPager) {
// 设置默认 position 避免 position 为 0 的 fragment 被先加载显示再跳转至具体页面
tryCatchInRelease {
val field = ViewPager::class.java.getDeclaredField("mRestoredCurItem")
field.isAccessible = true
field.set(viewPager, defaultSelectedTab)
lastSelectedPosition = defaultSelectedTab
}
}
/**
* 初始化每个需要显示的 TabView
*/
protected open fun initTabView(tabEntityList: ArrayList<MultiTabNav.LinkMultiTabNav>) {
for (i in 0 until tabEntityList.size) {
val tabView = tabLayout?.getTabAt(i) ?: continue
val tabEntity = tabEntityList[i]
val tabTitle = if (tabView.text != null) tabView.text.toString() else ""
val tabViewBinding = generateTabView(tabTitle)
val tabImageStyle = if (tabEntity.img.isEmpty()) {
TAB_IMAGE_EMPTY
} else if (tabEntity.showImgOnSelected == true) {
TAB_IMAGE_ALWAYS_ON
} else {
TAB_IMAGE_HIDE_ON_SELECTED
}
tabBindingList.add(tabViewBinding)
tabImageStyleList.add(tabImageStyle)
if (tabEntity.img.isNotEmpty()) {
tabViewBinding.titleTv.visibility = View.GONE
tabViewBinding.invisibleTitleTv.visibility = View.GONE
tabViewBinding.titleIv.setFixedHeight(16)
// 部分设备加载图片时会获取到错误的最小宽度,这里为它做个 64DP 的保底尺寸
tabViewBinding.titleIv.setTag(ImageUtils.TAG_TARGET_WIDTH, 64F.dip2px())
tabViewBinding.titleIv.display(tabEntity.img)
tabViewBinding.titleIv.registerLoadingCallback(object : WrapContentDraweeView.LoadingCallback {
override fun loaded() {
postRunnable {
viewPager?.run {
// 图片 layout 完成后,更新 tabBar 和 indicatorView 的位置,避免偏移
tabLayout?.setScrollPosition(currentItem, 0F, false)
indicatorView?.generatePath(currentItem, 0F)
}
}
}
})
} else {
tabViewBinding.titleTv.visibility = View.VISIBLE
tabViewBinding.invisibleTitleTv.visibility = View.INVISIBLE
}
tabView.customView = tabViewBinding.root
tabView.view.setPadding(0, 0, 0, 0)
tabView.view.setOnClickListener {
onTabViewClick()
}
// 第一个和最后一个分别设置额外的外边距
if (i == 0) {
tabView.view.updateLayoutParams {
this as LinearLayout.LayoutParams
setMargins(getFirstTabLeftMargin(), 0, 0, 0)
}
} else if (i == tabEntityList.size - 1) {
tabView.view.updateLayoutParams {
this as LinearLayout.LayoutParams
setMargins(0, 0, getLastTabRightMargin(), 0)
}
}
}
}
protected open fun getFirstTabLeftMargin(): Int = 10F.dip2px()
protected open fun getLastTabRightMargin(): Int = 10F.dip2px()
protected open fun onTabViewClick() {}
/**
* 生成 TabView
*/
protected open fun generateTabView(title: String): TabItemMainBinding {
val binding = TabItemMainBinding.inflate(LayoutInflater.from(requireContext()))
binding.titleTv.run {
text = title
textSize = provideTabTextSize()
setTextColor(tabDefaultColor)
}
binding.invisibleTitleTv.run {
text = title
textSize = provideTabTextSize()
}
return binding
}
protected open fun onPageSelected(position: Int) {
notifyChildFragmentLifecycle(position)
}
abstract fun onPageScrolled(position: Int, positionOffset: Float, tabEntityList: ArrayList<MultiTabNav.LinkMultiTabNav>)
protected open fun logTabSelected(tabEntity: MultiTabNav.LinkMultiTabNav, position: Int) {
SensorsBridge.trackEvent("SeveralTabPageTabSelect", json {
"position" to position
"tab_content" to tabEntity.name
"link_type" to tabEntity.link?.type
"link_id" to tabEntity.link?.link
"link_text" to tabEntity.link?.text
"bottom_tab" to bottomTabName
"several_tab_page_name" to multiTabNavName
"several_tab_page_id" to multiTabNavId
})
}
/**
* 安全地从根据 position 获取 fragment
*/
protected fun getFragment(position: Int): Fragment? {
return if (position < fragmentList.size) {
fragmentList.safelyGetInRelease(position)
} else {
null
}
}
protected fun getValidSmartRefreshContent(position: Int? = viewPager?.currentItem): ISmartRefreshContent? {
if (position == null) return null
val fragment = getFragment(position)
return if (fragment?.isAdded == true) fragment as? ISmartRefreshContent else null
}
// 滑动切换Tab是否使用缩放效果
protected open fun isTabScaleEnabled(): Boolean = true
/**
* 更新 tab 的样式
* @param selectedPosition 选中的 tab
* @param positionOffset 与选中 tab 的位置偏移,为负时在选中的 tab 左边,为正时在选中 tab 的右边
* @param currentTabDefaultColor tab默认颜色
* @param currentTabSelectedColor tab选中颜色
*/
protected open fun updateTabStyle(selectedPosition: Int, positionOffset: Float, currentTabDefaultColor: Int, currentTabSelectedColor: Int) {
if (tabBindingList.isEmpty()) return
val prePosition = selectedPosition - 1
val nextPosition = selectedPosition + 1
// positionOffset 小于零,表示 indicator 当前位置处于选中的 tab 的左边
val indicatorOnLeft = positionOffset < 0F
val selectedTabBinding = tabBindingList.safelyGetInRelease(selectedPosition) ?: return
val selectedTabImageStyle = tabImageStyleList.safelyGetInRelease(selectedPosition) ?: return
// 前一个 tab、当前选中的 tab、后一个 tab 的显示比例
val preScaleRatio = 1 + abs(positionOffset) / 4
val selectedScaleRatio = 1 + (1 - abs(positionOffset)) / 4
val nextScaleRatio = 1 + positionOffset / 4
// 处理前一个 tab
if (prePosition != -1) {
tabBindingList[prePosition].run {
if (indicatorOnLeft) {
when (tabImageStyleList[prePosition]) {
TAB_IMAGE_ALWAYS_ON -> {
if (isTabScaleEnabled()) {
titleIv.scaleX = preScaleRatio
titleIv.scaleY = preScaleRatio
}
}
TAB_IMAGE_HIDE_ON_SELECTED -> {
if (isTabScaleEnabled()) {
titleIv.scaleX = preScaleRatio
titleIv.scaleY = preScaleRatio
}
titleIv.visibility = View.VISIBLE
titleTv.visibility = View.GONE
invisibleTitleTv.visibility = View.GONE
}
else -> {
titleIv.visibility = View.GONE
titleTv.visibility = View.VISIBLE
invisibleTitleTv.visibility = View.INVISIBLE
}
}
if (isTabScaleEnabled()) {
titleTv.scaleX = preScaleRatio
titleTv.scaleY = preScaleRatio
}
titleTv.setTextColor(
ColorUtils.blendARGB(
currentTabDefaultColor,
currentTabSelectedColor,
abs(positionOffset)
)
)
} else {
titleTv.setTextColor(currentTabDefaultColor)
}
}
}
// 更新当前选中的 tab
selectedTabBinding.run {
// 更新当前选中的 tab 的图片显示状态
when (selectedTabImageStyle) {
TAB_IMAGE_ALWAYS_ON -> {
if (isTabScaleEnabled()) {
val scaleRatio = (1 + (1 - abs(positionOffset)) * 0.25).toFloat()
titleIv.scaleX = scaleRatio
titleIv.scaleY = scaleRatio
}
}
else -> {
titleIv.visibility = View.GONE
titleTv.visibility = View.VISIBLE
invisibleTitleTv.visibility = View.INVISIBLE
indicatorView?.visibility = View.VISIBLE
}
}
// 选中常驻型的图片时隐藏 indicatorView
indicatorView?.goneIf(selectedTabImageStyle == TAB_IMAGE_ALWAYS_ON)
if (isTabScaleEnabled()) {
titleTv.scaleX = selectedScaleRatio
titleTv.scaleY = selectedScaleRatio
}
titleTv.setTextColor(
ColorUtils.blendARGB(
currentTabDefaultColor,
currentTabSelectedColor,
1 - abs(positionOffset)
)
)
}
// 处理后一个 tab
if (nextPosition < tabBindingList.size) {
tabBindingList[nextPosition].run {
if (!indicatorOnLeft) {
when (tabImageStyleList[nextPosition]) {
TAB_IMAGE_ALWAYS_ON -> {
if (isTabScaleEnabled()) {
titleIv.scaleX = nextScaleRatio
titleIv.scaleY = nextScaleRatio
}
}
TAB_IMAGE_HIDE_ON_SELECTED -> {
if (isTabScaleEnabled()) {
titleIv.scaleX = nextScaleRatio
titleIv.scaleY = nextScaleRatio
}
titleIv.visibility = View.VISIBLE
titleTv.visibility = View.GONE
invisibleTitleTv.visibility = View.GONE
}
else -> {
titleIv.visibility = View.GONE
titleTv.visibility = View.VISIBLE
invisibleTitleTv.visibility = View.INVISIBLE
}
}
if (isTabScaleEnabled()) {
titleTv.scaleX = nextScaleRatio
titleTv.scaleY = nextScaleRatio
}
titleTv.setTextColor(
ColorUtils.blendARGB(
currentTabDefaultColor,
currentTabSelectedColor,
positionOffset
)
)
} else {
titleTv.setTextColor(currentTabDefaultColor)
}
}
}
// 多 tab 切换的时候可能会出现某些 tab 的文字没有回归到原始大小的问题的问题 (positionOffset 不保证连续)
for ((index, binding) in tabBindingList.withIndex()) {
if (index != prePosition && index != selectedPosition && index != nextPosition) {
if (binding.titleTv.scaleX != 1F) {
binding.titleTv.scaleX = 1F
binding.titleTv.scaleY = 1F
}
binding.titleTv.setTextColor(currentTabDefaultColor)
if (binding.titleIv.scaleX != 1F) {
binding.titleIv.scaleX = 1F
binding.titleIv.scaleY = 1F
}
}
if (index == selectedPosition) {
if (positionOffset == 0F) {
binding.titleTv.setTextColor(currentTabSelectedColor)
}
binding.titleTv.setTypeface(binding.titleTv.typeface, Typeface.BOLD)
} else {
if (positionOffset == 0F) {
binding.titleTv.setTextColor(currentTabDefaultColor)
}
binding.titleTv.setTypeface(null, Typeface.NORMAL)
}
}
}
protected open fun notifyChildFragmentLifecycle(currentSelectedPosition: Int) {
tryWithDefaultCatch {
// 补充 Viewpager Fragment 的生命周期, 先调用旧选中 fragment 的 onPause 再当前的 onResume
// 避免部分被内嵌的 Fragment 不能正常运作
if (fragmentList.size > lastSelectedPosition) {
val fragment: Fragment = fragmentList[lastSelectedPosition]
if (!fragment.isAdded) return
fragment.onPause()
val childFragmentManager = fragment.childFragmentManager
val fragments = childFragmentManager.fragments
for (childFragment in fragments) {
childFragment.onPause()
}
}
if (fragmentList.size > currentSelectedPosition) {
val fragment: Fragment = fragmentList[currentSelectedPosition]
if (!fragment.isAdded) return
fragment.onResume()
val childFragmentManager = fragment.childFragmentManager
val fragments = childFragmentManager.fragments
for (childFragment in fragments) {
childFragment.onResume()
}
}
lastSelectedPosition = currentSelectedPosition
}
}
protected fun getCurrentTabEntity(): MultiTabNav.LinkMultiTabNav? =
provideViewPager()?.currentItem?.let {
provideViewModel().tabListLiveData.value?.safelyGetInRelease(it)
}
// 默认页面是否为自定义页面
protected fun isDefaultCustomPageFragment(): Boolean = getFragment(provideViewModel().defaultTabPosition) is CustomPageFragment
abstract fun addTabGuideHandlerIfExists(chain: PriorityChain)
override fun onDarkModeChanged() {
super.onDarkModeChanged()
backgroundColor = com.gh.gamecenter.common.R.color.ui_background.toColor(requireContext())
backgroundWhiteColor = com.gh.gamecenter.common.R.color.ui_surface.toColor(requireContext())
amwayPrimaryColor = com.gh.gamecenter.common.R.color.amway_primary_color.toColor(requireContext())
tabDefaultColor = provideTabDefaultColor().toColor(requireContext())
tabSelectedColor = provideTabSelectedColor().toColor(requireContext())
tabDefaultLightColor = TAB_DEFAULT_COLOR_LIGHT.toColor(requireContext())
}
companion object {
const val LAST_SELECTED_POSITION = "last_selected_position"
var TAB_SELECTED_COLOR: Int = com.gh.gamecenter.common.R.color.text_primary
var TAB_DEFAULT_COLOR: Int = com.gh.gamecenter.common.R.color.text_secondary
var TAB_DEFAULT_COLOR_LIGHT: Int = com.gh.gamecenter.common.R.color.search_text_color_light
var DEFAULT_TAB_TEXT_SIZE = 16F
var DEFAULT_INDICATOR_WIDTH = 18
const val TAB_IMAGE_EMPTY = 0
const val TAB_IMAGE_HIDE_ON_SELECTED = 1
const val TAB_IMAGE_ALWAYS_ON = 2
}
}