修复安卓10上的一些界面问题,将主页面改为使用ViewPager2

This commit is contained in:
HapeLee
2025-09-28 03:54:05 +08:00
parent bdaf8aeb0a
commit e7679a3009
7 changed files with 153 additions and 75 deletions
@@ -3,6 +3,7 @@ package io.legato.kazusa.base
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.res.Configuration import android.content.res.Configuration
import android.graphics.Color
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.AttributeSet import android.util.AttributeSet
@@ -33,6 +34,10 @@ import io.legato.kazusa.utils.observeEvent
import io.legato.kazusa.utils.toastOnUi import io.legato.kazusa.utils.toastOnUi
import io.legato.kazusa.utils.windowSize import io.legato.kazusa.utils.windowSize
import io.legato.kazusa.lib.theme.primaryColor import io.legato.kazusa.lib.theme.primaryColor
import io.legato.kazusa.utils.fullScreen
import io.legato.kazusa.utils.setNavigationBarColorAuto
import io.legato.kazusa.utils.setStatusBarColorAuto
import io.legato.kazusa.utils.themeColor
abstract class BaseActivity<VB : ViewBinding>( abstract class BaseActivity<VB : ViewBinding>(
@@ -74,7 +79,12 @@ abstract class BaseActivity<VB : ViewBinding>(
AppContextWrapper.applyLocaleAndFont(this) AppContextWrapper.applyLocaleAndFont(this)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false) WindowCompat.setDecorFitsSystemWindows(window, false)
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q)
enableEdgeToEdge() enableEdgeToEdge()
else{
window.setNavigationBarColorAuto(themeColor(com.google.android.material.R.attr.colorSurface))
setupSystemBar()
}
//window.setNavigationBarColorAuto(themeColor(com.google.android.material.R.attr.colorSurface)) //window.setNavigationBarColorAuto(themeColor(com.google.android.material.R.attr.colorSurface))
//setupSystemBar() //setupSystemBar()
setContentView(binding.root) setContentView(binding.root)
@@ -95,6 +105,20 @@ abstract class BaseActivity<VB : ViewBinding>(
//setupSystemBar() //setupSystemBar()
} }
open fun setupSystemBar() {
if (fullScreen && !isInMultiWindow) {
fullScreen()
}
setStatusBarColorAuto(Color.TRANSPARENT, false, fullScreen)
val isDarkTheme = when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
Configuration.UI_MODE_NIGHT_YES -> true
Configuration.UI_MODE_NIGHT_NO,
Configuration.UI_MODE_NIGHT_UNDEFINED -> false
else -> false
}
WindowCompat.getInsetsController(window, window.decorView).isAppearanceLightStatusBars = !isDarkTheme
}
// override fun onConfigurationChanged(newConfig: Configuration) { // override fun onConfigurationChanged(newConfig: Configuration) {
// super.onConfigurationChanged(newConfig) // super.onConfigurationChanged(newConfig)
// //findViewById<TitleBar>(R.id.title_bar) // //findViewById<TitleBar>(R.id.title_bar)
@@ -8,7 +8,6 @@ import android.text.format.DateUtils
import android.view.Gravity import android.view.Gravity
import android.view.MenuItem import android.view.MenuItem
import android.view.MotionEvent import android.view.MotionEvent
import android.view.ViewGroup
import android.widget.FrameLayout import android.widget.FrameLayout
import android.widget.ImageView import android.widget.ImageView
import androidx.activity.addCallback import androidx.activity.addCallback
@@ -16,10 +15,10 @@ import androidx.activity.viewModels
import androidx.core.view.get import androidx.core.view.get
import androidx.core.view.postDelayed import androidx.core.view.postDelayed
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentStatePagerAdapter
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.viewpager.widget.ViewPager import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
import com.google.android.material.navigation.NavigationBarView import com.google.android.material.navigation.NavigationBarView
@@ -53,11 +52,9 @@ import io.legato.kazusa.utils.dpToPx
import io.legato.kazusa.utils.gone import io.legato.kazusa.utils.gone
import io.legato.kazusa.utils.hideSoftInput import io.legato.kazusa.utils.hideSoftInput
import io.legato.kazusa.utils.observeEvent import io.legato.kazusa.utils.observeEvent
import io.legato.kazusa.utils.setNavigationBarColorAuto
import io.legato.kazusa.utils.shouldHideSoftInput import io.legato.kazusa.utils.shouldHideSoftInput
import io.legato.kazusa.utils.showDialogFragment import io.legato.kazusa.utils.showDialogFragment
import io.legato.kazusa.utils.startActivity import io.legato.kazusa.utils.startActivity
import io.legato.kazusa.utils.themeColor
import io.legato.kazusa.utils.toastOnUi import io.legato.kazusa.utils.toastOnUi
import io.legato.kazusa.utils.viewbindingdelegate.viewBinding import io.legato.kazusa.utils.viewbindingdelegate.viewBinding
import io.legato.kazusa.utils.visible import io.legato.kazusa.utils.visible
@@ -91,7 +88,7 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
private var bottomMenuCount = 4 private var bottomMenuCount = 4
private val realPositions = arrayOf(idBookshelf, idExplore, idRss, idMy) private val realPositions = arrayOf(idBookshelf, idExplore, idRss, idMy)
private val adapter by lazy { private val adapter by lazy {
TabFragmentPageAdapter(supportFragmentManager) TabFragmentPageAdapter(this)
} }
private val badge by lazy { private val badge by lazy {
@@ -175,21 +172,16 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
} }
} }
override fun onNavigationItemSelected(item: MenuItem): Boolean = binding.run { override fun onNavigationItemSelected(item: MenuItem): Boolean {
when (item.itemId) { val index = when (item.itemId) {
R.id.menu_bookshelf -> R.id.menu_bookshelf -> 0
viewPagerMain.setCurrentItem(0, false) R.id.menu_discovery -> realPositions.indexOf(idExplore)
R.id.menu_rss -> realPositions.indexOf(idRss)
R.id.menu_discovery -> R.id.menu_my_config -> realPositions.indexOf(idMy)
viewPagerMain.setCurrentItem(realPositions.indexOf(idExplore), false) else -> 0
R.id.menu_rss ->
viewPagerMain.setCurrentItem(realPositions.indexOf(idRss), false)
R.id.menu_my_config ->
viewPagerMain.setCurrentItem(realPositions.indexOf(idMy), false)
} }
return false binding.viewPagerMain.setCurrentItem(index, true)
return true
} }
override fun onNavigationItemReselected(item: MenuItem) { override fun onNavigationItemReselected(item: MenuItem) {
@@ -215,8 +207,9 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
private fun initView() = binding.run { private fun initView() = binding.run {
viewPagerMain.offscreenPageLimit = 3 viewPagerMain.offscreenPageLimit = 3
viewPagerMain.adapter = adapter viewPagerMain.adapter = adapter
viewPagerMain.addOnPageChangeListener(PageChangeCallback()) viewPagerMain.registerOnPageChangeCallback(PageChangeCallback())
window.setNavigationBarColorAuto(themeColor(com.google.android.material.R.attr.colorSurfaceContainer))
//window.setNavigationBarColorAuto(themeColor(com.google.android.material.R.attr.colorSurfaceContainer))
} }
/** /**
@@ -464,45 +457,29 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
return id return id
} }
private inner class PageChangeCallback : ViewPager2.OnPageChangeCallback() {
private inner class PageChangeCallback : ViewPager.SimpleOnPageChangeListener() {
override fun onPageSelected(position: Int) { override fun onPageSelected(position: Int) {
pagePosition = position pagePosition = position
val navView = getNavigationBarView() getNavigationBarView().selectedItemId = when (realPositions[position]) {
navView.menu[realPositions[position]].isChecked = true idBookshelf -> R.id.menu_bookshelf
idExplore -> R.id.menu_discovery
idRss -> R.id.menu_rss
idMy -> R.id.menu_my_config
else -> R.id.menu_bookshelf
}
updateNavigationRailFab(position) updateNavigationRailFab(position)
} }
}
private inner class TabFragmentPageAdapter(fm: FragmentManager) :
FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
private fun getId(position: Int): Int {
return getFragmentId(position)
}
override fun getItemPosition(any: Any): Int {
val position = (any as? MainFragmentInterface)?.position ?: return POSITION_NONE
val fragmentId = getId(position)
if (
(fragmentId == idBookshelf1 && any is BookshelfFragment1) ||
(fragmentId == idBookshelf2 && any is BookshelfFragment2) ||
(fragmentId == idBookshelf3 && any is BookshelfFragment3) ||
(fragmentId == idExplore && any is ExploreFragment) ||
(fragmentId == idRss && any is RssFragment) ||
(fragmentId == idMy && any is MyFragment)
) {
return POSITION_UNCHANGED
}
return POSITION_NONE
} }
override fun getItem(position: Int): Fragment { private inner class TabFragmentPageAdapter(
return when (getId(position)) { activity: FragmentActivity
) : FragmentStateAdapter(activity) {
override fun getItemCount(): Int = bottomMenuCount
override fun createFragment(position: Int): Fragment {
val fragment = when (getFragmentId(position)) {
idBookshelf1 -> BookshelfFragment1(position) idBookshelf1 -> BookshelfFragment1(position)
idBookshelf2 -> BookshelfFragment2(position) idBookshelf2 -> BookshelfFragment2(position)
idBookshelf3 -> BookshelfFragment3(position) idBookshelf3 -> BookshelfFragment3(position)
@@ -510,18 +487,22 @@ class MainActivity : VMBaseActivity<ActivityMainBinding, MainViewModel>(),
idRss -> RssFragment(position) idRss -> RssFragment(position)
else -> MyFragment(position) else -> MyFragment(position)
} }
}
override fun getCount(): Int { fragmentMap[getFragmentId(position)] = fragment
return bottomMenuCount
}
override fun instantiateItem(container: ViewGroup, position: Int): Any {
val fragment = super.instantiateItem(container, position) as Fragment
fragmentMap[getId(position)] = fragment
return fragment return fragment
} }
override fun getItemId(position: Int): Long {
return getFragmentId(position).toLong()
} }
override fun containsItem(itemId: Long): Boolean {
return realPositions.map { getFragmentId(it).toLong() }.contains(itemId)
} }
}
}
@@ -0,0 +1,65 @@
package io.legato.kazusa.ui.widget
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.ViewConfiguration
import android.widget.FrameLayout
import androidx.viewpager2.widget.ViewPager2
import kotlin.math.abs
import androidx.core.view.isNotEmpty
class NestedScrollableHost @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
) : FrameLayout(context, attrs) {
private var touchSlop = 0
private var initialX = 0f
private var initialY = 0f
private val parentViewPager: ViewPager2?
get() {
var v: View? = parent as? View
while (v != null && v !is ViewPager2) {
v = v.parent as? View
}
return v
}
private val child: View?
get() = if (isNotEmpty()) getChildAt(0) else null
init {
touchSlop = ViewConfiguration.get(context).scaledTouchSlop
}
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
handleInterceptTouchEvent(ev)
return super.onInterceptTouchEvent(ev)
}
private fun handleInterceptTouchEvent(e: MotionEvent) {
val parentVp = parentViewPager ?: return
when (e.action) {
MotionEvent.ACTION_DOWN -> {
initialX = e.x
initialY = e.y
parent.requestDisallowInterceptTouchEvent(true)
}
MotionEvent.ACTION_MOVE -> {
val dx = e.x - initialX
val dy = e.y - initialY
val isHorizontal = abs(dx) > abs(dy)
if (isHorizontal) {
val canScroll = child?.canScrollHorizontally(-dx.toInt()) ?: false
parent.requestDisallowInterceptTouchEvent(canScroll)
} else {
parent.requestDisallowInterceptTouchEvent(false)
}
}
}
}
}
+1 -1
View File
@@ -5,7 +5,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<androidx.viewpager.widget.ViewPager <androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager_main" android:id="@+id/view_pager_main"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
@@ -15,6 +15,7 @@
android:stateListAnimator="@null"> android:stateListAnimator="@null">
<com.google.android.material.appbar.CollapsingToolbarLayout <com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/coll_top_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/collapsingToolbarLayoutMediumSize" android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
style="?attr/collapsingToolbarLayoutMediumStyle" style="?attr/collapsingToolbarLayoutMediumStyle"
@@ -42,12 +43,16 @@
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<!-- ViewPager --> <io.legato.kazusa.ui.widget.NestedScrollableHost
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.viewpager2.widget.ViewPager2 <androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager_bookshelf" android:id="@+id/view_pager_bookshelf"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:paddingHorizontal="8dp" android:paddingHorizontal="8dp" />
app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </io.legato.kazusa.ui.widget.NestedScrollableHost>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
@@ -35,12 +35,15 @@
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<!-- ViewPager --> <io.legato.kazusa.ui.widget.NestedScrollableHost
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.viewpager2.widget.ViewPager2 <androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager_bookshelf" android:id="@+id/view_pager_bookshelf"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:paddingHorizontal="8dp" android:paddingHorizontal="8dp" />
app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </io.legato.kazusa.ui.widget.NestedScrollableHost>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
+1 -1
View File
@@ -28,7 +28,7 @@ jsoupxpath = "2.5.3"
coroutines = "1.10.2" coroutines = "1.10.2"
liveeventbus = "1.8.14" liveeventbus = "1.8.14"
markwon = "4.6.2" markwon = "4.6.2"
material = "1.14.0-alpha04" material = "1.14.0-alpha05"
media = "1.7.1" media = "1.7.1"
media3 = "1.8.0" media3 = "1.8.0"
nanoHttpd = "2.3.1" nanoHttpd = "2.3.1"