Fix window insets handling

This commit is contained in:
Koitharu
2025-03-05 16:56:16 +02:00
parent d4a2d97071
commit 7cec7f5359
15 changed files with 181 additions and 20 deletions

View File

@@ -5,6 +5,8 @@ import android.os.Bundle
import android.view.Gravity
import android.view.View
import androidx.annotation.StringRes
import androidx.core.view.ancestors
import androidx.fragment.app.FragmentContainerView
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceScreen
@@ -12,6 +14,7 @@ import androidx.preference.get
import androidx.recyclerview.widget.RecyclerView
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.EntryPointAccessors
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
@@ -49,7 +52,12 @@ abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
val themedContext = (view.parentView ?: view).context
view.setBackgroundColor(themedContext.getThemeColor(android.R.attr.colorBackground))
listView.clipToPadding = false
listView.consumeInsetsAsPadding(Gravity.BOTTOM or Gravity.START or Gravity.END)
val insetsEdges = Gravity.BOTTOM or when {
!resources.getBoolean(R.bool.is_tablet) -> Gravity.FILL_HORIZONTAL
isMaster() -> Gravity.START
else -> Gravity.END
}
listView.consumeInsetsAsPadding(insetsEdges)
}
override fun onResume() {
@@ -91,4 +99,9 @@ abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
}
return -1
}
private fun isMaster(): Boolean {
val container = view?.ancestors?.firstNotNullOfOrNull { it as? FragmentContainerView } ?: return false
return container.id == R.id.container_master
}
}

View File

@@ -1,7 +1,12 @@
package org.koitharu.kotatsu.core.ui
import android.os.Bundle
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import com.google.android.material.appbar.AppBarLayout
@@ -14,6 +19,7 @@ import org.koitharu.kotatsu.main.ui.owners.SnackbarOwner
@AndroidEntryPoint
abstract class FragmentContainerActivity(private val fragmentClass: Class<out Fragment>) :
BaseActivity<ActivityContainerBinding>(),
OnApplyWindowInsetsListener,
AppBarOwner,
SnackbarOwner {
@@ -27,6 +33,7 @@ abstract class FragmentContainerActivity(private val fragmentClass: Class<out Fr
super.onCreate(savedInstanceState)
setContentView(ActivityContainerBinding.inflate(layoutInflater))
supportActionBar?.setDisplayHomeAsUpEnabled(true)
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
val fm = supportFragmentManager
if (fm.findFragmentById(R.id.container) == null) {
fm.commit {
@@ -36,5 +43,15 @@ abstract class FragmentContainerActivity(private val fragmentClass: Class<out Fr
}
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val bars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
viewBinding.appbar.updatePadding(
left = bars.left,
right = bars.right,
top = bars.top,
)
return insets
}
protected open fun getFragmentExtras(): Bundle? = intent.extras
}

View File

@@ -1,13 +1,17 @@
package org.koitharu.kotatsu.download.ui.list
import android.os.Bundle
import android.view.Gravity
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.activity.viewModels
import androidx.appcompat.view.ActionMode
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import coil3.ImageLoader
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
@@ -17,7 +21,6 @@ import org.koitharu.kotatsu.core.ui.list.ListSelectionController
import org.koitharu.kotatsu.core.ui.list.RecyclerScrollKeeper
import org.koitharu.kotatsu.core.ui.util.MenuInvalidator
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.databinding.ActivityDownloadsBinding
@@ -28,6 +31,7 @@ import javax.inject.Inject
@AndroidEntryPoint
class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(),
DownloadItemListener,
OnApplyWindowInsetsListener,
ListSelectionController.Callback {
@Inject
@@ -43,6 +47,7 @@ class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(),
super.onCreate(savedInstanceState)
setContentView(ActivityDownloadsBinding.inflate(layoutInflater))
supportActionBar?.setDisplayHomeAsUpEnabled(true)
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
val downloadsAdapter = DownloadsAdapter(this, coil, this)
val decoration = TypedListSpacingDecoration(this, false)
selectionController = ListSelectionController(
@@ -52,7 +57,6 @@ class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(),
callback = this,
)
with(viewBinding.recyclerView) {
consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
setHasFixedSize(true)
addItemDecoration(decoration)
adapter = downloadsAdapter
@@ -68,6 +72,23 @@ class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(),
viewModel.hasCancellableWorks.observe(this, menuInvalidator)
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val bars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
viewBinding.recyclerView.updatePadding(
left = bars.left,
right = bars.right,
bottom = bars.bottom,
)
viewBinding.appbar.updatePadding(
left = bars.left,
right = bars.right,
top = bars.top,
)
return return WindowInsetsCompat.Builder(insets)
.setInsets(WindowInsetsCompat.Type.systemBars(), Insets.NONE)
.build()
}
override fun onItemClick(item: DownloadItemModel, view: View) {
if (selectionController.onItemClick(item.id.mostSignificantBits)) {
return

View File

@@ -25,6 +25,7 @@ import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.core.view.updatePaddingRelative
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import androidx.fragment.app.commit
@@ -224,9 +225,16 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
barsInsets.start(v)
}
}
viewBinding.bottomNav?.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
bottom = barsInsets.bottom,
)
return viewBinding.navRail?.let { navRail ->
navRail.updateLayoutParams<MarginLayoutParams> {
marginStart = barsInsets.start(v)
topMargin = barsInsets.top
bottomMargin = barsInsets.bottom
}
WindowInsetsCompat.Builder(insets)
.setInsets(WindowInsetsCompat.Type.systemBars(), barsInsets.consumeRelative(v, start = true))

View File

@@ -2,8 +2,15 @@ package org.koitharu.kotatsu.settings
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.activity.viewModels
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePaddingRelative
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentFactory
import androidx.fragment.app.FragmentTransaction
@@ -17,8 +24,10 @@ import org.koitharu.kotatsu.core.model.MangaSource
import org.koitharu.kotatsu.core.nav.AppRouter
import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.util.ext.buildBundle
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.start
import org.koitharu.kotatsu.core.util.ext.textAndVisible
import org.koitharu.kotatsu.databinding.ActivitySettingsBinding
import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
@@ -36,6 +45,7 @@ import org.koitharu.kotatsu.settings.userdata.UserDataSettingsFragment
@AndroidEntryPoint
class SettingsActivity :
BaseActivity<ActivitySettingsBinding>(),
OnApplyWindowInsetsListener,
PreferenceFragmentCompat.OnPreferenceStartFragmentCallback,
AppBarOwner {
@@ -45,14 +55,12 @@ class SettingsActivity :
private val isMasterDetails
get() = viewBinding.containerMaster != null
private var screenPadding = 0
private val viewModel: SettingsSearchViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(ActivitySettingsBinding.inflate(layoutInflater))
screenPadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val fm = supportFragmentManager
val currentFragment = fm.findFragmentById(R.id.container)
@@ -69,6 +77,21 @@ class SettingsActivity :
viewModel.onNavigateToPreference.observeEvent(this, ::navigateToPreference)
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val bars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
val isTablet = viewBinding.containerMaster != null
viewBinding.appbar.updatePaddingRelative(
start = bars.start(v),
top = bars.top,
end = if (isTablet) 0 else bars.end(v),
)
viewBinding.textViewHeader?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
marginEnd = bars.end(v)
topMargin = bars.top
}
return insets
}
override fun onPreferenceStartFragment(
caller: PreferenceFragmentCompat,
pref: Preference,

View File

@@ -1,6 +1,7 @@
package org.koitharu.kotatsu.settings.search
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -11,6 +12,7 @@ import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.core.ui.BaseFragment
import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.databinding.FragmentSearchSuggestionBinding
import org.koitharu.kotatsu.list.ui.adapter.ListItemType
@@ -28,6 +30,7 @@ class SettingsSearchFragment : BaseFragment<FragmentSearchSuggestionBinding>(),
override fun onViewBindingCreated(binding: FragmentSearchSuggestionBinding, savedInstanceState: Bundle?) {
super.onViewBindingCreated(binding, savedInstanceState)
binding.root.consumeInsetsAsPadding(Gravity.FILL_HORIZONTAL or Gravity.BOTTOM)
val adapter = BaseListAdapter<SettingsItem>()
.addDelegate(ListItemType.NAV_ITEM, settingsItemAD(this))
adapter.addListListener(this)

View File

@@ -1,13 +1,17 @@
package org.koitharu.kotatsu.settings.sources.catalog
import android.os.Bundle
import android.view.Gravity
import android.view.Menu
import android.view.MenuItem
import android.view.View
import androidx.activity.viewModels
import androidx.appcompat.widget.PopupMenu
import androidx.appcompat.widget.SearchView
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import coil3.ImageLoader
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.chip.Chip
@@ -23,7 +27,6 @@ import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.ui.widgets.ChipsView
import org.koitharu.kotatsu.core.ui.widgets.ChipsView.ChipModel
import org.koitharu.kotatsu.core.util.LocaleComparator
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding
import org.koitharu.kotatsu.core.util.ext.getDisplayName
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
@@ -37,7 +40,10 @@ import javax.inject.Inject
@AndroidEntryPoint
class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
OnListItemClickListener<SourceCatalogItem.Source>,
AppBarOwner, MenuItem.OnActionExpandListener, ChipsView.OnChipClickListener {
OnApplyWindowInsetsListener,
AppBarOwner,
MenuItem.OnActionExpandListener,
ChipsView.OnChipClickListener {
@Inject
lateinit var coil: ImageLoader
@@ -51,9 +57,9 @@ class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
super.onCreate(savedInstanceState)
setContentView(ActivitySourcesCatalogBinding.inflate(layoutInflater))
supportActionBar?.setDisplayHomeAsUpEnabled(true)
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
val sourcesAdapter = SourcesCatalogAdapter(this, coil, this)
with(viewBinding.recyclerView) {
consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
setHasFixedSize(true)
addItemDecoration(TypedListSpacingDecoration(context, false))
adapter = sourcesAdapter
@@ -71,6 +77,23 @@ class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
addMenuProvider(SourcesCatalogMenuProvider(this, viewModel, this))
}
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val bars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
viewBinding.recyclerView.updatePadding(
left = bars.left,
right = bars.right,
bottom = bars.bottom,
)
viewBinding.appbar.updatePadding(
left = bars.left,
right = bars.right,
top = bars.top,
)
return return WindowInsetsCompat.Builder(insets)
.setInsets(WindowInsetsCompat.Type.systemBars(), Insets.NONE)
.build()
}
override fun onChipClick(chip: Chip, data: Any?) {
when (data) {
is ContentType -> viewModel.setContentType(data, !chip.isChecked)

View File

@@ -4,12 +4,19 @@ import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.view.ViewStub
import android.widget.CompoundButton
import androidx.activity.viewModels
import androidx.appcompat.widget.PopupMenu
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePaddingRelative
import androidx.recyclerview.widget.AsyncListDiffer
import coil3.ImageLoader
import com.google.android.material.chip.Chip
@@ -24,12 +31,14 @@ import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.util.KotatsuColors
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.newImageRequest
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.setTextAndVisible
import org.koitharu.kotatsu.core.util.ext.showOrHide
import org.koitharu.kotatsu.core.util.ext.start
import org.koitharu.kotatsu.databinding.ActivityStatsBinding
import org.koitharu.kotatsu.databinding.ItemEmptyStateBinding
import org.koitharu.kotatsu.list.ui.adapter.ListItemType
@@ -41,10 +50,13 @@ import javax.inject.Inject
@AndroidEntryPoint
class StatsActivity : BaseActivity<ActivityStatsBinding>(),
OnApplyWindowInsetsListener,
OnListItemClickListener<Manga>,
PieChartView.OnSegmentClickListener,
AsyncListDiffer.ListListener<StatsRecord>,
ViewStub.OnInflateListener, View.OnClickListener, CompoundButton.OnCheckedChangeListener {
ViewStub.OnInflateListener,
View.OnClickListener,
CompoundButton.OnCheckedChangeListener {
@Inject
lateinit var coil: ImageLoader
@@ -55,6 +67,7 @@ class StatsActivity : BaseActivity<ActivityStatsBinding>(),
super.onCreate(savedInstanceState)
setContentView(ActivityStatsBinding.inflate(layoutInflater))
supportActionBar?.setDisplayHomeAsUpEnabled(true)
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
val adapter = BaseListAdapter<StatsRecord>()
.addDelegate(ListItemType.FEED, statsAD(this))
.addListListener(this)
@@ -88,6 +101,39 @@ class StatsActivity : BaseActivity<ActivityStatsBinding>(),
}
}
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val bars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
val isTablet = viewBinding.guidelineCenter != null
viewBinding.appbar.updatePaddingRelative(
start = bars.start(v),
top = bars.top,
end = if (isTablet) 0 else bars.end(v),
)
val badgePadding = resources.getDimensionPixelOffset(R.dimen.list_spacing_large)
viewBinding.scrollViewChips.updatePaddingRelative(
start = badgePadding + if (isTablet) 0 else bars.start(v),
end = badgePadding + bars.end(v),
top = if (isTablet) bars.top else 0,
)
viewBinding.recyclerView.updatePaddingRelative(
start = if (isTablet) 0 else bars.start(v),
end = bars.end(v),
bottom = bars.bottom,
)
viewBinding.chart.updateLayoutParams<ViewGroup.MarginLayoutParams> {
val baseMargin = topMargin
bottomMargin = if (isTablet) baseMargin + bars.bottom else baseMargin
marginStart = baseMargin + bars.start(v)
marginEnd = if (isTablet) baseMargin else baseMargin + bars.end(v)
}
return return WindowInsetsCompat.Builder(insets)
.setInsets(WindowInsetsCompat.Type.systemBars(), Insets.NONE)
.build()
}
override fun onClick(v: View) {
when (v.id) {
R.id.chip_period -> showPeriodSelector()

View File

@@ -12,10 +12,14 @@
android:id="@+id/navRail"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:fitsSystemWindows="false"
app:elevation="1dp"
app:headerLayout="@layout/navigation_rail_fab"
app:labelVisibilityMode="labeled"
app:layout_constraintStart_toStartOf="parent" />
app:layout_constraintStart_toStartOf="parent"
app:paddingBottomSystemWindowInsets="false"
app:paddingStartSystemWindowInsets="false"
app:paddingTopSystemWindowInsets="false" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"

View File

@@ -11,7 +11,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:elevation="0dp"
android:fitsSystemWindows="true"
android:fitsSystemWindows="false"
app:elevation="0dp"
app:layout_constraintEnd_toEndOf="@id/container_master"
app:layout_constraintStart_toStartOf="parent"

View File

@@ -28,11 +28,12 @@
<HorizontalScrollView
android:id="@+id/scrollView_chips"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_height="0dp"
android:clipToPadding="false"
android:paddingHorizontal="12dp"
android:scrollIndicators="start"
android:scrollbars="none"
app:layout_constraintBottom_toBottomOf="@id/appbar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/guideline_center"
app:layout_constraintTop_toTopOf="parent">
@@ -40,7 +41,8 @@
<com.google.android.material.chip.ChipGroup
android:id="@+id/layout_chips"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:layout_gravity="center_vertical">
<com.google.android.material.chip.Chip
android:id="@+id/chip_period"

View File

@@ -10,7 +10,7 @@
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
android:fitsSystemWindows="false">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsingToolbarLayout"

View File

@@ -95,6 +95,7 @@
android:id="@+id/bottomNav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom" />
android:layout_gravity="bottom"
android:fitsSystemWindows="false" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -9,7 +9,7 @@
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:fitsSystemWindows="false"
app:liftOnScroll="false">
<com.google.android.material.appbar.MaterialToolbar

View File

@@ -11,7 +11,7 @@
android:id="@+id/appbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:fitsSystemWindows="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">