diff --git a/app/src/main/java/io/legato/kazusa/base/BaseActivity.kt b/app/src/main/java/io/legato/kazusa/base/BaseActivity.kt index f0dd96c53..f8f437a09 100644 --- a/app/src/main/java/io/legato/kazusa/base/BaseActivity.kt +++ b/app/src/main/java/io/legato/kazusa/base/BaseActivity.kt @@ -3,6 +3,7 @@ package io.legato.kazusa.base import android.annotation.SuppressLint import android.content.Context import android.content.res.Configuration +import android.graphics.Color import android.os.Build import android.os.Bundle 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.windowSize 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( @@ -74,7 +79,12 @@ abstract class BaseActivity( AppContextWrapper.applyLocaleAndFont(this) super.onCreate(savedInstanceState) WindowCompat.setDecorFitsSystemWindows(window, false) - enableEdgeToEdge() + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) + enableEdgeToEdge() + else{ + window.setNavigationBarColorAuto(themeColor(com.google.android.material.R.attr.colorSurface)) + setupSystemBar() + } //window.setNavigationBarColorAuto(themeColor(com.google.android.material.R.attr.colorSurface)) //setupSystemBar() setContentView(binding.root) @@ -95,6 +105,20 @@ abstract class BaseActivity( //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) { // super.onConfigurationChanged(newConfig) // //findViewById(R.id.title_bar) diff --git a/app/src/main/java/io/legato/kazusa/ui/main/MainActivity.kt b/app/src/main/java/io/legato/kazusa/ui/main/MainActivity.kt index d986a8422..86a515d16 100644 --- a/app/src/main/java/io/legato/kazusa/ui/main/MainActivity.kt +++ b/app/src/main/java/io/legato/kazusa/ui/main/MainActivity.kt @@ -8,7 +8,6 @@ import android.text.format.DateUtils import android.view.Gravity import android.view.MenuItem import android.view.MotionEvent -import android.view.ViewGroup import android.widget.FrameLayout import android.widget.ImageView import androidx.activity.addCallback @@ -16,10 +15,10 @@ import androidx.activity.viewModels import androidx.core.view.get import androidx.core.view.postDelayed import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentManager -import androidx.fragment.app.FragmentStatePagerAdapter +import androidx.fragment.app.FragmentActivity 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.floatingactionbutton.ExtendedFloatingActionButton 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.hideSoftInput import io.legato.kazusa.utils.observeEvent -import io.legato.kazusa.utils.setNavigationBarColorAuto import io.legato.kazusa.utils.shouldHideSoftInput import io.legato.kazusa.utils.showDialogFragment import io.legato.kazusa.utils.startActivity -import io.legato.kazusa.utils.themeColor import io.legato.kazusa.utils.toastOnUi import io.legato.kazusa.utils.viewbindingdelegate.viewBinding import io.legato.kazusa.utils.visible @@ -91,7 +88,7 @@ class MainActivity : VMBaseActivity(), private var bottomMenuCount = 4 private val realPositions = arrayOf(idBookshelf, idExplore, idRss, idMy) private val adapter by lazy { - TabFragmentPageAdapter(supportFragmentManager) + TabFragmentPageAdapter(this) } private val badge by lazy { @@ -175,21 +172,16 @@ class MainActivity : VMBaseActivity(), } } - override fun onNavigationItemSelected(item: MenuItem): Boolean = binding.run { - when (item.itemId) { - R.id.menu_bookshelf -> - viewPagerMain.setCurrentItem(0, false) - - R.id.menu_discovery -> - viewPagerMain.setCurrentItem(realPositions.indexOf(idExplore), false) - - R.id.menu_rss -> - viewPagerMain.setCurrentItem(realPositions.indexOf(idRss), false) - - R.id.menu_my_config -> - viewPagerMain.setCurrentItem(realPositions.indexOf(idMy), false) + override fun onNavigationItemSelected(item: MenuItem): Boolean { + val index = when (item.itemId) { + R.id.menu_bookshelf -> 0 + R.id.menu_discovery -> realPositions.indexOf(idExplore) + R.id.menu_rss -> realPositions.indexOf(idRss) + R.id.menu_my_config -> realPositions.indexOf(idMy) + else -> 0 } - return false + binding.viewPagerMain.setCurrentItem(index, true) + return true } override fun onNavigationItemReselected(item: MenuItem) { @@ -215,8 +207,9 @@ class MainActivity : VMBaseActivity(), private fun initView() = binding.run { viewPagerMain.offscreenPageLimit = 3 viewPagerMain.adapter = adapter - viewPagerMain.addOnPageChangeListener(PageChangeCallback()) - window.setNavigationBarColorAuto(themeColor(com.google.android.material.R.attr.colorSurfaceContainer)) + viewPagerMain.registerOnPageChangeCallback(PageChangeCallback()) + + //window.setNavigationBarColorAuto(themeColor(com.google.android.material.R.attr.colorSurfaceContainer)) } /** @@ -464,45 +457,29 @@ class MainActivity : VMBaseActivity(), return id } - - private inner class PageChangeCallback : ViewPager.SimpleOnPageChangeListener() { - + private inner class PageChangeCallback : ViewPager2.OnPageChangeCallback() { override fun onPageSelected(position: Int) { pagePosition = position - val navView = getNavigationBarView() - navView.menu[realPositions[position]].isChecked = true + getNavigationBarView().selectedItemId = when (realPositions[position]) { + 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) } - } - private inner class TabFragmentPageAdapter(fm: FragmentManager) : - FragmentStatePagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { - private fun getId(position: Int): Int { - return getFragmentId(position) - } + private inner class TabFragmentPageAdapter( + activity: FragmentActivity + ) : FragmentStateAdapter(activity) { - override fun getItemPosition(any: Any): Int { - val position = (any as? MainFragmentInterface)?.position ?: return POSITION_NONE - val fragmentId = getId(position) + override fun getItemCount(): Int = bottomMenuCount - 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 { - return when (getId(position)) { + override fun createFragment(position: Int): Fragment { + val fragment = when (getFragmentId(position)) { idBookshelf1 -> BookshelfFragment1(position) idBookshelf2 -> BookshelfFragment2(position) idBookshelf3 -> BookshelfFragment3(position) @@ -510,18 +487,22 @@ class MainActivity : VMBaseActivity(), idRss -> RssFragment(position) else -> MyFragment(position) } - } - override fun getCount(): Int { - return bottomMenuCount - } - - override fun instantiateItem(container: ViewGroup, position: Int): Any { - val fragment = super.instantiateItem(container, position) as Fragment - fragmentMap[getId(position)] = fragment + fragmentMap[getFragmentId(position)] = 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) + } } -} \ No newline at end of file + + +} + + diff --git a/app/src/main/java/io/legato/kazusa/ui/widget/NestedScrollableHost.kt b/app/src/main/java/io/legato/kazusa/ui/widget/NestedScrollableHost.kt new file mode 100644 index 000000000..5a9c5ecd2 --- /dev/null +++ b/app/src/main/java/io/legato/kazusa/ui/widget/NestedScrollableHost.kt @@ -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) + } + } + } + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 62f963473..124c094ec 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -5,7 +5,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - - + app:layout_behavior="@string/appbar_scrolling_view_behavior"> + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_bookshelf3.xml b/app/src/main/res/layout/fragment_bookshelf3.xml index f819f5c05..315b6767d 100644 --- a/app/src/main/res/layout/fragment_bookshelf3.xml +++ b/app/src/main/res/layout/fragment_bookshelf3.xml @@ -35,12 +35,15 @@ - - + app:layout_behavior="@string/appbar_scrolling_view_behavior"> + + \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 934c480ba..38696d201 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -28,7 +28,7 @@ jsoupxpath = "2.5.3" coroutines = "1.10.2" liveeventbus = "1.8.14" markwon = "4.6.2" -material = "1.14.0-alpha04" +material = "1.14.0-alpha05" media = "1.7.1" media3 = "1.8.0" nanoHttpd = "2.3.1"