Improve window insets handling

master
Koitharu 1 year ago
parent 7cec7f5359
commit 0981ba771a
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -1,10 +1,11 @@
package org.koitharu.kotatsu.alternatives.ui package org.koitharu.kotatsu.alternatives.ui
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import coil3.ImageLoader import coil3.ImageLoader
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
@ -15,9 +16,10 @@ import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.BaseListAdapter import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityAlternativesBinding import org.koitharu.kotatsu.databinding.ActivityAlternativesBinding
import org.koitharu.kotatsu.list.ui.adapter.ListItemType import org.koitharu.kotatsu.list.ui.adapter.ListItemType
import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration
@ -50,7 +52,6 @@ class AlternativesActivity : BaseActivity<ActivityAlternativesBinding>(),
.addDelegate(ListItemType.FOOTER_LOADING, loadingFooterAD()) .addDelegate(ListItemType.FOOTER_LOADING, loadingFooterAD())
.addDelegate(ListItemType.STATE_LOADING, loadingStateAD()) .addDelegate(ListItemType.STATE_LOADING, loadingStateAD())
with(viewBinding.recyclerView) { with(viewBinding.recyclerView) {
consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
setHasFixedSize(true) setHasFixedSize(true)
addItemDecoration(TypedListSpacingDecoration(context, addHorizontalPadding = false)) addItemDecoration(TypedListSpacingDecoration(context, addHorizontalPadding = false))
adapter = listAdapter adapter = listAdapter
@ -65,6 +66,24 @@ class AlternativesActivity : BaseActivity<ActivityAlternativesBinding>(),
} }
} }
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.recyclerView.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
bottom = barsInsets.bottom,
)
viewBinding.appbar.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
top = barsInsets.top,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onItemClick(item: MangaAlternativeModel, view: View) { override fun onItemClick(item: MangaAlternativeModel, view: View) {
when (view.id) { when (view.id) {
R.id.chip_source -> router.openSearch(item.manga.source, viewModel.manga.title) R.id.chip_source -> router.openSearch(item.manga.source, viewModel.manga.title)

@ -1,7 +1,6 @@
package org.koitharu.kotatsu.bookmarks.ui package org.koitharu.kotatsu.bookmarks.ui
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
@ -10,6 +9,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import coil3.ImageLoader import coil3.ImageLoader
@ -26,10 +26,11 @@ import org.koitharu.kotatsu.core.ui.list.ListSelectionController
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller import org.koitharu.kotatsu.core.ui.list.fastscroll.FastScroller
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.FragmentListSimpleBinding import org.koitharu.kotatsu.databinding.FragmentListSimpleBinding
import org.koitharu.kotatsu.list.ui.GridSpanResolver import org.koitharu.kotatsu.list.ui.GridSpanResolver
import org.koitharu.kotatsu.list.ui.adapter.ListHeaderClickListener import org.koitharu.kotatsu.list.ui.adapter.ListHeaderClickListener
@ -85,7 +86,6 @@ class AllBookmarksFragment :
) )
val spanSizeLookup = SpanSizeLookup() val spanSizeLookup = SpanSizeLookup()
with(binding.recyclerView) { with(binding.recyclerView) {
consumeInsetsAsPadding(Gravity.BOTTOM or Gravity.START or Gravity.END)
setHasFixedSize(true) setHasFixedSize(true)
val spanResolver = GridSpanResolver(resources) val spanResolver = GridSpanResolver(resources)
addItemDecoration(TypedListSpacingDecoration(context, false)) addItemDecoration(TypedListSpacingDecoration(context, false))
@ -107,6 +107,18 @@ class AllBookmarksFragment :
viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView)) viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView))
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val basePadding = resources.getDimensionPixelOffset(R.dimen.list_spacing_normal)
viewBinding?.recyclerView?.setPadding(
barsInsets.left + basePadding,
barsInsets.top + basePadding,
barsInsets.right + basePadding,
barsInsets.bottom + basePadding,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
bookmarksAdapter = null bookmarksAdapter = null

@ -1,10 +1,12 @@
package org.koitharu.kotatsu.browser package org.koitharu.kotatsu.browser
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
@ -16,7 +18,7 @@ import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.core.parser.ParserMangaRepository import org.koitharu.kotatsu.core.parser.ParserMangaRepository
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.util.ext.configureForParser import org.koitharu.kotatsu.core.util.ext.configureForParser
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.databinding.ActivityBrowserBinding import org.koitharu.kotatsu.databinding.ActivityBrowserBinding
import javax.inject.Inject import javax.inject.Inject
import com.google.android.material.R as materialR import com.google.android.material.R as materialR
@ -42,7 +44,6 @@ class BrowserActivity : BaseActivity<ActivityBrowserBinding>(), BrowserCallback
val repository = mangaRepositoryFactory.create(mangaSource) as? ParserMangaRepository val repository = mangaRepositoryFactory.create(mangaSource) as? ParserMangaRepository
val userAgent = repository?.getRequestHeaders()?.get(CommonHeaders.USER_AGENT) val userAgent = repository?.getRequestHeaders()?.get(CommonHeaders.USER_AGENT)
viewBinding.webView.configureForParser(userAgent) viewBinding.webView.configureForParser(userAgent)
viewBinding.webView.consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
viewBinding.webView.webViewClient = BrowserClient(this) viewBinding.webView.webViewClient = BrowserClient(this)
viewBinding.webView.webChromeClient = ProgressChromeClient(viewBinding.progressBar) viewBinding.webView.webChromeClient = ProgressChromeClient(viewBinding.progressBar)
onBackPressedCallback = WebViewBackPressedCallback(viewBinding.webView) onBackPressedCallback = WebViewBackPressedCallback(viewBinding.webView)
@ -62,6 +63,25 @@ class BrowserActivity : BaseActivity<ActivityBrowserBinding>(), BrowserCallback
} }
} }
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val type = WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.ime()
val barsInsets = insets.getInsets(type)
viewBinding.webView.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
bottom = barsInsets.bottom,
)
viewBinding.appbar.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
top = barsInsets.top,
)
return insets.consumeAll(type)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
super.onCreateOptionsMenu(menu) super.onCreateOptionsMenu(menu)
menuInflater.inflate(R.menu.opt_browser, menu) menuInflater.inflate(R.menu.opt_browser, menu)

@ -3,12 +3,14 @@ package org.koitharu.kotatsu.browser.cloudflare
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View
import androidx.activity.result.contract.ActivityResultContract import androidx.activity.result.contract.ActivityResultContract
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -25,7 +27,7 @@ import org.koitharu.kotatsu.core.nav.AppRouter
import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar import org.koitharu.kotatsu.core.network.cookies.MutableCookieJar
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.util.ext.configureForParser import org.koitharu.kotatsu.core.util.ext.configureForParser
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.databinding.ActivityBrowserBinding import org.koitharu.kotatsu.databinding.ActivityBrowserBinding
import org.koitharu.kotatsu.parsers.network.CloudFlareHelper import org.koitharu.kotatsu.parsers.network.CloudFlareHelper
import javax.inject.Inject import javax.inject.Inject
@ -58,7 +60,6 @@ class CloudFlareActivity : BaseActivity<ActivityBrowserBinding>(), CloudFlareCal
} }
cfClient = CloudFlareClient(cookieJar, this, url) cfClient = CloudFlareClient(cookieJar, this, url)
viewBinding.webView.configureForParser(intent?.getStringExtra(AppRouter.KEY_USER_AGENT)) viewBinding.webView.configureForParser(intent?.getStringExtra(AppRouter.KEY_USER_AGENT))
viewBinding.webView.consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
viewBinding.webView.webViewClient = cfClient viewBinding.webView.webViewClient = cfClient
onBackPressedCallback = WebViewBackPressedCallback(viewBinding.webView).also { onBackPressedCallback = WebViewBackPressedCallback(viewBinding.webView).also {
onBackPressedDispatcher.addCallback(it) onBackPressedDispatcher.addCallback(it)
@ -69,6 +70,25 @@ class CloudFlareActivity : BaseActivity<ActivityBrowserBinding>(), CloudFlareCal
} }
} }
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val type = WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.ime()
val barsInsets = insets.getInsets(type)
viewBinding.webView.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
bottom = barsInsets.bottom,
)
viewBinding.appbar.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
top = barsInsets.top,
)
return insets.consumeAll(type)
}
override fun onDestroy() { override fun onDestroy() {
runCatching { runCatching {
viewBinding.webView viewBinding.webView

@ -15,6 +15,8 @@ import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.viewbinding.ViewBinding import androidx.viewbinding.ViewBinding
import dagger.hilt.android.EntryPointAccessors import dagger.hilt.android.EntryPointAccessors
@ -31,6 +33,7 @@ import org.koitharu.kotatsu.main.ui.protect.ScreenshotPolicyHelper
abstract class BaseActivity<B : ViewBinding> : abstract class BaseActivity<B : ViewBinding> :
AppCompatActivity(), AppCompatActivity(),
ExceptionResolver.Host, ExceptionResolver.Host,
OnApplyWindowInsetsListener,
ScreenshotPolicyHelper.ContentContainer { ScreenshotPolicyHelper.ContentContainer {
private var isAmoledTheme = false private var isAmoledTheme = false
@ -78,16 +81,10 @@ abstract class BaseActivity<B : ViewBinding> :
} }
@Deprecated("Use ViewBinding", level = DeprecationLevel.ERROR) @Deprecated("Use ViewBinding", level = DeprecationLevel.ERROR)
override fun setContentView(layoutResID: Int) { override fun setContentView(layoutResID: Int) = throw UnsupportedOperationException()
super.setContentView(layoutResID)
setupToolbar()
}
@Deprecated("Use ViewBinding", level = DeprecationLevel.ERROR) @Deprecated("Use ViewBinding", level = DeprecationLevel.ERROR)
override fun setContentView(view: View?) { override fun setContentView(view: View?) = throw UnsupportedOperationException()
super.setContentView(view)
setupToolbar()
}
override fun getContext() = this override fun getContext() = this
@ -96,6 +93,7 @@ abstract class BaseActivity<B : ViewBinding> :
protected fun setContentView(binding: B) { protected fun setContentView(binding: B) {
this.viewBinding = binding this.viewBinding = binding
super.setContentView(binding.root) super.setContentView(binding.root)
ViewCompat.setOnApplyWindowInsetsListener(binding.root, this)
val toolbar = (binding.root.findViewById<View>(R.id.toolbar) as? Toolbar) val toolbar = (binding.root.findViewById<View>(R.id.toolbar) as? Toolbar)
toolbar?.let(this::setSupportActionBar) toolbar?.let(this::setSupportActionBar)
} }
@ -125,10 +123,6 @@ abstract class BaseActivity<B : ViewBinding> :
return super.onKeyDown(keyCode, event) return super.onKeyDown(keyCode, event)
} }
private fun setupToolbar() {
(findViewById<View>(R.id.toolbar) as? Toolbar)?.let(this::setSupportActionBar)
}
protected fun isDarkAmoledTheme(): Boolean { protected fun isDarkAmoledTheme(): Boolean {
val uiMode = resources.configuration.uiMode val uiMode = resources.configuration.uiMode
val isNight = uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES val isNight = uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES

@ -5,6 +5,8 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.viewbinding.ViewBinding import androidx.viewbinding.ViewBinding
import dagger.hilt.android.EntryPointAccessors import dagger.hilt.android.EntryPointAccessors
@ -12,6 +14,7 @@ import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
import org.koitharu.kotatsu.core.ui.util.ActionModeDelegate import org.koitharu.kotatsu.core.ui.util.ActionModeDelegate
abstract class BaseFragment<B : ViewBinding> : abstract class BaseFragment<B : ViewBinding> :
OnApplyWindowInsetsListener,
Fragment(), Fragment(),
ExceptionResolver.Host { ExceptionResolver.Host {
@ -42,6 +45,7 @@ abstract class BaseFragment<B : ViewBinding> :
final override fun onViewCreated(view: View, savedInstanceState: Bundle?) { final override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
ViewCompat.setOnApplyWindowInsetsListener(view, this)
onViewBindingCreated(requireViewBinding(), savedInstanceState) onViewBindingCreated(requireViewBinding(), savedInstanceState)
} }

@ -2,11 +2,11 @@ package org.koitharu.kotatsu.core.ui
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.View import android.view.View
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.core.view.ancestors import androidx.core.view.OnApplyWindowInsetsListener
import androidx.fragment.app.FragmentContainerView import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceScreen import androidx.preference.PreferenceScreen
@ -18,10 +18,14 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver import org.koitharu.kotatsu.core.exceptions.resolve.ExceptionResolver
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.container
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.getThemeColor import org.koitharu.kotatsu.core.util.ext.getThemeColor
import org.koitharu.kotatsu.core.util.ext.getThemeDrawable import org.koitharu.kotatsu.core.util.ext.getThemeDrawable
import org.koitharu.kotatsu.core.util.ext.parentView import org.koitharu.kotatsu.core.util.ext.parentView
import org.koitharu.kotatsu.core.util.ext.start
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.settings.SettingsActivity import org.koitharu.kotatsu.settings.SettingsActivity
import javax.inject.Inject import javax.inject.Inject
import com.google.android.material.R as materialR import com.google.android.material.R as materialR
@ -29,6 +33,7 @@ import com.google.android.material.R as materialR
@AndroidEntryPoint @AndroidEntryPoint
abstract class BasePreferenceFragment(@StringRes private val titleId: Int) : abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
PreferenceFragmentCompat(), PreferenceFragmentCompat(),
OnApplyWindowInsetsListener,
RecyclerViewOwner, RecyclerViewOwner,
ExceptionResolver.Host { ExceptionResolver.Host {
@ -49,15 +54,23 @@ abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
ViewCompat.setOnApplyWindowInsetsListener(view, this)
val themedContext = (view.parentView ?: view).context val themedContext = (view.parentView ?: view).context
view.setBackgroundColor(themedContext.getThemeColor(android.R.attr.colorBackground)) view.setBackgroundColor(themedContext.getThemeColor(android.R.attr.colorBackground))
listView.clipToPadding = false listView.clipToPadding = false
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 onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val isTablet = !resources.getBoolean(R.bool.is_tablet)
val isMaster = container?.id == R.id.container_master
listView.setPaddingRelative(
if (isTablet && !isMaster) 0 else barsInsets.start(v),
0,
if (isTablet && isMaster) 0 else barsInsets.end(v),
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
} }
override fun onResume() { override fun onResume() {
@ -99,9 +112,4 @@ abstract class BasePreferenceFragment(@StringRes private val titleId: Int) :
} }
return -1 return -1
} }
private fun isMaster(): Boolean {
val container = view?.ancestors?.firstNotNullOfOrNull { it as? FragmentContainerView } ?: return false
return container.id == R.id.container_master
}
} }

@ -3,8 +3,6 @@ package org.koitharu.kotatsu.core.ui
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -12,6 +10,7 @@ import androidx.fragment.app.commit
import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.AppBarLayout
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.util.ext.consumeSystemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityContainerBinding import org.koitharu.kotatsu.databinding.ActivityContainerBinding
import org.koitharu.kotatsu.main.ui.owners.AppBarOwner import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
import org.koitharu.kotatsu.main.ui.owners.SnackbarOwner import org.koitharu.kotatsu.main.ui.owners.SnackbarOwner
@ -19,7 +18,6 @@ import org.koitharu.kotatsu.main.ui.owners.SnackbarOwner
@AndroidEntryPoint @AndroidEntryPoint
abstract class FragmentContainerActivity(private val fragmentClass: Class<out Fragment>) : abstract class FragmentContainerActivity(private val fragmentClass: Class<out Fragment>) :
BaseActivity<ActivityContainerBinding>(), BaseActivity<ActivityContainerBinding>(),
OnApplyWindowInsetsListener,
AppBarOwner, AppBarOwner,
SnackbarOwner { SnackbarOwner {
@ -33,7 +31,6 @@ abstract class FragmentContainerActivity(private val fragmentClass: Class<out Fr
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityContainerBinding.inflate(layoutInflater)) setContentView(ActivityContainerBinding.inflate(layoutInflater))
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
val fm = supportFragmentManager val fm = supportFragmentManager
if (fm.findFragmentById(R.id.container) == null) { if (fm.findFragmentById(R.id.container) == null) {
fm.commit { fm.commit {
@ -50,7 +47,7 @@ abstract class FragmentContainerActivity(private val fragmentClass: Class<out Fr
right = bars.right, right = bars.right,
top = bars.top, top = bars.top,
) )
return insets return insets.consumeSystemBarsInsets(top = true)
} }
protected open fun getFragmentExtras(): Bundle? = intent.extras protected open fun getFragmentExtras(): Bundle? = intent.extras

@ -14,6 +14,8 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDialog import androidx.appcompat.app.AppCompatDialog
import androidx.appcompat.app.AppCompatDialogFragment import androidx.appcompat.app.AppCompatDialogFragment
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
@ -29,7 +31,9 @@ import org.koitharu.kotatsu.core.ui.BaseActivityEntryPoint
import org.koitharu.kotatsu.core.ui.util.ActionModeDelegate import org.koitharu.kotatsu.core.ui.util.ActionModeDelegate
import com.google.android.material.R as materialR import com.google.android.material.R as materialR
abstract class BaseAdaptiveSheet<B : ViewBinding> : AppCompatDialogFragment(), ExceptionResolver.Host { abstract class BaseAdaptiveSheet<B : ViewBinding> : AppCompatDialogFragment(),
OnApplyWindowInsetsListener,
ExceptionResolver.Host {
private var waitingForDismissAllowingStateLoss = false private var waitingForDismissAllowingStateLoss = false
private var isFitToContentsDisabled = false private var isFitToContentsDisabled = false
@ -74,6 +78,7 @@ abstract class BaseAdaptiveSheet<B : ViewBinding> : AppCompatDialogFragment(), E
final override fun onViewCreated(view: View, savedInstanceState: Bundle?) { final override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
ViewCompat.setOnApplyWindowInsetsListener(view, this)
val binding = requireViewBinding() val binding = requireViewBinding()
if (actionModeDelegate == null) { if (actionModeDelegate == null) {
actionModeDelegate = (activity as? BaseActivity<*>)?.actionModeDelegate actionModeDelegate = (activity as? BaseActivity<*>)?.actionModeDelegate

@ -1,51 +0,0 @@
package org.koitharu.kotatsu.core.ui.util
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import androidx.annotation.GravityInt
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updateLayoutParams
import org.koitharu.kotatsu.core.util.ext.consumeRelative
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.start
class InsetsToMarginsListener(
@GravityInt
private val sides: Int,
private val baseMargins: Insets,
) : OnApplyWindowInsetsListener {
private val insetType = WindowInsetsCompat.Type.systemBars()
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(insetType)
v.updateLayoutParams<ViewGroup.MarginLayoutParams> {
if (sides and Gravity.START == Gravity.START) {
marginStart = barsInsets.start(v) + baseMargins.start(v)
}
if (sides and Gravity.TOP == Gravity.TOP) {
topMargin = barsInsets.top + baseMargins.top
}
if (sides and Gravity.END == Gravity.END) {
marginEnd = barsInsets.end(v) + baseMargins.end(v)
}
if (sides and Gravity.BOTTOM == Gravity.BOTTOM) {
bottomMargin = barsInsets.bottom + baseMargins.bottom
}
}
return WindowInsetsCompat.Builder(insets)
.setInsets(
insetType,
barsInsets.consumeRelative(
v,
start = sides and Gravity.START == Gravity.START,
top = sides and Gravity.TOP == Gravity.TOP,
end = sides and Gravity.END == Gravity.END,
bottom = sides and Gravity.BOTTOM == Gravity.BOTTOM,
),
).build()
}
}

@ -1,61 +0,0 @@
package org.koitharu.kotatsu.core.ui.util
import android.view.Gravity
import android.view.View
import androidx.annotation.GravityInt
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.WindowInsetsCompat
import org.koitharu.kotatsu.core.util.ext.consumeRelative
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.start
class InsetsToPaddingListener(
@GravityInt
private val sides: Int,
private val basePaddings: Insets,
) : OnApplyWindowInsetsListener {
private val insetType = WindowInsetsCompat.Type.systemBars()
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(insetType)
v.setPaddingRelative(
/* start = */
if (sides and Gravity.START == Gravity.START) {
barsInsets.start(v) + basePaddings.start(v)
} else {
v.paddingStart
},
/* top = */
if (sides and Gravity.TOP == Gravity.TOP) {
barsInsets.top + basePaddings.top
} else {
v.paddingTop
},
/* end = */
if (sides and Gravity.END == Gravity.END) {
barsInsets.end(v) + basePaddings.end(v)
} else {
v.paddingEnd
},
/* bottom = */
if (sides and Gravity.BOTTOM == Gravity.BOTTOM) {
barsInsets.bottom + basePaddings.bottom
} else {
v.paddingBottom
},
)
return WindowInsetsCompat.Builder(insets)
.setInsets(
insetType,
barsInsets.consumeRelative(
v,
start = sides and Gravity.START == Gravity.START,
top = sides and Gravity.TOP == Gravity.TOP,
end = sides and Gravity.END == Gravity.END,
bottom = sides and Gravity.BOTTOM == Gravity.BOTTOM,
),
).build()
}
}

@ -10,6 +10,8 @@ import android.widget.LinearLayout
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.start
class WindowInsetHolder @JvmOverloads constructor( class WindowInsetHolder @JvmOverloads constructor(
context: Context, context: Context,
@ -24,9 +26,9 @@ class WindowInsetHolder @JvmOverloads constructor(
val barsInsets = WindowInsetsCompat.toWindowInsetsCompat(insets, this) val barsInsets = WindowInsetsCompat.toWindowInsetsCompat(insets, this)
.getInsets(WindowInsetsCompat.Type.systemBars()) .getInsets(WindowInsetsCompat.Type.systemBars())
val gravity = getLayoutGravity() val gravity = getLayoutGravity()
val newWidth = when (gravity and Gravity.HORIZONTAL_GRAVITY_MASK) { val newWidth = when (gravity and Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) {
Gravity.LEFT -> barsInsets.left Gravity.START -> barsInsets.start(this)
Gravity.RIGHT -> barsInsets.right Gravity.END -> barsInsets.end(this)
else -> 0 else -> 0
} }
val newHeight = when (gravity and Gravity.VERTICAL_GRAVITY_MASK) { val newHeight = when (gravity and Gravity.VERTICAL_GRAVITY_MASK) {

@ -2,7 +2,9 @@ package org.koitharu.kotatsu.core.util.ext
import android.os.Bundle import android.os.Bundle
import androidx.core.view.MenuProvider import androidx.core.view.MenuProvider
import androidx.core.view.ancestors
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentContainerView
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.coroutineScope import androidx.lifecycle.coroutineScope
@ -29,3 +31,8 @@ tailrec fun <T> Fragment.findParentCallback(cls: Class<T>): T? {
else -> parent.findParentCallback(cls) else -> parent.findParentCallback(cls)
} }
} }
val Fragment.container: FragmentContainerView?
get() = view?.ancestors?.firstNotNullOfOrNull {
it as? FragmentContainerView // TODO check if direct parent
}

@ -2,6 +2,8 @@ package org.koitharu.kotatsu.core.util.ext
import android.view.View import android.view.View
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsCompat.Type.InsetsType
fun Insets.end(view: View): Int { fun Insets.end(view: View): Int {
return if (view.isRtl) left else right return if (view.isRtl) left else right
@ -11,20 +13,69 @@ fun Insets.start(view: View): Int {
return if (view.isRtl) right else left return if (view.isRtl) right else left
} }
fun Insets.consume( @Deprecated("")
val WindowInsetsCompat.systemBarsInsets: Insets
get() = getInsets(WindowInsetsCompat.Type.systemBars())
@Deprecated("")
fun WindowInsetsCompat.consumeSystemBarsInsets(
left: Boolean = false, left: Boolean = false,
top: Boolean = false, top: Boolean = false,
right: Boolean = false, right: Boolean = false,
bottom: Boolean = false, bottom: Boolean = false,
): Insets = Insets.of( ): WindowInsetsCompat {
/* left = */ if (left) 0 else this.left, val barsInsets = systemBarsInsets
/* top = */ if (top) 0 else this.top, val insets = Insets.of(
/* right = */ if (right) 0 else this.right, if (left) 0 else barsInsets.left,
/* bottom = */ if (bottom) 0 else this.bottom, if (top) 0 else barsInsets.top,
if (right) 0 else barsInsets.right,
if (bottom) 0 else barsInsets.bottom,
) )
return WindowInsetsCompat.Builder(this)
.setInsets(WindowInsetsCompat.Type.systemBars(), insets)
.build()
}
fun WindowInsetsCompat.consume(
v: View,
@InsetsType typeMask: Int,
start: Boolean = false,
top: Boolean = false,
end: Boolean = false,
bottom: Boolean = false,
): WindowInsetsCompat {
val insets = getInsets(typeMask)
val newInsets = Insets.of(
/* left = */ if (if (v.isRtl) end else start) 0 else insets.left,
/* top = */ if (top) 0 else insets.top,
/* right = */ if (if (v.isRtl) start else end) 0 else insets.right,
/* bottom = */ if (bottom) 0 else insets.bottom,
)
return WindowInsetsCompat.Builder(this)
.setInsets(typeMask, newInsets)
.build()
}
fun WindowInsetsCompat.consumeAll(
@InsetsType typeMask: Int,
): WindowInsetsCompat = WindowInsetsCompat.Builder(this)
.setInsets(typeMask, Insets.NONE)
.build()
@Deprecated("")
fun WindowInsetsCompat.consumeSystemBarsInsets(
view: View,
start: Boolean = false,
top: Boolean = false,
end: Boolean = false,
bottom: Boolean = false,
): WindowInsetsCompat = consume(view, WindowInsetsCompat.Type.systemBars(), start, top, end, bottom)
fun Insets.consumeRelative( @Deprecated("")
fun WindowInsetsCompat.consumeAllSystemBarsInsets() = consumeAll(WindowInsetsCompat.Type.systemBars())
@Deprecated("")
fun Insets.consume(
view: View, view: View,
start: Boolean = false, start: Boolean = false,
top: Boolean = false, top: Boolean = false,

@ -6,11 +6,8 @@ import android.view.View
import android.view.View.MeasureSpec import android.view.View.MeasureSpec
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Checkable import android.widget.Checkable
import androidx.annotation.GravityInt
import androidx.appcompat.widget.ActionMenuView import androidx.appcompat.widget.ActionMenuView
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.core.graphics.Insets
import androidx.core.view.ViewCompat
import androidx.core.view.children import androidx.core.view.children
import androidx.core.view.descendants import androidx.core.view.descendants
import androidx.core.view.isVisible import androidx.core.view.isVisible
@ -27,8 +24,6 @@ import com.google.android.material.slider.RangeSlider
import com.google.android.material.slider.Slider import com.google.android.material.slider.Slider
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import org.koitharu.kotatsu.core.ui.OnContextClickListenerCompat import org.koitharu.kotatsu.core.ui.OnContextClickListenerCompat
import org.koitharu.kotatsu.core.ui.util.InsetsToMarginsListener
import org.koitharu.kotatsu.core.ui.util.InsetsToPaddingListener
import kotlin.math.roundToInt import kotlin.math.roundToInt
fun View.hasGlobalPoint(x: Int, y: Int): Boolean { fun View.hasGlobalPoint(x: Int, y: Int): Boolean {
@ -194,19 +189,3 @@ fun Chip.setProgressIcon() {
chipIcon = progressDrawable chipIcon = progressDrawable
progressDrawable.start() progressDrawable.start()
} }
private fun View.marginsSnapshot(): Insets = (layoutParams as? ViewGroup.MarginLayoutParams)?.let { lp ->
Insets.of(lp.leftMargin, lp.topMargin, lp.rightMargin, lp.bottomMargin)
} ?: Insets.NONE
private fun View.paddingSnapshot(): Insets = Insets.of(paddingLeft, paddingTop, paddingRight, paddingBottom)
fun View.consumeInsetsAsPadding(@GravityInt sides: Int) = ViewCompat.setOnApplyWindowInsetsListener(
this,
InsetsToPaddingListener(sides, paddingSnapshot()),
)
fun View.consumeInsetsAsMargins(@GravityInt sides: Int) = ViewCompat.setOnApplyWindowInsetsListener(
this,
InsetsToMarginsListener(sides, marginsSnapshot()),
)

@ -2,7 +2,6 @@ package org.koitharu.kotatsu.details.ui
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.transition.TransitionManager
import android.view.Gravity import android.view.Gravity
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -10,8 +9,6 @@ import android.view.ViewTreeObserver
import android.widget.Toast import android.widget.Toast
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.text.method.LinkMovementMethodCompat import androidx.core.text.method.LinkMovementMethodCompat
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
@ -19,6 +16,7 @@ import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import androidx.core.view.updatePaddingRelative import androidx.core.view.updatePaddingRelative
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import androidx.transition.TransitionManager
import coil3.ImageLoader import coil3.ImageLoader
import coil3.request.ImageRequest import coil3.request.ImageRequest
import coil3.request.SuccessResult import coil3.request.SuccessResult
@ -68,7 +66,7 @@ import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.ui.widgets.ChipsView import org.koitharu.kotatsu.core.ui.widgets.ChipsView
import org.koitharu.kotatsu.core.util.FileSize import org.koitharu.kotatsu.core.util.FileSize
import org.koitharu.kotatsu.core.util.LocaleUtils import org.koitharu.kotatsu.core.util.LocaleUtils
import org.koitharu.kotatsu.core.util.ext.consumeRelative import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.copyToClipboard import org.koitharu.kotatsu.core.util.ext.copyToClipboard
import org.koitharu.kotatsu.core.util.ext.crossfade import org.koitharu.kotatsu.core.util.ext.crossfade
import org.koitharu.kotatsu.core.util.ext.defaultPlaceholders import org.koitharu.kotatsu.core.util.ext.defaultPlaceholders
@ -77,6 +75,7 @@ import org.koitharu.kotatsu.core.util.ext.drawableStart
import org.koitharu.kotatsu.core.util.ext.end import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.enqueueWith import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.getQuantityStringSafe import org.koitharu.kotatsu.core.util.ext.getQuantityStringSafe
import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled
import org.koitharu.kotatsu.core.util.ext.isTextTruncated import org.koitharu.kotatsu.core.util.ext.isTextTruncated
import org.koitharu.kotatsu.core.util.ext.joinToStringWithLimit import org.koitharu.kotatsu.core.util.ext.joinToStringWithLimit
import org.koitharu.kotatsu.core.util.ext.mangaSourceExtra import org.koitharu.kotatsu.core.util.ext.mangaSourceExtra
@ -114,7 +113,7 @@ import com.google.android.material.R as materialR
@AndroidEntryPoint @AndroidEntryPoint
class DetailsActivity : class DetailsActivity :
BaseActivity<ActivityDetailsBinding>(), BaseActivity<ActivityDetailsBinding>(),
View.OnClickListener, OnApplyWindowInsetsListener, View.OnClickListener,
View.OnLayoutChangeListener, ViewTreeObserver.OnDrawListener, View.OnLayoutChangeListener, ViewTreeObserver.OnDrawListener,
ChipsView.OnChipClickListener, OnListItemClickListener<Bookmark>, ChipsView.OnChipClickListener, OnListItemClickListener<Bookmark>,
SwipeRefreshLayout.OnRefreshListener { SwipeRefreshLayout.OnRefreshListener {
@ -162,7 +161,6 @@ class DetailsActivity :
DetailsBottomSheetCallback(viewBinding.swipeRefreshLayout, checkNotNull(viewBinding.navbarDim)), DetailsBottomSheetCallback(viewBinding.swipeRefreshLayout, checkNotNull(viewBinding.navbarDim)),
) )
} }
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
val appRouter = router val appRouter = router
viewModel.mangaDetails.filterNotNull().observe(this, ::onMangaUpdated) viewModel.mangaDetails.filterNotNull().observe(this, ::onMangaUpdated)
@ -244,7 +242,11 @@ class DetailsActivity :
R.id.button_description_more -> { R.id.button_description_more -> {
val tv = viewBinding.textViewDescription val tv = viewBinding.textViewDescription
TransitionManager.beginDelayedTransition(tv.parentView) if (tv.context.isAnimationsEnabled) {
tv.parentView?.let {
TransitionManager.beginDelayedTransition(it)
}
}
if (tv.maxLines in 1 until Integer.MAX_VALUE) { if (tv.maxLines in 1 until Integer.MAX_VALUE) {
tv.maxLines = Integer.MAX_VALUE tv.maxLines = Integer.MAX_VALUE
} else { } else {
@ -319,7 +321,8 @@ class DetailsActivity :
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat { override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) val typeMask = WindowInsetsCompat.Type.systemBars()
val barsInsets = insets.getInsets(typeMask)
if (viewBinding.cardChapters != null) { if (viewBinding.cardChapters != null) {
// landscape // landscape
viewBinding.cardChapters?.updateLayoutParams<ViewGroup.MarginLayoutParams> { viewBinding.cardChapters?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
@ -334,12 +337,11 @@ class DetailsActivity :
viewBinding.appbar.updatePaddingRelative( viewBinding.appbar.updatePaddingRelative(
start = barsInsets.start(v), start = barsInsets.start(v),
) )
return WindowInsetsCompat.Builder(insets) return insets.consume(v, typeMask, bottom = true, end = true)
.setInsets(
WindowInsetsCompat.Type.systemBars(),
barsInsets.consumeRelative(v, end = true, bottom = true),
).build()
} else { } else {
viewBinding.navbarDim?.updateLayoutParams {
height = barsInsets.bottom
}
return insets return insets
} }
} }

@ -3,11 +3,10 @@ package org.koitharu.kotatsu.details.ui
import android.view.View import android.view.View
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import org.koitharu.kotatsu.core.ui.widgets.WindowInsetHolder
class DetailsBottomSheetCallback( class DetailsBottomSheetCallback(
private val swipeRefreshLayout: SwipeRefreshLayout, private val swipeRefreshLayout: SwipeRefreshLayout,
private val navbarDimView: WindowInsetHolder, private val navbarDimView: View,
) : BottomSheetBehavior.BottomSheetCallback() { ) : BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) { override fun onStateChanged(bottomSheet: View, newState: Int) {

@ -5,7 +5,9 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.transition.TransitionManager
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator import com.google.android.material.tabs.TabLayoutMediator
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@ -25,6 +27,7 @@ import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.util.ext.doOnPageChanged import org.koitharu.kotatsu.core.util.ext.doOnPageChanged
import org.koitharu.kotatsu.core.util.ext.findCurrentPagerFragment import org.koitharu.kotatsu.core.util.ext.findCurrentPagerFragment
import org.koitharu.kotatsu.core.util.ext.isAnimationsEnabled
import org.koitharu.kotatsu.core.util.ext.menuView import org.koitharu.kotatsu.core.util.ext.menuView
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
@ -95,12 +98,17 @@ class ChaptersPagesSheet : BaseAdaptiveSheet<SheetChaptersPagesBinding>(),
} }
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat = insets
override fun onStateChanged(sheet: View, newState: Int) { override fun onStateChanged(sheet: View, newState: Int) {
if (newState == STATE_DRAGGING || newState == STATE_SETTLING) { if (newState == STATE_DRAGGING || newState == STATE_SETTLING) {
return return
} }
val binding = viewBinding ?: return val binding = viewBinding ?: return
val isActionModeStarted = actionModeDelegate?.isActionModeStarted == true val isActionModeStarted = actionModeDelegate?.isActionModeStarted == true
if (sheet.context.isAnimationsEnabled) {
TransitionManager.beginDelayedTransition(binding.toolbar)
}
binding.toolbar.menuView?.isVisible = newState == STATE_EXPANDED && !isActionModeStarted binding.toolbar.menuView?.isVisible = newState == STATE_EXPANDED && !isActionModeStarted
binding.splitButtonRead.isVisible = newState != STATE_EXPANDED && !isActionModeStarted binding.splitButtonRead.isVisible = newState != STATE_EXPANDED && !isActionModeStarted
&& viewModel is DetailsViewModel && viewModel is DetailsViewModel

@ -1,7 +1,6 @@
package org.koitharu.kotatsu.details.ui.pager.bookmarks package org.koitharu.kotatsu.details.ui.pager.bookmarks
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
@ -9,6 +8,7 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -29,11 +29,12 @@ import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.util.PagerNestedScrollHelper import org.koitharu.kotatsu.core.ui.util.PagerNestedScrollHelper
import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate
import org.koitharu.kotatsu.core.util.ext.findParentCallback import org.koitharu.kotatsu.core.util.ext.findParentCallback
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.FragmentMangaBookmarksBinding import org.koitharu.kotatsu.databinding.FragmentMangaBookmarksBinding
import org.koitharu.kotatsu.details.ui.pager.ChaptersPagesViewModel import org.koitharu.kotatsu.details.ui.pager.ChaptersPagesViewModel
import org.koitharu.kotatsu.list.ui.GridSpanResolver import org.koitharu.kotatsu.list.ui.GridSpanResolver
@ -94,7 +95,6 @@ class BookmarksFragment : BaseFragment<FragmentMangaBookmarksBinding>(),
headerClickListener = null, headerClickListener = null,
) )
viewModel.gridScale.observe(viewLifecycleOwner, ::onGridScaleChanged) // before rv initialization viewModel.gridScale.observe(viewLifecycleOwner, ::onGridScaleChanged) // before rv initialization
binding.recyclerView.consumeInsetsAsPadding(Gravity.START or Gravity.BOTTOM or Gravity.END)
with(binding.recyclerView) { with(binding.recyclerView) {
addItemDecoration(TypedListSpacingDecoration(context, false)) addItemDecoration(TypedListSpacingDecoration(context, false))
setHasFixedSize(true) setHasFixedSize(true)
@ -116,6 +116,17 @@ class BookmarksFragment : BaseFragment<FragmentMangaBookmarksBinding>(),
viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView)) viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView))
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding?.recyclerView?.setPadding(
barsInsets.left,
barsInsets.top,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onDestroyView() { override fun onDestroyView() {
spanResolver = null spanResolver = null
bookmarksAdapter = null bookmarksAdapter = null

@ -4,8 +4,6 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
@ -49,7 +47,6 @@ import kotlin.math.roundToInt
class ChaptersFragment : class ChaptersFragment :
BaseFragment<FragmentChaptersBinding>(), BaseFragment<FragmentChaptersBinding>(),
OnListItemClickListener<ChapterListItem>, OnListItemClickListener<ChapterListItem>,
OnApplyWindowInsetsListener,
RecyclerViewOwner, RecyclerViewOwner,
ChipsView.OnChipClickListener { ChipsView.OnChipClickListener {
@ -84,7 +81,6 @@ class ChaptersFragment :
LinearLayoutManager(context) LinearLayoutManager(context)
} }
} }
ViewCompat.setOnApplyWindowInsetsListener(binding.root, this)
with(binding.recyclerViewChapters) { with(binding.recyclerViewChapters) {
addItemDecoration(TypedListSpacingDecoration(context, true)) addItemDecoration(TypedListSpacingDecoration(context, true))
checkNotNull(selectionController).attachToRecyclerView(this) checkNotNull(selectionController).attachToRecyclerView(this)

@ -1,7 +1,6 @@
package org.koitharu.kotatsu.details.ui.pager.pages package org.koitharu.kotatsu.details.ui.pager.pages
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
@ -10,6 +9,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.collection.ArraySet import androidx.collection.ArraySet
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
@ -33,7 +33,7 @@ import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.util.PagerNestedScrollHelper import org.koitharu.kotatsu.core.ui.util.PagerNestedScrollHelper
import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.util.RecyclerViewScrollCallback import org.koitharu.kotatsu.core.util.RecyclerViewScrollCallback
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate
import org.koitharu.kotatsu.core.util.ext.findParentCallback import org.koitharu.kotatsu.core.util.ext.findParentCallback
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
@ -118,7 +118,6 @@ class PagesFragment :
clickListener = this@PagesFragment, clickListener = this@PagesFragment,
) )
viewModel.gridScale.observe(viewLifecycleOwner, ::onGridScaleChanged) // before rv initialization viewModel.gridScale.observe(viewLifecycleOwner, ::onGridScaleChanged) // before rv initialization
binding.recyclerView.consumeInsetsAsPadding(Gravity.START or Gravity.BOTTOM or Gravity.END)
with(binding.recyclerView) { with(binding.recyclerView) {
addItemDecoration(TypedListSpacingDecoration(context, false)) addItemDecoration(TypedListSpacingDecoration(context, false))
checkNotNull(selectionController).attachToRecyclerView(this) checkNotNull(selectionController).attachToRecyclerView(this)
@ -150,6 +149,18 @@ class PagesFragment :
super.onDestroyView() super.onDestroyView()
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeBask = WindowInsetsCompat.Type.systemBars()
val barsInsets = insets.getInsets(typeBask)
viewBinding?.recyclerView?.setPadding(
barsInsets.left,
barsInsets.top,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAll(typeBask)
}
override fun onItemClick(item: PageThumbnail, view: View) { override fun onItemClick(item: PageThumbnail, view: View) {
if (selectionController?.onItemClick(item.page.id) == true) { if (selectionController?.onItemClick(item.page.id) == true) {
return return

@ -10,6 +10,8 @@ import android.widget.RatingBar
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.text.method.LinkMovementMethodCompat import androidx.core.text.method.LinkMovementMethodCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import coil3.ImageLoader import coil3.ImageLoader
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
@ -18,6 +20,7 @@ import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.nav.AppRouter import org.koitharu.kotatsu.core.nav.AppRouter
import org.koitharu.kotatsu.core.nav.router import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.defaultPlaceholders import org.koitharu.kotatsu.core.util.ext.defaultPlaceholders
import org.koitharu.kotatsu.core.util.ext.enqueueWith import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
@ -81,6 +84,15 @@ class ScrobblingInfoSheet :
menu = null menu = null
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
viewBinding?.root?.updatePadding(
bottom = insets.getInsets(typeMask).bottom,
)
return insets.consume(v, typeMask, bottom = true)
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
viewModel.updateScrobbling( viewModel.updateScrobbling(
index = scrobblerIndex, index = scrobblerIndex,

@ -8,8 +8,6 @@ import android.view.View
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import coil3.ImageLoader import coil3.ImageLoader
@ -31,7 +29,6 @@ import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(), class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(),
DownloadItemListener, DownloadItemListener,
OnApplyWindowInsetsListener,
ListSelectionController.Callback { ListSelectionController.Callback {
@Inject @Inject
@ -47,7 +44,6 @@ class DownloadsActivity : BaseActivity<ActivityDownloadsBinding>(),
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityDownloadsBinding.inflate(layoutInflater)) setContentView(ActivityDownloadsBinding.inflate(layoutInflater))
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
val downloadsAdapter = DownloadsAdapter(this, coil, this) val downloadsAdapter = DownloadsAdapter(this, coil, this)
val decoration = TypedListSpacingDecoration(this, false) val decoration = TypedListSpacingDecoration(this, false)
selectionController = ListSelectionController( selectionController = ListSelectionController(

@ -5,7 +5,6 @@ import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
@ -13,6 +12,7 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@ -32,10 +32,11 @@ import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.ui.util.SpanSizeResolver import org.koitharu.kotatsu.core.ui.util.SpanSizeResolver
import org.koitharu.kotatsu.core.util.ext.addMenuProvider import org.koitharu.kotatsu.core.util.ext.addMenuProvider
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.FragmentExploreBinding import org.koitharu.kotatsu.databinding.FragmentExploreBinding
import org.koitharu.kotatsu.explore.ui.adapter.ExploreAdapter import org.koitharu.kotatsu.explore.ui.adapter.ExploreAdapter
import org.koitharu.kotatsu.explore.ui.adapter.ExploreListEventListener import org.koitharu.kotatsu.explore.ui.adapter.ExploreListEventListener
@ -79,7 +80,6 @@ class ExploreFragment :
callback = this, callback = this,
) )
with(binding.recyclerView) { with(binding.recyclerView) {
consumeInsetsAsPadding(Gravity.BOTTOM or Gravity.START or Gravity.END)
adapter = exploreAdapter adapter = exploreAdapter
setHasFixedSize(true) setHasFixedSize(true)
SpanSizeResolver(this, resources.getDimensionPixelSize(R.dimen.explore_grid_width)).attach() SpanSizeResolver(this, resources.getDimensionPixelSize(R.dimen.explore_grid_width)).attach()
@ -97,6 +97,18 @@ class ExploreFragment :
} }
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val basePadding = v.resources.getDimensionPixelOffset(R.dimen.list_spacing_normal)
viewBinding?.recyclerView?.setPadding(
/* left = */ barsInsets.left + basePadding,
/* top = */ basePadding,
/* right = */ barsInsets.right + basePadding,
/* bottom = */ barsInsets.bottom + basePadding,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
sourceSelectionController = null sourceSelectionController = null

@ -1,10 +1,13 @@
package org.koitharu.kotatsu.favourites.ui.categories package org.koitharu.kotatsu.favourites.ui.categories
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.View import android.view.View
import android.view.ViewGroup.MarginLayoutParams
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import coil3.ImageLoader import coil3.ImageLoader
@ -15,9 +18,11 @@ import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.nav.router import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.list.ListSelectionController import org.koitharu.kotatsu.core.ui.list.ListSelectionController
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityCategoriesBinding import org.koitharu.kotatsu.databinding.ActivityCategoriesBinding
import org.koitharu.kotatsu.favourites.ui.categories.adapter.CategoriesAdapter import org.koitharu.kotatsu.favourites.ui.categories.adapter.CategoriesAdapter
import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener
@ -53,7 +58,6 @@ class FavouriteCategoriesActivity :
callback = CategoriesSelectionCallback(viewBinding.recyclerView, viewModel), callback = CategoriesSelectionCallback(viewBinding.recyclerView, viewModel),
) )
selectionController.attachToRecyclerView(viewBinding.recyclerView) selectionController.attachToRecyclerView(viewBinding.recyclerView)
viewBinding.recyclerView.consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
viewBinding.recyclerView.setHasFixedSize(true) viewBinding.recyclerView.setHasFixedSize(true)
viewBinding.recyclerView.adapter = adapter viewBinding.recyclerView.adapter = adapter
viewBinding.recyclerView.addItemDecoration(TypedListSpacingDecoration(this, false)) viewBinding.recyclerView.addItemDecoration(TypedListSpacingDecoration(this, false))
@ -67,6 +71,28 @@ class FavouriteCategoriesActivity :
viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null)) viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null))
} }
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.recyclerView.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
bottom = barsInsets.bottom,
)
viewBinding.appbar.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
top = barsInsets.top,
)
viewBinding.fabAdd.updateLayoutParams<MarginLayoutParams> {
marginEnd = topMargin + barsInsets.end(v)
bottomMargin = topMargin + barsInsets.bottom
}
return insets.consumeAllSystemBarsInsets()
}
override fun onClick(v: View) { override fun onClick(v: View) {
when (v.id) { when (v.id) {
R.id.fab_add -> router.openFavoriteCategoryCreate() R.id.fab_add -> router.openFavoriteCategoryCreate()

@ -8,18 +8,21 @@ import android.widget.AdapterView
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.Filter import android.widget.Filter
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.getSerializableCompat import org.koitharu.kotatsu.core.util.ext.getSerializableCompat
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.setChecked import org.koitharu.kotatsu.core.util.ext.setChecked
import org.koitharu.kotatsu.core.util.ext.sortedByOrdinal import org.koitharu.kotatsu.core.util.ext.sortedByOrdinal
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityCategoryEditBinding import org.koitharu.kotatsu.databinding.ActivityCategoryEditBinding
import org.koitharu.kotatsu.list.domain.ListSortOrder import org.koitharu.kotatsu.list.domain.ListSortOrder
import com.google.android.material.R as materialR import com.google.android.material.R as materialR
@ -56,6 +59,20 @@ class FavouritesCategoryEditActivity :
} }
} }
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.root.setPadding(
barsInsets.left,
barsInsets.top,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
outState.putSerializable(KEY_SORT_ORDER, selectedSortOrder) outState.putSerializable(KEY_SORT_ORDER, selectedSortOrder)

@ -6,6 +6,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.ViewStub import android.view.ViewStub
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -77,6 +78,8 @@ class FavouritesContainerFragment : BaseFragment<FragmentFavouritesContainerBind
super.onDestroyView() super.onDestroyView()
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat = insets
override fun onActionModeStarted(mode: ActionMode) { override fun onActionModeStarted(mode: ActionMode) {
viewBinding?.run { viewBinding?.run {
pager.isUserInputEnabled = false pager.isUserInputEnabled = false

@ -2,7 +2,9 @@ package org.koitharu.kotatsu.filter.ui
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@ -47,6 +49,8 @@ class FilterHeaderFragment : BaseFragment<FragmentFilterHeaderBinding>(), ChipsV
.observe(viewLifecycleOwner, ::onDataChanged) .observe(viewLifecycleOwner, ::onDataChanged)
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat = insets
override fun onChipClick(chip: Chip, data: Any?) { override fun onChipClick(chip: Chip, data: Any?) {
when (data) { when (data) {
is MangaTag -> filter.toggleTag(data, !chip.isChecked) is MangaTag -> filter.toggleTag(data, !chip.isChecked)

@ -7,6 +7,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.AdapterView import android.widget.AdapterView
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
@ -18,6 +19,7 @@ import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.model.titleRes import org.koitharu.kotatsu.core.ui.model.titleRes
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.ui.widgets.ChipsView import org.koitharu.kotatsu.core.ui.widgets.ChipsView
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.getDisplayName import org.koitharu.kotatsu.core.util.ext.getDisplayName
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
@ -92,6 +94,14 @@ class FilterSheetFragment : BaseAdaptiveSheet<SheetFilterBinding>(),
} }
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
viewBinding?.scrollView?.updatePadding(
bottom = insets.getInsets(typeMask).bottom,
)
return insets.consume(v, typeMask, bottom = true)
}
override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) { override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
val filter = requireFilter() val filter = requireFilter()
when (parent.id) { when (parent.id) {

@ -8,6 +8,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import android.widget.TextView import android.widget.TextView
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.lifecycle.withCreationCallback import dagger.hilt.android.lifecycle.withCreationCallback
@ -17,6 +18,7 @@ import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetBehavior
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetCallback import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetCallback
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.databinding.SheetTagsBinding import org.koitharu.kotatsu.databinding.SheetTagsBinding
import org.koitharu.kotatsu.filter.ui.FilterCoordinator import org.koitharu.kotatsu.filter.ui.FilterCoordinator
@ -59,6 +61,18 @@ class TagsCatalogSheet : BaseAdaptiveSheet<SheetTagsBinding>(),
disableFitToContents() disableFitToContents()
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeBask = WindowInsetsCompat.Type.systemBars()
val barsInsets = insets.getInsets(typeBask)
viewBinding?.recyclerView?.setPadding(
barsInsets.left,
barsInsets.top,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAll(typeBask)
}
override fun onItemClick(item: TagCatalogItem, view: View) { override fun onItemClick(item: TagCatalogItem, view: View) {
viewModel.handleTagClick(item.tag, item.isChecked) viewModel.handleTagClick(item.tag, item.isChecked)
} }

@ -7,8 +7,6 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
@ -33,6 +31,7 @@ import org.koitharu.kotatsu.core.nav.AppRouter
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.PopupMenuMediator import org.koitharu.kotatsu.core.ui.util.PopupMenuMediator
import org.koitharu.kotatsu.core.util.ShareHelper import org.koitharu.kotatsu.core.util.ShareHelper
import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.core.util.ext.end import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.enqueueWith import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.getDisplayIcon import org.koitharu.kotatsu.core.util.ext.getDisplayIcon
@ -50,7 +49,6 @@ import com.google.android.material.R as materialR
@AndroidEntryPoint @AndroidEntryPoint
class ImageActivity : BaseActivity<ActivityImageBinding>(), class ImageActivity : BaseActivity<ActivityImageBinding>(),
ImageRequest.Listener, ImageRequest.Listener,
OnApplyWindowInsetsListener,
View.OnClickListener { View.OnClickListener {
@Inject @Inject
@ -63,7 +61,6 @@ class ImageActivity : BaseActivity<ActivityImageBinding>(),
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityImageBinding.inflate(layoutInflater)) setContentView(ActivityImageBinding.inflate(layoutInflater))
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
viewBinding.buttonBack.setOnClickListener(this) viewBinding.buttonBack.setOnClickListener(this)
viewBinding.buttonMenu.setOnClickListener(this) viewBinding.buttonMenu.setOnClickListener(this)
val imageUrl = requireNotNull(intent.data) val imageUrl = requireNotNull(intent.data)
@ -111,16 +108,18 @@ class ImageActivity : BaseActivity<ActivityImageBinding>(),
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat { override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) val typeMask = WindowInsetsCompat.Type.systemBars()
val barsInsets = insets.getInsets(typeMask)
val baseMargin = v.resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.buttonMenu.updateLayoutParams<ViewGroup.MarginLayoutParams> { viewBinding.buttonMenu.updateLayoutParams<ViewGroup.MarginLayoutParams> {
marginEnd = barsInsets.end(v) marginEnd = barsInsets.end(v) + baseMargin
topMargin = barsInsets.top topMargin = barsInsets.top + baseMargin
} }
viewBinding.buttonBack.updateLayoutParams<ViewGroup.MarginLayoutParams> { viewBinding.buttonBack.updateLayoutParams<ViewGroup.MarginLayoutParams> {
marginStart = barsInsets.start(v) marginStart = barsInsets.start(v) + baseMargin
topMargin = barsInsets.top topMargin = barsInsets.top + baseMargin
} }
return insets return insets.consumeAll(typeMask)
} }
private fun loadImage(url: Uri?) { private fun loadImage(url: Uri?) {

@ -1,7 +1,6 @@
package org.koitharu.kotatsu.list.ui package org.koitharu.kotatsu.list.ui
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
@ -11,6 +10,7 @@ import android.view.ViewGroup
import androidx.annotation.CallSuper import androidx.annotation.CallSuper
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.collection.ArraySet import androidx.collection.ArraySet
import androidx.core.view.WindowInsetsCompat
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
@ -37,7 +37,7 @@ import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.ui.widgets.TipView import org.koitharu.kotatsu.core.ui.widgets.TipView
import org.koitharu.kotatsu.core.util.ShareHelper import org.koitharu.kotatsu.core.util.ShareHelper
import org.koitharu.kotatsu.core.util.ext.addMenuProvider import org.koitharu.kotatsu.core.util.ext.addMenuProvider
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
@ -110,7 +110,6 @@ abstract class MangaListFragment :
) )
paginationListener = PaginationScrollListener(4, this) paginationListener = PaginationScrollListener(4, this)
with(binding.recyclerView) { with(binding.recyclerView) {
consumeInsetsAsPadding(Gravity.START or Gravity.BOTTOM or Gravity.END)
setHasFixedSize(true) setHasFixedSize(true)
adapter = listAdapter adapter = listAdapter
checkNotNull(selectionController).attachToRecyclerView(this) checkNotNull(selectionController).attachToRecyclerView(this)
@ -132,6 +131,19 @@ abstract class MangaListFragment :
viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView)) viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.recyclerView))
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
val barsInsets = insets.getInsets(typeMask)
val basePadding = v.resources.getDimensionPixelOffset(R.dimen.list_spacing_normal)
viewBinding?.recyclerView?.setPadding(
left = barsInsets.left + basePadding,
top = basePadding,
right = barsInsets.right + basePadding,
bottom = barsInsets.bottom + basePadding,
)
return insets.consumeAll(typeMask)
}
override fun onDestroyView() { override fun onDestroyView() {
listAdapter = null listAdapter = null
paginationListener = null paginationListener = null

@ -7,7 +7,9 @@ import android.view.ViewGroup
import android.widget.AdapterView import android.widget.AdapterView
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.CompoundButton import android.widget.CompoundButton
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import com.google.android.material.button.MaterialButtonToggleGroup import com.google.android.material.button.MaterialButtonToggleGroup
import com.google.android.material.slider.Slider import com.google.android.material.slider.Slider
@ -15,6 +17,7 @@ import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.prefs.ListMode import org.koitharu.kotatsu.core.prefs.ListMode
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.setValueRounded import org.koitharu.kotatsu.core.util.ext.setValueRounded
import org.koitharu.kotatsu.core.util.progress.IntPercentLabelFormatter import org.koitharu.kotatsu.core.util.progress.IntPercentLabelFormatter
import org.koitharu.kotatsu.databinding.SheetListModeBinding import org.koitharu.kotatsu.databinding.SheetListModeBinding
@ -73,6 +76,14 @@ class ListConfigBottomSheet :
} }
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
viewBinding?.scrollView?.updatePadding(
bottom = insets.getInsets(typeMask).bottom,
)
return insets.consume(v, typeMask, bottom = true)
}
override fun onButtonChecked(group: MaterialButtonToggleGroup?, checkedId: Int, isChecked: Boolean) { override fun onButtonChecked(group: MaterialButtonToggleGroup?, checkedId: Int, isChecked: Boolean) {
if (!isChecked) { if (!isChecked) {
return return

@ -6,6 +6,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import androidx.core.text.method.LinkMovementMethodCompat import androidx.core.text.method.LinkMovementMethodCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import coil3.ImageLoader import coil3.ImageLoader
@ -68,6 +69,8 @@ class PreviewFragment : BaseFragment<FragmentPreviewBinding>(), View.OnClickList
viewModel.description.observe(viewLifecycleOwner, ::onDescriptionChanged) viewModel.description.observe(viewLifecycleOwner, ::onDescriptionChanged)
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat = insets
override fun onClick(v: View) { override fun onClick(v: View) {
val manga = viewModel.manga.value val manga = viewModel.manga.value
when (v.id) { when (v.id) {

@ -15,9 +15,7 @@ import androidx.appcompat.view.ActionMode
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.SoftwareKeyboardControllerCompat import androidx.core.view.SoftwareKeyboardControllerCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.children import androidx.core.view.children
import androidx.core.view.inputmethod.EditorInfoCompat import androidx.core.view.inputmethod.EditorInfoCompat
@ -25,7 +23,6 @@ import androidx.core.view.isInvisible
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import androidx.core.view.updatePaddingRelative
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction import androidx.fragment.app.FragmentTransaction
import androidx.fragment.app.commit import androidx.fragment.app.commit
@ -53,7 +50,7 @@ import org.koitharu.kotatsu.core.ui.util.FadingAppbarMediator
import org.koitharu.kotatsu.core.ui.util.MenuInvalidator import org.koitharu.kotatsu.core.ui.util.MenuInvalidator
import org.koitharu.kotatsu.core.ui.util.OptionsMenuBadgeHelper import org.koitharu.kotatsu.core.ui.util.OptionsMenuBadgeHelper
import org.koitharu.kotatsu.core.ui.widgets.SlidingBottomNavigationView import org.koitharu.kotatsu.core.ui.widgets.SlidingBottomNavigationView
import org.koitharu.kotatsu.core.util.ext.consumeRelative import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.end import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
@ -84,7 +81,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
View.OnClickListener, View.OnClickListener,
View.OnFocusChangeListener, View.OnFocusChangeListener,
SearchSuggestionListener, SearchSuggestionListener,
OnApplyWindowInsetsListener,
MainNavigationDelegate.OnFragmentChangedListener, MainNavigationDelegate.OnFragmentChangedListener,
View.OnLayoutChangeListener { View.OnLayoutChangeListener {
@ -107,7 +103,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityMainBinding.inflate(layoutInflater)) setContentView(ActivityMainBinding.inflate(layoutInflater))
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
with(viewBinding.searchView) { with(viewBinding.searchView) {
onFocusChangeListener = this@MainActivity onFocusChangeListener = this@MainActivity
@ -216,7 +211,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat { override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) val typeMask = WindowInsetsCompat.Type.systemBars()
val barsInsets = insets.getInsets(typeMask)
viewBinding.toolbarCard.updateLayoutParams<MarginLayoutParams> { viewBinding.toolbarCard.updateLayoutParams<MarginLayoutParams> {
marginEnd = barsInsets.end(v) marginEnd = barsInsets.end(v)
marginStart = if (viewBinding.navRail != null) { marginStart = if (viewBinding.navRail != null) {
@ -230,16 +226,12 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
right = barsInsets.right, right = barsInsets.right,
bottom = barsInsets.bottom, bottom = barsInsets.bottom,
) )
return viewBinding.navRail?.let { navRail -> viewBinding.navRail?.updateLayoutParams<MarginLayoutParams> {
navRail.updateLayoutParams<MarginLayoutParams> {
marginStart = barsInsets.start(v) marginStart = barsInsets.start(v)
topMargin = barsInsets.top topMargin = barsInsets.top
bottomMargin = barsInsets.bottom bottomMargin = barsInsets.bottom
} }
WindowInsetsCompat.Builder(insets) return insets.consume(v, typeMask, start = viewBinding.navRail != null)
.setInsets(WindowInsetsCompat.Type.systemBars(), barsInsets.consumeRelative(v, start = true))
.build()
} ?: insets
} }
override fun onLayoutChange( override fun onLayoutChange(

@ -58,13 +58,16 @@ class MainNavigationDelegate(
} }
override fun onNavigationItemSelected(item: MenuItem): Boolean { override fun onNavigationItemSelected(item: MenuItem): Boolean {
return onNavigationItemSelected(item.itemId) return if (onNavigationItemSelected(item.itemId)) {
item.isChecked = true
true
} else {
false
}
} }
override fun onNavigationItemReselected(item: MenuItem) { override fun onNavigationItemReselected(item: MenuItem) {
val fragment = fragmentManager.findFragmentByTag(TAG_PRIMARY) onNavigationItemReselected()
val recyclerView = (fragment as? RecyclerViewOwner)?.recyclerView ?: return
recyclerView.smoothScrollToTop()
} }
override fun handleOnBackPressed() { override fun handleOnBackPressed() {
@ -137,8 +140,7 @@ class MainNavigationDelegate(
} }
private fun onNavigationItemSelected(@IdRes itemId: Int): Boolean { private fun onNavigationItemSelected(@IdRes itemId: Int): Boolean {
return setPrimaryFragment( val newFragment = when (itemId) {
when (itemId) {
R.id.nav_history -> HistoryListFragment::class.java R.id.nav_history -> HistoryListFragment::class.java
R.id.nav_favorites -> FavouritesContainerFragment::class.java R.id.nav_favorites -> FavouritesContainerFragment::class.java
R.id.nav_explore -> ExploreFragment::class.java R.id.nav_explore -> ExploreFragment::class.java
@ -148,8 +150,12 @@ class MainNavigationDelegate(
R.id.nav_bookmarks -> AllBookmarksFragment::class.java R.id.nav_bookmarks -> AllBookmarksFragment::class.java
R.id.nav_updated -> UpdatesFragment::class.java R.id.nav_updated -> UpdatesFragment::class.java
else -> return false else -> return false
}, }
) if (!setPrimaryFragment(newFragment)) {
// probably already selected
onNavigationItemReselected()
}
return true
} }
private fun getItemId(fragment: Fragment) = when (fragment) { private fun getItemId(fragment: Fragment) = when (fragment) {
@ -178,6 +184,11 @@ class MainNavigationDelegate(
return true return true
} }
private fun onNavigationItemReselected() {
val recyclerView = (primaryFragment as? RecyclerViewOwner)?.recyclerView ?: return
recyclerView.smoothScrollToTop()
}
private fun onFragmentChanged(fragment: Fragment, fromUser: Boolean) { private fun onFragmentChanged(fragment: Fragment, fromUser: Boolean) {
isEnabled = getItemId(fragment) != firstItem()?.itemId isEnabled = getItemId(fragment) != firstItem()?.itemId
listeners.forEach { it.onFragmentChanged(fragment, fromUser) } listeners.forEach { it.onFragmentChanged(fragment, fromUser) }

@ -4,7 +4,6 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.view.Gravity
import android.view.KeyEvent import android.view.KeyEvent
import android.view.View import android.view.View
import android.view.WindowManager import android.view.WindowManager
@ -16,16 +15,18 @@ import androidx.biometric.BiometricManager.Authenticators.BIOMETRIC_WEAK
import androidx.biometric.BiometricManager.BIOMETRIC_SUCCESS import androidx.biometric.BiometricManager.BIOMETRIC_SUCCESS
import androidx.biometric.BiometricPrompt import androidx.biometric.BiometricPrompt
import androidx.biometric.BiometricPrompt.AuthenticationCallback import androidx.biometric.BiometricPrompt.AuthenticationCallback
import androidx.core.view.WindowInsetsCompat
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityProtectBinding import org.koitharu.kotatsu.databinding.ActivityProtectBinding
import com.google.android.material.R as materialR import com.google.android.material.R as materialR
@ -43,7 +44,6 @@ class ProtectActivity :
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE) window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
setContentView(ActivityProtectBinding.inflate(layoutInflater)) setContentView(ActivityProtectBinding.inflate(layoutInflater))
viewBinding.root.consumeInsetsAsPadding(Gravity.FILL)
viewBinding.editPassword.setOnEditorActionListener(this) viewBinding.editPassword.setOnEditorActionListener(this)
viewBinding.editPassword.addTextChangedListener(this) viewBinding.editPassword.addTextChangedListener(this)
viewBinding.buttonNext.setOnClickListener(this) viewBinding.buttonNext.setOnClickListener(this)
@ -64,6 +64,18 @@ class ProtectActivity :
} }
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.root.setPadding(
barsInsets.left + basePadding,
barsInsets.top + basePadding,
barsInsets.right + basePadding,
barsInsets.bottom + basePadding,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
canUseBiometric = useFingerprint() canUseBiometric = useFingerprint()

@ -8,7 +8,9 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.activity.result.ActivityResultCallback import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
@ -18,6 +20,7 @@ import org.koitharu.kotatsu.core.model.titleResId
import org.koitharu.kotatsu.core.nav.router import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.ui.widgets.ChipsView import org.koitharu.kotatsu.core.ui.widgets.ChipsView
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.getDisplayName import org.koitharu.kotatsu.core.util.ext.getDisplayName
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.tryLaunch import org.koitharu.kotatsu.core.util.ext.tryLaunch
@ -53,6 +56,14 @@ class WelcomeSheet : BaseAdaptiveSheet<SheetWelcomeBinding>(), ChipsView.OnChipC
viewModel.types.observe(viewLifecycleOwner, ::onTypesChanged) viewModel.types.observe(viewLifecycleOwner, ::onTypesChanged)
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
viewBinding?.scrollView?.updatePadding(
bottom = insets.getInsets(typeMask).bottom,
)
return insets.consume(v, typeMask, bottom = true)
}
override fun onChipClick(chip: Chip, data: Any?) { override fun onChipClick(chip: Chip, data: Any?) {
when (data) { when (data) {
is ContentType -> viewModel.setTypeChecked(data, !chip.isChecked) is ContentType -> viewModel.setTypeChecked(data, !chip.isChecked)

@ -2,10 +2,6 @@ package org.koitharu.kotatsu.reader.ui
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.transition.Fade
import android.transition.Slide
import android.transition.TransitionManager
import android.transition.TransitionSet
import android.view.Gravity import android.view.Gravity
import android.view.KeyEvent import android.view.KeyEvent
import android.view.MotionEvent import android.view.MotionEvent
@ -14,8 +10,6 @@ import android.view.ViewGroup
import android.view.WindowManager import android.view.WindowManager
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
@ -23,6 +17,10 @@ import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.transition.Fade
import androidx.transition.Slide
import androidx.transition.TransitionManager
import androidx.transition.TransitionSet
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -63,7 +61,6 @@ class ReaderActivity :
TapGridDispatcher.OnGridTouchListener, TapGridDispatcher.OnGridTouchListener,
ReaderConfigSheet.Callback, ReaderConfigSheet.Callback,
ReaderControlDelegate.OnInteractionListener, ReaderControlDelegate.OnInteractionListener,
OnApplyWindowInsetsListener,
ReaderNavigationCallback, ReaderNavigationCallback,
IdlingDetector.Callback, IdlingDetector.Callback,
ZoomControl.ZoomControlListener { ZoomControl.ZoomControlListener {
@ -116,7 +113,6 @@ class ReaderActivity :
viewBinding.zoomControl.listener = this viewBinding.zoomControl.listener = this
viewBinding.actionsView.listener = this viewBinding.actionsView.listener = this
idlingDetector.bindToLifecycle(this) idlingDetector.bindToLifecycle(this)
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
screenOrientationHelper.applySettings() screenOrientationHelper.applySettings()
viewModel.onError.observeEvent( viewModel.onError.observeEvent(
@ -297,7 +293,9 @@ class ReaderActivity :
.setOrdering(TransitionSet.ORDERING_TOGETHER) .setOrdering(TransitionSet.ORDERING_TOGETHER)
.addTransition(Slide(Gravity.TOP).addTarget(viewBinding.appbarTop)) .addTransition(Slide(Gravity.TOP).addTarget(viewBinding.appbarTop))
.addTransition(Fade().addTarget(viewBinding.infoBar)) .addTransition(Fade().addTarget(viewBinding.infoBar))
.addTransition(Slide(Gravity.BOTTOM).addTarget(viewBinding.toolbarDocked)) viewBinding.toolbarDocked?.let {
transition.addTransition(Slide(Gravity.BOTTOM).addTarget(it))
}
TransitionManager.beginDelayedTransition(viewBinding.root, transition) TransitionManager.beginDelayedTransition(viewBinding.root, transition)
} }
val isFullscreen = settings.isReaderFullscreenEnabled val isFullscreen = settings.isReaderFullscreenEnabled

@ -3,10 +3,10 @@ package org.koitharu.kotatsu.reader.ui.colorfilter
import android.content.res.Resources import android.content.res.Resources
import android.graphics.Bitmap import android.graphics.Bitmap
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.View import android.view.View
import android.widget.CompoundButton import android.widget.CompoundButton
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat
import coil3.ImageLoader import coil3.ImageLoader
import coil3.request.ImageRequest import coil3.request.ImageRequest
import coil3.request.bitmapConfig import coil3.request.bitmapConfig
@ -19,7 +19,7 @@ import com.google.android.material.slider.Slider
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.decodeRegion import org.koitharu.kotatsu.core.util.ext.decodeRegion
import org.koitharu.kotatsu.core.util.ext.enqueueWith import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.indicator import org.koitharu.kotatsu.core.util.ext.indicator
@ -28,6 +28,7 @@ import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.setChecked import org.koitharu.kotatsu.core.util.ext.setChecked
import org.koitharu.kotatsu.core.util.ext.setValueRounded import org.koitharu.kotatsu.core.util.ext.setValueRounded
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityColorFilterBinding import org.koitharu.kotatsu.databinding.ActivityColorFilterBinding
import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.model.MangaPage
import org.koitharu.kotatsu.parsers.util.format import org.koitharu.kotatsu.parsers.util.format
@ -54,7 +55,6 @@ class ColorFilterConfigActivity :
setDisplayHomeAsUpEnabled(true) setDisplayHomeAsUpEnabled(true)
setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material) setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material)
} }
viewBinding.root.consumeInsetsAsPadding(Gravity.FILL)
viewBinding.sliderBrightness.addOnChangeListener(this) viewBinding.sliderBrightness.addOnChangeListener(this)
viewBinding.sliderContrast.addOnChangeListener(this) viewBinding.sliderContrast.addOnChangeListener(this)
val formatter = PercentLabelFormatter(resources) val formatter = PercentLabelFormatter(resources)
@ -75,6 +75,20 @@ class ColorFilterConfigActivity :
loadPreview(viewModel.preview) loadPreview(viewModel.preview)
} }
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.root.setPadding(
barsInsets.left,
barsInsets.top,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) { override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) {
if (fromUser) { if (fromUser) {
when (slider.id) { when (slider.id) {

@ -5,8 +5,10 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.CompoundButton import android.widget.CompoundButton
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.google.android.material.button.MaterialButtonToggleGroup import com.google.android.material.button.MaterialButtonToggleGroup
@ -25,6 +27,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.ReaderMode import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.core.prefs.observeAsStateFlow import org.koitharu.kotatsu.core.prefs.observeAsStateFlow
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.findParentCallback import org.koitharu.kotatsu.core.util.ext.findParentCallback
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope
@ -123,6 +126,14 @@ class ReaderConfigSheet :
} }
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
viewBinding?.scrollView?.updatePadding(
bottom = insets.getInsets(typeMask).bottom,
)
return insets.consume(v, typeMask, bottom = true)
}
override fun onClick(v: View) { override fun onClick(v: View) {
when (v.id) { when (v.id) {
R.id.button_settings -> { R.id.button_settings -> {

@ -1,6 +1,8 @@
package org.koitharu.kotatsu.reader.ui.pager package org.koitharu.kotatsu.reader.ui.pager
import android.os.Bundle import android.os.Bundle
import android.view.View
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.viewbinding.ViewBinding import androidx.viewbinding.ViewBinding
import org.koitharu.kotatsu.core.prefs.ReaderAnimation import org.koitharu.kotatsu.core.prefs.ReaderAnimation
@ -31,6 +33,8 @@ abstract class BaseReaderFragment<B : ViewBinding> : BaseFragment<B>(), ZoomCont
} }
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat = insets
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
viewModel.saveCurrentState(getCurrentState()) viewModel.saveCurrentState(getCurrentState())

@ -2,9 +2,10 @@ package org.koitharu.kotatsu.scrobbling.common.ui.config
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.View import android.view.View
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import coil3.ImageLoader import coil3.ImageLoader
import coil3.request.error import coil3.request.error
import coil3.request.fallback import coil3.request.fallback
@ -16,13 +17,14 @@ import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
import org.koitharu.kotatsu.core.nav.router import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.disposeImageRequest import org.koitharu.kotatsu.core.util.ext.disposeImageRequest
import org.koitharu.kotatsu.core.util.ext.enqueueWith import org.koitharu.kotatsu.core.util.ext.enqueueWith
import org.koitharu.kotatsu.core.util.ext.newImageRequest import org.koitharu.kotatsu.core.util.ext.newImageRequest
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.showOrHide import org.koitharu.kotatsu.core.util.ext.showOrHide
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityScrobblerConfigBinding import org.koitharu.kotatsu.databinding.ActivityScrobblerConfigBinding
import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration
import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerUser
@ -48,7 +50,6 @@ class ScrobblerConfigActivity : BaseActivity<ActivityScrobblerConfigBinding>(),
val listAdapter = ScrobblingMangaAdapter(this, coil, this) val listAdapter = ScrobblingMangaAdapter(this, coil, this)
with(viewBinding.recyclerView) { with(viewBinding.recyclerView) {
consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
adapter = listAdapter adapter = listAdapter
setHasFixedSize(true) setHasFixedSize(true)
val decoration = TypedListSpacingDecoration(context, false) val decoration = TypedListSpacingDecoration(context, false)
@ -73,6 +74,23 @@ class ScrobblerConfigActivity : BaseActivity<ActivityScrobblerConfigBinding>(),
processIntent(intent) processIntent(intent)
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val basePadding = v.resources.getDimensionPixelOffset(R.dimen.list_spacing_normal)
viewBinding.appbar.updatePadding(
top = barsInsets.top,
left = barsInsets.left,
right = barsInsets.right,
)
viewBinding.recyclerView.setPadding(
barsInsets.left + basePadding,
barsInsets.top + basePadding,
barsInsets.right + basePadding,
barsInsets.bottom + basePadding,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onItemClick(item: ScrobblingInfo, view: View) { override fun onItemClick(item: ScrobblingInfo, view: View) {
router.openDetails(item.mangaId) router.openDetails(item.mangaId)
} }

@ -7,6 +7,8 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.AsyncListDiffer import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.RecyclerView.NO_ID import androidx.recyclerview.widget.RecyclerView.NO_ID
@ -22,6 +24,7 @@ import org.koitharu.kotatsu.core.ui.list.PaginationScrollListener
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.ui.util.CollapseActionViewCallback import org.koitharu.kotatsu.core.ui.util.CollapseActionViewCallback
import org.koitharu.kotatsu.core.util.RecyclerViewScrollCallback import org.koitharu.kotatsu.core.util.RecyclerViewScrollCallback
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.firstVisibleItemPosition import org.koitharu.kotatsu.core.util.ext.firstVisibleItemPosition
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
@ -114,6 +117,15 @@ class ScrobblingSelectorSheet :
paginationScrollListener = null paginationScrollListener = null
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
val basePadding = v.resources.getDimensionPixelOffset(R.dimen.list_spacing_normal)
viewBinding?.recyclerView?.updatePadding(
bottom = basePadding + insets.getInsets(typeMask).bottom,
)
return insets.consume(v, typeMask, bottom = true)
}
override fun onCurrentListChanged(previousList: MutableList<ListModel>, currentList: MutableList<ListModel>) { override fun onCurrentListChanged(previousList: MutableList<ListModel>, currentList: MutableList<ListModel>) {
if (previousList.singleOrNull() is LoadingFooter) { if (previousList.singleOrNull() is LoadingFooter) {
val rv = viewBinding?.recyclerView ?: return val rv = viewBinding?.recyclerView ?: return

@ -4,13 +4,14 @@ import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.view.Gravity
import android.view.View import android.view.View
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.core.view.WindowInsetsCompat
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityKitsuAuthBinding import org.koitharu.kotatsu.databinding.ActivityKitsuAuthBinding
import org.koitharu.kotatsu.parsers.util.urlEncoded import org.koitharu.kotatsu.parsers.util.urlEncoded
@ -21,13 +22,27 @@ class KitsuAuthActivity : BaseActivity<ActivityKitsuAuthBinding>(), View.OnClick
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityKitsuAuthBinding.inflate(layoutInflater)) setContentView(ActivityKitsuAuthBinding.inflate(layoutInflater))
viewBinding.root.consumeInsetsAsPadding(Gravity.FILL)
viewBinding.buttonCancel.setOnClickListener(this) viewBinding.buttonCancel.setOnClickListener(this)
viewBinding.buttonDone.setOnClickListener(this) viewBinding.buttonDone.setOnClickListener(this)
viewBinding.editEmail.addTextChangedListener(this) viewBinding.editEmail.addTextChangedListener(this)
viewBinding.editPassword.addTextChangedListener(this) viewBinding.editPassword.addTextChangedListener(this)
} }
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.root.setPadding(
barsInsets.left + basePadding,
barsInsets.top + basePadding,
barsInsets.right + basePadding,
barsInsets.bottom + basePadding,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onClick(v: View) { override fun onClick(v: View) {
when (v.id) { when (v.id) {
R.id.button_cancel -> finish() R.id.button_cancel -> finish()

@ -5,8 +5,6 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.graphics.drawable.toDrawable import androidx.core.graphics.drawable.toDrawable
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePaddingRelative import androidx.core.view.updatePaddingRelative
@ -32,7 +30,7 @@ import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.model.titleRes import org.koitharu.kotatsu.core.ui.model.titleRes
import org.koitharu.kotatsu.core.util.ViewBadge import org.koitharu.kotatsu.core.util.ViewBadge
import org.koitharu.kotatsu.core.util.ext.consumeRelative import org.koitharu.kotatsu.core.util.ext.consumeSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.end import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat
import org.koitharu.kotatsu.core.util.ext.getSerializableExtraCompat import org.koitharu.kotatsu.core.util.ext.getSerializableExtraCompat
@ -60,7 +58,6 @@ class MangaListActivity :
BaseActivity<ActivityMangaListBinding>(), BaseActivity<ActivityMangaListBinding>(),
AppBarOwner, View.OnClickListener, AppBarOwner, View.OnClickListener,
FilterCoordinator.Owner, FilterCoordinator.Owner,
OnApplyWindowInsetsListener,
AppBarLayout.OnOffsetChangedListener { AppBarLayout.OnOffsetChangedListener {
override val appBar: AppBarLayout override val appBar: AppBarLayout
@ -82,8 +79,6 @@ class MangaListActivity :
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
if (viewBinding.containerFilterHeader != null) { if (viewBinding.containerFilterHeader != null) {
viewBinding.appbar.addOnOffsetChangedListener(this) viewBinding.appbar.addOnOffsetChangedListener(this)
} else {
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
} }
viewBinding.buttonOrder?.setOnClickListener(this) viewBinding.buttonOrder?.setOnClickListener(this)
title = source.getTitle(this) title = source.getTitle(this)
@ -113,17 +108,10 @@ class MangaListActivity :
} }
viewBinding.appbar.updatePaddingRelative( viewBinding.appbar.updatePaddingRelative(
top = barsInsets.top, top = barsInsets.top,
end = if (viewBinding.cardSide == null) barsInsets.end(v) else 0,
start = barsInsets.start(v), start = barsInsets.start(v),
) )
return WindowInsetsCompat.Builder(insets) return insets.consumeSystemBarsInsets(v, top = true, end = true)
.setInsets(
WindowInsetsCompat.Type.systemBars(),
barsInsets.consumeRelative(
v,
top = true,
end = true,
),
).build()
} }
override fun onClick(v: View) { override fun onClick(v: View) {

@ -1,13 +1,14 @@
package org.koitharu.kotatsu.search.ui.multi package org.koitharu.kotatsu.search.ui.multi
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import coil3.ImageLoader import coil3.ImageLoader
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
@ -19,10 +20,11 @@ import org.koitharu.kotatsu.core.ui.list.ListSelectionController
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.widgets.TipView import org.koitharu.kotatsu.core.ui.widgets.TipView
import org.koitharu.kotatsu.core.util.ShareHelper import org.koitharu.kotatsu.core.util.ShareHelper
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.invalidateNestedItemDecorations import org.koitharu.kotatsu.core.util.ext.invalidateNestedItemDecorations
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivitySearchBinding import org.koitharu.kotatsu.databinding.ActivitySearchBinding
import org.koitharu.kotatsu.list.domain.ListFilterOption import org.koitharu.kotatsu.list.domain.ListFilterOption
import org.koitharu.kotatsu.list.ui.MangaSelectionDecoration import org.koitharu.kotatsu.list.ui.MangaSelectionDecoration
@ -91,7 +93,6 @@ class SearchActivity :
selectionDecoration = selectionDecoration, selectionDecoration = selectionDecoration,
) )
viewBinding.recyclerView.adapter = adapter viewBinding.recyclerView.adapter = adapter
viewBinding.recyclerView.consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
viewBinding.recyclerView.setHasFixedSize(true) viewBinding.recyclerView.setHasFixedSize(true)
viewBinding.recyclerView.addItemDecoration(TypedListSpacingDecoration(this, true)) viewBinding.recyclerView.addItemDecoration(TypedListSpacingDecoration(this, true))
@ -106,6 +107,22 @@ class SearchActivity :
viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null)) viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null))
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.appbar.updatePadding(
top = barsInsets.top,
left = barsInsets.left,
right = barsInsets.right,
)
viewBinding.recyclerView.setPadding(
barsInsets.left,
barsInsets.top,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onItemClick(item: Manga, view: View) { override fun onItemClick(item: Manga, view: View) {
if (!selectionController.onItemClick(item.id)) { if (!selectionController.onItemClick(item.id)) {
router.openDetails(item) router.openDetails(item)

@ -1,9 +1,10 @@
package org.koitharu.kotatsu.search.ui.suggestion package org.koitharu.kotatsu.search.ui.suggestion
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import coil3.ImageLoader import coil3.ImageLoader
@ -11,7 +12,7 @@ import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.core.os.VoiceInputContract import org.koitharu.kotatsu.core.os.VoiceInputContract
import org.koitharu.kotatsu.core.ui.BaseFragment import org.koitharu.kotatsu.core.ui.BaseFragment
import org.koitharu.kotatsu.core.util.ext.addMenuProvider import org.koitharu.kotatsu.core.util.ext.addMenuProvider
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.databinding.FragmentSearchSuggestionBinding import org.koitharu.kotatsu.databinding.FragmentSearchSuggestionBinding
import org.koitharu.kotatsu.search.ui.suggestion.adapter.SearchSuggestionAdapter import org.koitharu.kotatsu.search.ui.suggestion.adapter.SearchSuggestionAdapter
@ -47,12 +48,22 @@ class SearchSuggestionFragment :
addMenuProvider(SearchSuggestionMenuProvider(binding.root.context, voiceInputLauncher, viewModel)) addMenuProvider(SearchSuggestionMenuProvider(binding.root.context, voiceInputLauncher, viewModel))
binding.root.adapter = adapter binding.root.adapter = adapter
binding.root.setHasFixedSize(true) binding.root.setHasFixedSize(true)
binding.root.consumeInsetsAsPadding(Gravity.BOTTOM or Gravity.START or Gravity.END)
viewModel.suggestion.observe(viewLifecycleOwner, adapter) viewModel.suggestion.observe(viewLifecycleOwner, adapter)
ItemTouchHelper(SearchSuggestionItemCallback(this)) ItemTouchHelper(SearchSuggestionItemCallback(this))
.attachToRecyclerView(binding.root) .attachToRecyclerView(binding.root)
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.getInsets(WindowInsetsCompat.Type.ime() or WindowInsetsCompat.Type.systemBars())
v.setPadding(
barsInsets.left,
0,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onRemoveQuery(query: String) { override fun onRemoveQuery(query: String) {
viewModel.deleteQuery(query) viewModel.deleteQuery(query)
} }

@ -5,8 +5,6 @@ import android.os.Bundle
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
@ -45,7 +43,6 @@ import org.koitharu.kotatsu.settings.userdata.UserDataSettingsFragment
@AndroidEntryPoint @AndroidEntryPoint
class SettingsActivity : class SettingsActivity :
BaseActivity<ActivitySettingsBinding>(), BaseActivity<ActivitySettingsBinding>(),
OnApplyWindowInsetsListener,
PreferenceFragmentCompat.OnPreferenceStartFragmentCallback, PreferenceFragmentCompat.OnPreferenceStartFragmentCallback,
AppBarOwner { AppBarOwner {
@ -60,7 +57,6 @@ class SettingsActivity :
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivitySettingsBinding.inflate(layoutInflater)) setContentView(ActivitySettingsBinding.inflate(layoutInflater))
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
val fm = supportFragmentManager val fm = supportFragmentManager
val currentFragment = fm.findFragmentById(R.id.container) val currentFragment = fm.findFragmentById(R.id.container)

@ -15,6 +15,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.text.buildSpannedString import androidx.core.text.buildSpannedString
import androidx.core.view.WindowInsetsCompat
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import io.noties.markwon.Markwon import io.noties.markwon.Markwon
@ -26,12 +27,14 @@ import org.koitharu.kotatsu.core.github.AppVersion
import org.koitharu.kotatsu.core.nav.router import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.util.FileSize import org.koitharu.kotatsu.core.util.FileSize
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
import org.koitharu.kotatsu.core.util.ext.setTextAndVisible import org.koitharu.kotatsu.core.util.ext.setTextAndVisible
import org.koitharu.kotatsu.core.util.ext.showOrHide import org.koitharu.kotatsu.core.util.ext.showOrHide
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.core.util.ext.textAndVisible
import org.koitharu.kotatsu.databinding.ActivityAppUpdateBinding import org.koitharu.kotatsu.databinding.ActivityAppUpdateBinding
@ -83,6 +86,21 @@ class AppUpdateActivity : BaseActivity<ActivityAppUpdateBinding>(), View.OnClick
super.onDestroy() super.onDestroy()
} }
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.root.setPadding(
barsInsets.left + basePadding,
barsInsets.top + basePadding,
barsInsets.right + basePadding,
barsInsets.bottom + basePadding,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onClick(v: View) { override fun onClick(v: View) {
when (v.id) { when (v.id) {
R.id.button_cancel -> finishAfterTransition() R.id.button_cancel -> finishAfterTransition()

@ -5,6 +5,7 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -17,7 +18,12 @@ import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
import org.koitharu.kotatsu.core.ui.dialog.setRecyclerViewList import org.koitharu.kotatsu.core.ui.dialog.setRecyclerViewList
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.container
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.start
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.FragmentSettingsSourcesBinding import org.koitharu.kotatsu.databinding.FragmentSettingsSourcesBinding
import org.koitharu.kotatsu.list.ui.adapter.ListItemType import org.koitharu.kotatsu.list.ui.adapter.ListItemType
import org.koitharu.kotatsu.list.ui.model.ListModel import org.koitharu.kotatsu.list.ui.model.ListModel
@ -60,6 +66,19 @@ class NavConfigFragment : BaseFragment<FragmentSettingsSourcesBinding>(), Recycl
viewModel.content.observe(viewLifecycleOwner, navConfigAdapter) viewModel.content.observe(viewLifecycleOwner, navConfigAdapter)
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val isTablet = !resources.getBoolean(R.bool.is_tablet)
val isMaster = container?.id == R.id.container_master
v.setPaddingRelative(
if (isTablet && !isMaster) 0 else barsInsets.start(v),
0,
if (isTablet && isMaster) 0 else barsInsets.end(v),
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
activity?.setTitle(R.string.main_screen_sections) activity?.setTitle(R.string.main_screen_sections)

@ -4,7 +4,6 @@ import android.content.pm.PackageManager
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.view.Gravity
import android.view.KeyEvent import android.view.KeyEvent
import android.view.View import android.view.View
import android.view.WindowManager import android.view.WindowManager
@ -12,15 +11,17 @@ import android.view.inputmethod.EditorInfo
import android.widget.CompoundButton import android.widget.CompoundButton
import android.widget.TextView import android.widget.TextView
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivitySetupProtectBinding import org.koitharu.kotatsu.databinding.ActivitySetupProtectBinding
private const val MIN_PASSWORD_LENGTH = 4 private const val MIN_PASSWORD_LENGTH = 4
@ -39,7 +40,6 @@ class ProtectSetupActivity :
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE) window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
setContentView(ActivitySetupProtectBinding.inflate(layoutInflater)) setContentView(ActivitySetupProtectBinding.inflate(layoutInflater))
viewBinding.root.consumeInsetsAsPadding(Gravity.FILL)
viewBinding.editPassword.addTextChangedListener(this) viewBinding.editPassword.addTextChangedListener(this)
viewBinding.editPassword.setOnEditorActionListener(this) viewBinding.editPassword.setOnEditorActionListener(this)
viewBinding.buttonNext.setOnClickListener(this) viewBinding.buttonNext.setOnClickListener(this)
@ -60,6 +60,18 @@ class ProtectSetupActivity :
} }
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.root.setPadding(
barsInsets.left + basePadding,
barsInsets.top + basePadding,
barsInsets.right + basePadding,
barsInsets.bottom + basePadding,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onClick(v: View) { override fun onClick(v: View) {
when (v.id) { when (v.id) {
R.id.button_cancel -> finish() R.id.button_cancel -> finish()

@ -4,7 +4,6 @@ import android.content.DialogInterface
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable import android.graphics.drawable.LayerDrawable
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
@ -14,14 +13,16 @@ import androidx.core.graphics.ColorUtils
import androidx.core.graphics.drawable.toDrawable import androidx.core.graphics.drawable.toDrawable
import androidx.core.text.bold import androidx.core.text.bold
import androidx.core.text.buildSpannedString import androidx.core.text.buildSpannedString
import androidx.core.view.WindowInsetsCompat
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.findKeyByValue import org.koitharu.kotatsu.core.util.ext.findKeyByValue
import org.koitharu.kotatsu.core.util.ext.getThemeDrawable import org.koitharu.kotatsu.core.util.ext.getThemeDrawable
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityReaderTapActionsBinding import org.koitharu.kotatsu.databinding.ActivityReaderTapActionsBinding
import org.koitharu.kotatsu.reader.domain.TapGridArea import org.koitharu.kotatsu.reader.domain.TapGridArea
import org.koitharu.kotatsu.reader.ui.tapgrid.TapAction import org.koitharu.kotatsu.reader.ui.tapgrid.TapAction
@ -39,7 +40,6 @@ class ReaderTapGridConfigActivity : BaseActivity<ActivityReaderTapActionsBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityReaderTapActionsBinding.inflate(layoutInflater)) setContentView(ActivityReaderTapActionsBinding.inflate(layoutInflater))
viewBinding.root.consumeInsetsAsPadding(Gravity.FILL)
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
controls[TapGridArea.TOP_LEFT] = viewBinding.textViewTopLeft controls[TapGridArea.TOP_LEFT] = viewBinding.textViewTopLeft
controls[TapGridArea.TOP_CENTER] = viewBinding.textViewTopCenter controls[TapGridArea.TOP_CENTER] = viewBinding.textViewTopCenter
@ -59,6 +59,17 @@ class ReaderTapGridConfigActivity : BaseActivity<ActivityReaderTapActionsBinding
viewModel.content.observe(this, ::onContentChanged) viewModel.content.observe(this, ::onContentChanged)
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.root.setPadding(
barsInsets.left,
barsInsets.top,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean { override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.opt_tap_grid_config, menu) menuInflater.inflate(R.menu.opt_tap_grid_config, menu)
return super.onCreateOptionsMenu(menu) return super.onCreateOptionsMenu(menu)

@ -1,10 +1,10 @@
package org.koitharu.kotatsu.settings.search package org.koitharu.kotatsu.settings.search
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.AsyncListDiffer.ListListener import androidx.recyclerview.widget.AsyncListDiffer.ListListener
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@ -12,7 +12,7 @@ import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.core.ui.BaseFragment import org.koitharu.kotatsu.core.ui.BaseFragment
import org.koitharu.kotatsu.core.ui.BaseListAdapter import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.databinding.FragmentSearchSuggestionBinding import org.koitharu.kotatsu.databinding.FragmentSearchSuggestionBinding
import org.koitharu.kotatsu.list.ui.adapter.ListItemType import org.koitharu.kotatsu.list.ui.adapter.ListItemType
@ -30,7 +30,6 @@ class SettingsSearchFragment : BaseFragment<FragmentSearchSuggestionBinding>(),
override fun onViewBindingCreated(binding: FragmentSearchSuggestionBinding, savedInstanceState: Bundle?) { override fun onViewBindingCreated(binding: FragmentSearchSuggestionBinding, savedInstanceState: Bundle?) {
super.onViewBindingCreated(binding, savedInstanceState) super.onViewBindingCreated(binding, savedInstanceState)
binding.root.consumeInsetsAsPadding(Gravity.FILL_HORIZONTAL or Gravity.BOTTOM)
val adapter = BaseListAdapter<SettingsItem>() val adapter = BaseListAdapter<SettingsItem>()
.addDelegate(ListItemType.NAV_ITEM, settingsItemAD(this)) .addDelegate(ListItemType.NAV_ITEM, settingsItemAD(this))
adapter.addListListener(this) adapter.addListListener(this)
@ -39,6 +38,18 @@ class SettingsSearchFragment : BaseFragment<FragmentSearchSuggestionBinding>(),
viewModel.content.observe(viewLifecycleOwner, adapter) viewModel.content.observe(viewLifecycleOwner, adapter)
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val type = WindowInsetsCompat.Type.ime() or WindowInsetsCompat.Type.systemBars()
val barsInsets = insets.getInsets(type)
v.setPadding(
barsInsets.left,
0,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAll(type)
}
override fun onItemClick(item: SettingsItem, view: View) = viewModel.navigateToPreference(item) override fun onItemClick(item: SettingsItem, view: View) = viewModel.navigateToPreference(item)
override fun onCurrentListChanged( override fun onCurrentListChanged(

@ -5,9 +5,12 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.MenuItem import android.view.MenuItem
import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContract import androidx.activity.result.contract.ActivityResultContract
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.browser.BrowserCallback import org.koitharu.kotatsu.browser.BrowserCallback
@ -21,6 +24,7 @@ import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.core.parser.ParserMangaRepository import org.koitharu.kotatsu.core.parser.ParserMangaRepository
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.util.ext.configureForParser import org.koitharu.kotatsu.core.util.ext.configureForParser
import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.databinding.ActivityBrowserBinding import org.koitharu.kotatsu.databinding.ActivityBrowserBinding
import org.koitharu.kotatsu.parsers.MangaParserAuthProvider import org.koitharu.kotatsu.parsers.MangaParserAuthProvider
import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
@ -84,6 +88,25 @@ class SourceAuthActivity : BaseActivity<ActivityBrowserBinding>(), BrowserCallba
viewBinding.webView.destroy() viewBinding.webView.destroy()
} }
override fun onApplyWindowInsets(
v: View,
insets: WindowInsetsCompat
): WindowInsetsCompat {
val type = WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.ime()
val barsInsets = insets.getInsets(type)
viewBinding.webView.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
bottom = barsInsets.bottom,
)
viewBinding.appbar.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
top = barsInsets.top,
)
return insets.consumeAll(type)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) { override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
android.R.id.home -> { android.R.id.home -> {
viewBinding.webView.stopLoading() viewBinding.webView.stopLoading()

@ -8,8 +8,6 @@ import androidx.activity.viewModels
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import coil3.ImageLoader import coil3.ImageLoader
@ -40,7 +38,6 @@ import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(), class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
OnListItemClickListener<SourceCatalogItem.Source>, OnListItemClickListener<SourceCatalogItem.Source>,
OnApplyWindowInsetsListener,
AppBarOwner, AppBarOwner,
MenuItem.OnActionExpandListener, MenuItem.OnActionExpandListener,
ChipsView.OnChipClickListener { ChipsView.OnChipClickListener {
@ -57,7 +54,6 @@ class SourcesCatalogActivity : BaseActivity<ActivitySourcesCatalogBinding>(),
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivitySourcesCatalogBinding.inflate(layoutInflater)) setContentView(ActivitySourcesCatalogBinding.inflate(layoutInflater))
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
val sourcesAdapter = SourcesCatalogAdapter(this, coil, this) val sourcesAdapter = SourcesCatalogAdapter(this, coil, this)
with(viewBinding.recyclerView) { with(viewBinding.recyclerView) {
setHasFixedSize(true) setHasFixedSize(true)

@ -1,14 +1,15 @@
package org.koitharu.kotatsu.settings.sources.manage package org.koitharu.kotatsu.settings.sources.manage
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
import android.view.MenuInflater import android.view.MenuInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.core.view.MenuProvider import androidx.core.view.MenuProvider
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -23,10 +24,14 @@ import org.koitharu.kotatsu.core.ui.BaseFragment
import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.util.ext.addMenuProvider import org.koitharu.kotatsu.core.util.ext.addMenuProvider
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.container
import org.koitharu.kotatsu.core.util.ext.end
import org.koitharu.kotatsu.core.util.ext.getItem import org.koitharu.kotatsu.core.util.ext.getItem
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.start
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope import org.koitharu.kotatsu.core.util.ext.viewLifecycleScope
import org.koitharu.kotatsu.databinding.FragmentSettingsSourcesBinding import org.koitharu.kotatsu.databinding.FragmentSettingsSourcesBinding
import org.koitharu.kotatsu.main.ui.owners.AppBarOwner import org.koitharu.kotatsu.main.ui.owners.AppBarOwner
@ -72,7 +77,6 @@ class SourcesManageFragment :
sourcesAdapter = SourceConfigAdapter(this, coil, viewLifecycleOwner) sourcesAdapter = SourceConfigAdapter(this, coil, viewLifecycleOwner)
with(binding.recyclerView) { with(binding.recyclerView) {
setHasFixedSize(true) setHasFixedSize(true)
consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
adapter = sourcesAdapter adapter = sourcesAdapter
reorderHelper = ItemTouchHelper(SourcesReorderCallback()).also { reorderHelper = ItemTouchHelper(SourcesReorderCallback()).also {
it.attachToRecyclerView(this) it.attachToRecyclerView(this)
@ -86,6 +90,19 @@ class SourcesManageFragment :
addMenuProvider(SourcesMenuProvider()) addMenuProvider(SourcesMenuProvider())
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val isTablet = !resources.getBoolean(R.bool.is_tablet)
val isMaster = container?.id == R.id.container_master
v.setPaddingRelative(
if (isTablet && !isMaster) 0 else barsInsets.start(v),
0,
if (isTablet && isMaster) 0 else barsInsets.end(v),
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
activity?.setTitle(R.string.manage_sources) activity?.setTitle(R.string.manage_sources)

@ -8,9 +8,6 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
@ -23,6 +20,7 @@ import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
import org.koitharu.kotatsu.core.os.OpenDocumentTreeHelper import org.koitharu.kotatsu.core.os.OpenDocumentTreeHelper
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.tryLaunch import org.koitharu.kotatsu.core.util.ext.tryLaunch
@ -33,7 +31,7 @@ import org.koitharu.kotatsu.settings.storage.RequestStorageManagerPermissionCont
@AndroidEntryPoint @AndroidEntryPoint
class MangaDirectoriesActivity : BaseActivity<ActivityMangaDirectoriesBinding>(), class MangaDirectoriesActivity : BaseActivity<ActivityMangaDirectoriesBinding>(),
OnListItemClickListener<DirectoryModel>, View.OnClickListener, OnApplyWindowInsetsListener { OnListItemClickListener<DirectoryModel>, View.OnClickListener {
private val viewModel: MangaDirectoriesViewModel by viewModels() private val viewModel: MangaDirectoriesViewModel by viewModels()
private val pickFileTreeLauncher = OpenDocumentTreeHelper( private val pickFileTreeLauncher = OpenDocumentTreeHelper(
@ -64,7 +62,6 @@ class MangaDirectoriesActivity : BaseActivity<ActivityMangaDirectoriesBinding>()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityMangaDirectoriesBinding.inflate(layoutInflater)) setContentView(ActivityMangaDirectoriesBinding.inflate(layoutInflater))
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
val adapter = AsyncListDifferDelegationAdapter(DirectoryDiffCallback(), directoryConfigAD(this)) val adapter = AsyncListDifferDelegationAdapter(DirectoryDiffCallback(), directoryConfigAD(this))
viewBinding.recyclerView.adapter = adapter viewBinding.recyclerView.adapter = adapter
@ -105,8 +102,6 @@ class MangaDirectoriesActivity : BaseActivity<ActivityMangaDirectoriesBinding>()
viewBinding.recyclerView.updatePadding( viewBinding.recyclerView.updatePadding(
bottom = barsInsets.bottom, bottom = barsInsets.bottom,
) )
return WindowInsetsCompat.Builder(insets) return insets.consumeAllSystemBarsInsets()
.setInsets(WindowInsetsCompat.Type.systemBars(), Insets.NONE)
.build()
} }
} }

@ -4,12 +4,15 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.FavouriteCategory import org.koitharu.kotatsu.core.model.FavouriteCategory
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.databinding.SheetBaseBinding import org.koitharu.kotatsu.databinding.SheetBaseBinding
@ -33,6 +36,14 @@ class TrackerCategoriesConfigSheet :
viewModel.content.observe(viewLifecycleOwner, adapter) viewModel.content.observe(viewLifecycleOwner, adapter)
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
viewBinding?.recyclerView?.updatePadding(
bottom = insets.getInsets(typeMask).bottom,
)
return insets.consume(v, typeMask, bottom = true)
}
override fun onItemClick(item: FavouriteCategory, view: View) { override fun onItemClick(item: FavouriteCategory, view: View) {
viewModel.toggleItem(item) viewModel.toggleItem(item)
} }

@ -10,8 +10,6 @@ import android.widget.CompoundButton
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isVisible import androidx.core.view.isVisible
@ -50,7 +48,6 @@ import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class StatsActivity : BaseActivity<ActivityStatsBinding>(), class StatsActivity : BaseActivity<ActivityStatsBinding>(),
OnApplyWindowInsetsListener,
OnListItemClickListener<Manga>, OnListItemClickListener<Manga>,
PieChartView.OnSegmentClickListener, PieChartView.OnSegmentClickListener,
AsyncListDiffer.ListListener<StatsRecord>, AsyncListDiffer.ListListener<StatsRecord>,
@ -67,7 +64,6 @@ class StatsActivity : BaseActivity<ActivityStatsBinding>(),
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivityStatsBinding.inflate(layoutInflater)) setContentView(ActivityStatsBinding.inflate(layoutInflater))
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
ViewCompat.setOnApplyWindowInsetsListener(viewBinding.root, this)
val adapter = BaseListAdapter<StatsRecord>() val adapter = BaseListAdapter<StatsRecord>()
.addDelegate(ListItemType.FEED, statsAD(this)) .addDelegate(ListItemType.FEED, statsAD(this))
.addListListener(this) .addListListener(this)

@ -5,12 +5,15 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.collection.IntList import androidx.collection.IntList
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.nav.router import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.util.KotatsuColors import org.koitharu.kotatsu.core.util.KotatsuColors
import org.koitharu.kotatsu.core.util.ext.consume
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.textAndVisible import org.koitharu.kotatsu.core.util.ext.textAndVisible
import org.koitharu.kotatsu.databinding.SheetStatsMangaBinding import org.koitharu.kotatsu.databinding.SheetStatsMangaBinding
@ -40,6 +43,14 @@ class MangaStatsSheet : BaseAdaptiveSheet<SheetStatsMangaBinding>(), View.OnClic
binding.buttonOpen.setOnClickListener(this) binding.buttonOpen.setOnClickListener(this)
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
viewBinding?.scrollView?.updatePadding(
bottom = insets.getInsets(typeMask).bottom,
)
return insets.consume(v, typeMask, bottom = true)
}
override fun onClick(v: View) { override fun onClick(v: View) {
router.openDetails(viewModel.manga) router.openDetails(viewModel.manga)
} }

@ -6,12 +6,12 @@ import android.accounts.AccountManager
import android.os.Bundle import android.os.Bundle
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.view.Gravity
import android.view.View import android.view.View
import android.widget.Button import android.widget.Button
import android.widget.Toast import android.widget.Toast
import androidx.activity.OnBackPressedCallback import androidx.activity.OnBackPressedCallback
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.FragmentResultListener import androidx.fragment.app.FragmentResultListener
import androidx.transition.Fade import androidx.transition.Fade
@ -21,11 +21,12 @@ import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher import org.koitharu.kotatsu.core.ui.util.DefaultTextWatcher
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.getDisplayMessage import org.koitharu.kotatsu.core.util.ext.getDisplayMessage
import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat import org.koitharu.kotatsu.core.util.ext.getParcelableExtraCompat
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivitySyncAuthBinding import org.koitharu.kotatsu.databinding.ActivitySyncAuthBinding
import org.koitharu.kotatsu.sync.data.SyncSettings import org.koitharu.kotatsu.sync.data.SyncSettings
import org.koitharu.kotatsu.sync.domain.SyncAuthResult import org.koitharu.kotatsu.sync.domain.SyncAuthResult
@ -42,7 +43,6 @@ class SyncAuthActivity : BaseActivity<ActivitySyncAuthBinding>(), View.OnClickLi
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(ActivitySyncAuthBinding.inflate(layoutInflater)) setContentView(ActivitySyncAuthBinding.inflate(layoutInflater))
viewBinding.root.consumeInsetsAsPadding(Gravity.FILL)
accountAuthenticatorResponse = accountAuthenticatorResponse =
intent.getParcelableExtraCompat(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE) intent.getParcelableExtraCompat(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE)
accountAuthenticatorResponse?.onRequestContinued() accountAuthenticatorResponse?.onRequestContinued()
@ -68,6 +68,18 @@ class SyncAuthActivity : BaseActivity<ActivitySyncAuthBinding>(), View.OnClickLi
pageBackCallback.update() pageBackCallback.update()
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
val basePadding = resources.getDimensionPixelOffset(R.dimen.screen_padding)
viewBinding.root.setPadding(
barsInsets.left + basePadding,
barsInsets.top + basePadding,
barsInsets.right + basePadding,
barsInsets.bottom + basePadding,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onClick(v: View) { override fun onClick(v: View) {
when (v.id) { when (v.id) {
R.id.button_cancel -> { R.id.button_cancel -> {

@ -1,17 +1,19 @@
package org.koitharu.kotatsu.tracker.ui.debug package org.koitharu.kotatsu.tracker.ui.debug
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.View import android.view.View
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import coil3.ImageLoader import coil3.ImageLoader
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.core.nav.router import org.koitharu.kotatsu.core.nav.router
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.BaseListAdapter import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityTrackerDebugBinding import org.koitharu.kotatsu.databinding.ActivityTrackerDebugBinding
import org.koitharu.kotatsu.list.ui.adapter.ListItemType import org.koitharu.kotatsu.list.ui.adapter.ListItemType
import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration
@ -32,7 +34,6 @@ class TrackerDebugActivity : BaseActivity<ActivityTrackerDebugBinding>(), OnList
val tracksAdapter = BaseListAdapter<TrackDebugItem>() val tracksAdapter = BaseListAdapter<TrackDebugItem>()
.addDelegate(ListItemType.FEED, trackDebugAD(this, coil, this)) .addDelegate(ListItemType.FEED, trackDebugAD(this, coil, this))
with(viewBinding.recyclerView) { with(viewBinding.recyclerView) {
consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
setHasFixedSize(true) setHasFixedSize(true)
adapter = tracksAdapter adapter = tracksAdapter
addItemDecoration(TypedListSpacingDecoration(context, false)) addItemDecoration(TypedListSpacingDecoration(context, false))
@ -40,6 +41,21 @@ class TrackerDebugActivity : BaseActivity<ActivityTrackerDebugBinding>(), OnList
viewModel.content.observe(this, tracksAdapter) viewModel.content.observe(this, tracksAdapter)
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.recyclerView.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
bottom = barsInsets.bottom,
)
viewBinding.appbar.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
top = barsInsets.top,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onItemClick(item: TrackDebugItem, view: View) { override fun onItemClick(item: TrackDebugItem, view: View) {
router.openDetails(item.manga) router.openDetails(item.manga)
} }

@ -4,6 +4,7 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.WindowInsetsCompat
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@ -22,6 +23,7 @@ import org.koitharu.kotatsu.core.ui.util.RecyclerViewOwner
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
import org.koitharu.kotatsu.core.ui.widgets.TipView import org.koitharu.kotatsu.core.ui.widgets.TipView
import org.koitharu.kotatsu.core.util.ext.addMenuProvider import org.koitharu.kotatsu.core.util.ext.addMenuProvider
import org.koitharu.kotatsu.core.util.ext.consumeAll
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.databinding.FragmentListBinding import org.koitharu.kotatsu.databinding.FragmentListBinding
@ -83,6 +85,19 @@ class FeedFragment :
viewModel.isRunning.observe(viewLifecycleOwner, this::onIsTrackerRunningChanged) viewModel.isRunning.observe(viewLifecycleOwner, this::onIsTrackerRunningChanged)
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val typeMask = WindowInsetsCompat.Type.systemBars()
val barsInsets = insets.getInsets(typeMask)
val basePadding = v.resources.getDimensionPixelOffset(R.dimen.list_spacing_normal)
viewBinding?.recyclerView?.setPadding(
left = barsInsets.left + basePadding,
top = basePadding,
right = barsInsets.right + basePadding,
bottom = barsInsets.bottom + basePadding,
)
return insets.consumeAll(typeMask)
}
override fun onRefresh() { override fun onRefresh() {
viewModel.update() viewModel.update()
} }

@ -3,13 +3,14 @@ package org.koitharu.kotatsu.widget.recent
import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetManager
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.View import android.view.View
import androidx.core.view.WindowInsetsCompat
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.prefs.AppWidgetConfig import org.koitharu.kotatsu.core.prefs.AppWidgetConfig
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityAppwidgetRecentBinding import org.koitharu.kotatsu.databinding.ActivityAppwidgetRecentBinding
import com.google.android.material.R as materialR import com.google.android.material.R as materialR
@ -28,7 +29,6 @@ class RecentWidgetConfigActivity :
setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material) setHomeAsUpIndicator(materialR.drawable.abc_ic_clear_material)
} }
viewBinding.buttonDone.setOnClickListener(this) viewBinding.buttonDone.setOnClickListener(this)
viewBinding.root.consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM or Gravity.TOP)
val appWidgetId = intent?.getIntExtra( val appWidgetId = intent?.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID,
@ -41,6 +41,17 @@ class RecentWidgetConfigActivity :
viewBinding.switchBackground.isChecked = config.hasBackground viewBinding.switchBackground.isChecked = config.hasBackground
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.root.setPadding(
barsInsets.left,
barsInsets.top,
barsInsets.right,
barsInsets.bottom,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onClick(v: View) { override fun onClick(v: View) {
when (v.id) { when (v.id) {
R.id.button_done -> { R.id.button_done -> {

@ -3,18 +3,20 @@ package org.koitharu.kotatsu.widget.shelf
import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetManager
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.Gravity
import android.view.View import android.view.View
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver import org.koitharu.kotatsu.core.exceptions.resolve.SnackbarErrorObserver
import org.koitharu.kotatsu.core.prefs.AppWidgetConfig import org.koitharu.kotatsu.core.prefs.AppWidgetConfig
import org.koitharu.kotatsu.core.ui.BaseActivity import org.koitharu.kotatsu.core.ui.BaseActivity
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.util.ext.consumeInsetsAsPadding import org.koitharu.kotatsu.core.util.ext.consumeAllSystemBarsInsets
import org.koitharu.kotatsu.core.util.ext.observe import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.systemBarsInsets
import org.koitharu.kotatsu.databinding.ActivityAppwidgetShelfBinding import org.koitharu.kotatsu.databinding.ActivityAppwidgetShelfBinding
import org.koitharu.kotatsu.widget.shelf.adapter.CategorySelectAdapter import org.koitharu.kotatsu.widget.shelf.adapter.CategorySelectAdapter
import org.koitharu.kotatsu.widget.shelf.model.CategoryItem import org.koitharu.kotatsu.widget.shelf.model.CategoryItem
@ -40,7 +42,6 @@ class ShelfWidgetConfigActivity :
} }
adapter = CategorySelectAdapter(this) adapter = CategorySelectAdapter(this)
viewBinding.recyclerView.adapter = adapter viewBinding.recyclerView.adapter = adapter
viewBinding.recyclerView.consumeInsetsAsPadding(Gravity.START or Gravity.END or Gravity.BOTTOM)
viewBinding.buttonDone.setOnClickListener(this) viewBinding.buttonDone.setOnClickListener(this)
val appWidgetId = intent?.getIntExtra( val appWidgetId = intent?.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.EXTRA_APPWIDGET_ID,
@ -58,6 +59,21 @@ class ShelfWidgetConfigActivity :
viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null)) viewModel.onError.observeEvent(this, SnackbarErrorObserver(viewBinding.recyclerView, null))
} }
override fun onApplyWindowInsets(v: View, insets: WindowInsetsCompat): WindowInsetsCompat {
val barsInsets = insets.systemBarsInsets
viewBinding.recyclerView.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
bottom = barsInsets.bottom,
)
viewBinding.appbar.updatePadding(
left = barsInsets.left,
right = barsInsets.right,
top = barsInsets.top,
)
return insets.consumeAllSystemBarsInsets()
}
override fun onClick(v: View) { override fun onClick(v: View) {
when (v.id) { when (v.id) {
R.id.button_done -> { R.id.button_done -> {

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

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

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

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

@ -318,7 +318,7 @@
app:paddingBottomSystemWindowInsets="false" app:paddingBottomSystemWindowInsets="false"
tools:layout="@layout/sheet_chapters_pages" /> tools:layout="@layout/sheet_chapters_pages" />
<org.koitharu.kotatsu.core.ui.widgets.WindowInsetHolder <View
android:id="@+id/navbarDim" android:id="@+id/navbarDim"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

@ -37,7 +37,7 @@
android:id="@+id/toolbar_card" android:id="@+id/toolbar_card"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="56dp" android:layout_height="56dp"
android:layout_marginTop="@dimen/margin_normal" android:layout_marginTop="@dimen/margin_small"
android:layout_marginBottom="@dimen/margin_small" android:layout_marginBottom="@dimen/margin_small"
android:background="@drawable/search_bar_background" android:background="@drawable/search_bar_background"
android:theme="@style/ThemeOverlay.Kotatsu.MainToolbar" android:theme="@style/ThemeOverlay.Kotatsu.MainToolbar"

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

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

@ -13,12 +13,6 @@
app:elevation="0dp" app:elevation="0dp"
app:liftOnScroll="false"> app:liftOnScroll="false">
<org.koitharu.kotatsu.core.ui.widgets.WindowInsetHolder
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
app:layout_scrollFlags="scroll|enterAlways|snap" />
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar" android:id="@id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"

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

@ -17,6 +17,7 @@
android:id="@+id/scrollView" android:id="@+id/scrollView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:clipToPadding="false"
android:scrollIndicators="top" android:scrollIndicators="top"
tools:ignore="UnusedAttribute"> tools:ignore="UnusedAttribute">

@ -15,8 +15,10 @@
app:title="@string/list_options" /> app:title="@string/list_options" />
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clipToPadding="false"
android:scrollIndicators="top" android:scrollIndicators="top"
android:scrollbars="vertical"> android:scrollbars="vertical">

@ -14,8 +14,10 @@
app:title="@string/options" /> app:title="@string/options" />
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clipToPadding="false"
android:scrollIndicators="top"> android:scrollIndicators="top">
<LinearLayout <LinearLayout

@ -4,7 +4,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:clipToPadding="false">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent" android:layout_width="match_parent"

@ -18,6 +18,7 @@
android:id="@+id/scrollView" android:id="@+id/scrollView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:clipToPadding="false"
android:scrollIndicators="top"> android:scrollIndicators="top">
<LinearLayout <LinearLayout

@ -15,7 +15,8 @@
<androidx.core.widget.NestedScrollView <androidx.core.widget.NestedScrollView
android:id="@+id/scrollView" android:id="@+id/scrollView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:clipToPadding="false"
android:scrollIndicators="top"> android:scrollIndicators="top">
<LinearLayout <LinearLayout

@ -36,6 +36,13 @@
<style name="ThemeOverlay.Kotatsu.BottomSheetDialog" parent="ThemeOverlay.Material3.BottomSheetDialog"> <style name="ThemeOverlay.Kotatsu.BottomSheetDialog" parent="ThemeOverlay.Material3.BottomSheetDialog">
<item name="android:windowAnimationStyle">@style/Animation.Kotatsu.BottomSheetDialog</item> <item name="android:windowAnimationStyle">@style/Animation.Kotatsu.BottomSheetDialog</item>
<item name="bottomSheetStyle">@style/Widget.Kotatsu.BottomSheet.Modal</item>
</style>
<style name="ThemeOverlay.Kotatsu.SideSheetDialog" parent="ThemeOverlay.Material3.SideSheetDialog" />
<style name="Widget.Kotatsu.BottomSheet.Modal" parent="Widget.Material3.BottomSheet.Modal">
<item name="paddingBottomSystemWindowInsets">false</item>
</style> </style>
<style name="Widget.Kotatsu.BottomSheet.DragHandle" parent="Widget.Material3.BottomSheet.DragHandle"> <style name="Widget.Kotatsu.BottomSheet.DragHandle" parent="Widget.Material3.BottomSheet.DragHandle">

@ -58,6 +58,7 @@
<item name="android:itemTextAppearance">@style/TextAppearance.Widget.Menu</item> <item name="android:itemTextAppearance">@style/TextAppearance.Widget.Menu</item>
<item name="alertDialogTheme">@style/ThemeOverlay.Kotatsu.AlertDialog</item> <item name="alertDialogTheme">@style/ThemeOverlay.Kotatsu.AlertDialog</item>
<item name="bottomSheetDialogTheme">@style/ThemeOverlay.Kotatsu.BottomSheetDialog</item> <item name="bottomSheetDialogTheme">@style/ThemeOverlay.Kotatsu.BottomSheetDialog</item>
<item name="sideSheetDialogTheme">@style/ThemeOverlay.Kotatsu.SideSheetDialog</item>
<item name="textAppearanceButton">@style/TextAppearance.Kotatsu.Button</item> <item name="textAppearanceButton">@style/TextAppearance.Kotatsu.Button</item>
<item name="android:buttonStyle">?attr/borderlessButtonStyle</item> <item name="android:buttonStyle">?attr/borderlessButtonStyle</item>
<item name="android:backgroundDimAmount">0.32</item> <item name="android:backgroundDimAmount">0.32</item>

Loading…
Cancel
Save