Binding Sheets

And you know what being honest,
This commit is contained in:
Jays2Kings 2021-03-29 22:22:54 -04:00
parent aba58f70c4
commit ea3ea165aa
7 changed files with 107 additions and 110 deletions

View File

@ -16,6 +16,7 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.textview.MaterialTextView
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.BottomMenuSheetBinding
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.system.hasSideNavBar
@ -29,7 +30,6 @@ import eu.kanade.tachiyomi.util.view.setTextColorRes
import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.visible
import eu.kanade.tachiyomi.util.view.visibleIf
import kotlinx.android.synthetic.main.bottom_menu_sheet.*
open class MaterialMenuSheet(
activity: Activity,
@ -44,20 +44,20 @@ open class MaterialMenuSheet(
(activity, R.style.BottomSheetDialogTheme) {
private val primaryColor = activity.getResourceColor(android.R.attr.textColorPrimary)
private val view = activity.layoutInflater.inflate(R.layout.bottom_menu_sheet, null)
private val binding = BottomMenuSheetBinding.inflate(activity.layoutInflater)
init {
setContentView(view)
setEdgeToEdge(activity, view)
setContentView(binding.root)
setEdgeToEdge(activity, binding.root)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !context.isInNightMode() && !activity.window.decorView.rootWindowInsets.hasSideNavBar()) {
window?.decorView?.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
}
maxHeight?.let {
menu_scroll_view.maxHeight = it + activity.window.decorView.rootWindowInsets.systemWindowInsetBottom
menu_scroll_view.requestLayout()
binding.menuScrollView.maxHeight = it + activity.window.decorView.rootWindowInsets.systemWindowInsetBottom
binding.menuScrollView.requestLayout()
}
divider.visibleIf(showDivider)
binding.divider.visibleIf(showDivider)
var currentIndex: Int? = null
items.forEachIndexed { index, item ->
val view =
@ -68,7 +68,7 @@ open class MaterialMenuSheet(
}
with(view) {
id = item.id
menu_layout.addView(this)
binding.menuLayout.addView(this)
setOnClickListener {
val shouldDismiss = onMenuItemClicked(this@MaterialMenuSheet, id)
if (shouldDismiss) {
@ -99,17 +99,17 @@ open class MaterialMenuSheet(
}
}
BottomSheetBehavior.from(view.parent as ViewGroup).expand()
BottomSheetBehavior.from(view.parent as ViewGroup).skipCollapsed = true
BottomSheetBehavior.from(binding.root.parent as ViewGroup).expand()
BottomSheetBehavior.from(binding.root.parent as ViewGroup).skipCollapsed = true
setBottomEdge(menu_layout, activity)
setBottomEdge(binding.menuLayout, activity)
title_layout.visibleIf(title != null)
toolbar_title.text = title
binding.titleLayout.visibleIf(title != null)
binding.toolbarTitle.text = title
currentIndex?.let {
view.post {
menu_scroll_view?.scrollTo(0, it * 48.dpToPx - menu_scroll_view.height / 2)
binding.root.post {
binding.menuScrollView?.scrollTo(0, it * 48.dpToPx - binding.menuScrollView.height / 2)
}
}
@ -121,17 +121,17 @@ open class MaterialMenuSheet(
isElevated = elevate
elevationAnimator?.cancel()
elevationAnimator = ObjectAnimator.ofFloat(
title_layout,
binding.titleLayout,
"elevation",
title_layout.elevation,
binding.titleLayout.elevation,
if (elevate) 10f else 0f
)
elevationAnimator?.start()
}
elevate(menu_scroll_view.canScrollVertically(-1))
if (title_layout.isVisible()) {
menu_scroll_view.setOnScrollChangeListener { _: View?, _: Int, _: Int, _: Int, _: Int ->
val notAtTop = menu_scroll_view.canScrollVertically(-1)
elevate(binding.menuScrollView.canScrollVertically(-1))
if (binding.titleLayout.isVisible()) {
binding.menuScrollView.setOnScrollChangeListener { _: View?, _: Int, _: Int, _: Int, _: Int ->
val notAtTop = binding.menuScrollView.canScrollVertically(-1)
if (notAtTop != isElevated) {
elevate(notAtTop)
}
@ -140,9 +140,9 @@ open class MaterialMenuSheet(
}
private fun clearEndDrawables() {
(0 until menu_layout.childCount).forEach {
val textView = (menu_layout.getChildAt(it) as ViewGroup).getChildAt(0) as TextView
val imageView = (menu_layout.getChildAt(it) as ViewGroup).getChildAt(1) as ImageView
(0 until binding.menuLayout.childCount).forEach {
val textView = (binding.menuLayout.getChildAt(it) as ViewGroup).getChildAt(0) as TextView
val imageView = (binding.menuLayout.getChildAt(it) as ViewGroup).getChildAt(1) as ImageView
textView.setTextColor(primaryColor)
textView.compoundDrawableTintList = ColorStateList.valueOf(primaryColor)
imageView.invisible()
@ -153,7 +153,7 @@ open class MaterialMenuSheet(
if (clearAll) {
clearEndDrawables()
}
val layout = menu_layout.findViewById<ViewGroup>(id) ?: return
val layout = binding.menuLayout.findViewById<ViewGroup>(id) ?: return
val textView = layout.getChildAt(0) as? TextView
val imageView = layout.getChildAt(1) as? ImageView
textView?.setTextColorRes(R.color.colorAccent)

View File

@ -3,50 +3,51 @@ package eu.kanade.tachiyomi.ui.manga.chapter
import android.content.Context
import android.util.AttributeSet
import android.widget.CompoundButton
import android.widget.FrameLayout
import android.widget.RelativeLayout
import eu.kanade.tachiyomi.R
import android.widget.LinearLayout
import eu.kanade.tachiyomi.data.database.models.Manga
import kotlinx.android.synthetic.main.chapter_filter_layout.view.*
import eu.kanade.tachiyomi.databinding.ChapterFilterLayoutBinding
class ChapterFilterLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
FrameLayout(context, attrs) {
LinearLayout(context, attrs) {
init {
RelativeLayout.inflate(context, R.layout.chapter_filter_layout, this)
show_all.setOnCheckedChangeListener(::checkedFilter)
show_read.setOnCheckedChangeListener(::checkedFilter)
show_unread.setOnCheckedChangeListener(::checkedFilter)
show_download.setOnCheckedChangeListener(::checkedFilter)
show_bookmark.setOnCheckedChangeListener(::checkedFilter)
lateinit var binding: ChapterFilterLayoutBinding
override fun onFinishInflate() {
super.onFinishInflate()
binding = ChapterFilterLayoutBinding.bind(this)
binding.showAll.setOnCheckedChangeListener(::checkedFilter)
binding.showRead.setOnCheckedChangeListener(::checkedFilter)
binding.showUnread.setOnCheckedChangeListener(::checkedFilter)
binding.showDownload.setOnCheckedChangeListener(::checkedFilter)
binding.showBookmark.setOnCheckedChangeListener(::checkedFilter)
}
private fun checkedFilter(checkBox: CompoundButton, isChecked: Boolean) {
if (isChecked) {
if (show_all == checkBox) {
show_read.isChecked = false
show_unread.isChecked = false
show_download.isChecked = false
show_bookmark.isChecked = false
if (binding.showAll == checkBox) {
binding.showRead.isChecked = false
binding.showUnread.isChecked = false
binding.showDownload.isChecked = false
binding.showBookmark.isChecked = false
} else {
show_all.isChecked = false
if (show_read == checkBox) show_unread.isChecked = false
else if (show_unread == checkBox) show_read.isChecked = false
binding.showAll.isChecked = false
if (binding.showRead == checkBox) binding.showUnread.isChecked = false
else if (binding.showUnread == checkBox) binding.showRead.isChecked = false
}
} else if (!show_read.isChecked && !show_unread.isChecked && !show_download.isChecked && !show_bookmark.isChecked) {
show_all.isChecked = true
} else if (!binding.showRead.isChecked && !binding.showUnread.isChecked && !binding.showDownload.isChecked && !binding.showBookmark.isChecked) {
binding.showAll.isChecked = true
}
}
fun setCheckboxes(manga: Manga) {
show_read.isChecked = manga.readFilter == Manga.SHOW_READ
show_unread.isChecked = manga.readFilter == Manga.SHOW_UNREAD
show_download.isChecked = manga.downloadedFilter == Manga.SHOW_DOWNLOADED
show_bookmark.isChecked = manga.bookmarkedFilter == Manga.SHOW_BOOKMARKED
binding.showRead.isChecked = manga.readFilter == Manga.SHOW_READ
binding.showUnread.isChecked = manga.readFilter == Manga.SHOW_UNREAD
binding.showDownload.isChecked = manga.downloadedFilter == Manga.SHOW_DOWNLOADED
binding.showBookmark.isChecked = manga.bookmarkedFilter == Manga.SHOW_BOOKMARKED
show_all.isChecked = !(
show_read.isChecked || show_unread.isChecked ||
show_download.isChecked || show_bookmark.isChecked
binding.showAll.isChecked = !(
binding.showRead.isChecked || binding.showUnread.isChecked ||
binding.showDownload.isChecked || binding.showBookmark.isChecked
)
}
}

View File

@ -15,8 +15,6 @@ import eu.kanade.tachiyomi.util.view.setBottomEdge
import eu.kanade.tachiyomi.util.view.setEdgeToEdge
import eu.kanade.tachiyomi.util.view.visInvisIf
import eu.kanade.tachiyomi.util.view.visibleIf
import kotlinx.android.synthetic.main.chapter_filter_layout.*
import kotlinx.android.synthetic.main.chapter_sort_bottom_sheet.*
import kotlin.math.max
class ChaptersSortBottomSheet(controller: MangaDetailsController) : BottomSheetDialog
@ -42,9 +40,9 @@ class ChaptersSortBottomSheet(controller: MangaDetailsController) : BottomSheetD
object : BottomSheetBehavior.BottomSheetCallback() {
override fun onSlide(bottomSheet: View, progress: Float) {
if (progress.isNaN()) {
pill.alpha = 0f
binding.pill.alpha = 0f
} else {
pill.alpha = (1 - max(0f, progress)) * 0.25f
binding.pill.alpha = (1 - max(0f, progress)) * 0.25f
}
}
@ -68,68 +66,68 @@ class ChaptersSortBottomSheet(controller: MangaDetailsController) : BottomSheetD
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initGeneralPreferences()
setBottomEdge(hide_titles, activity)
close_button.setOnClickListener { dismiss() }
settings_scroll_view.viewTreeObserver.addOnGlobalLayoutListener {
setBottomEdge(binding.hideTitles, activity)
binding.closeButton.setOnClickListener { dismiss() }
binding.settingsScrollView.viewTreeObserver.addOnGlobalLayoutListener {
val isScrollable =
settings_scroll_view!!.height < sort_layout.height +
settings_scroll_view.paddingTop + settings_scroll_view.paddingBottom
close_button.visibleIf(isScrollable)
binding.settingsScrollView.height < binding.sortLayout.height +
binding.settingsScrollView.paddingTop + binding.settingsScrollView.paddingBottom
binding.closeButton.visibleIf(isScrollable)
// making the view gone somehow breaks the layout so lets make it invisible
pill.visInvisIf(!isScrollable)
binding.pill.visInvisIf(!isScrollable)
}
setOnDismissListener {
presenter.setFilters(
show_read.isChecked,
show_unread.isChecked,
show_download.isChecked,
show_bookmark.isChecked
binding.chapterFilterLayout.showRead.isChecked,
binding.chapterFilterLayout.showUnread.isChecked,
binding.chapterFilterLayout.showDownload.isChecked,
binding.chapterFilterLayout.showBookmark.isChecked
)
}
}
private fun initGeneralPreferences() {
chapter_filter_layout.setCheckboxes(presenter.manga)
binding.chapterFilterLayout.root.setCheckboxes(presenter.manga)
var defPref = presenter.globalSort()
sort_group.check(
binding.sortGroup.check(
if (presenter.manga.sortDescending(defPref)) R.id.sort_newest else {
R.id.sort_oldest
}
)
hide_titles.isChecked = presenter.manga.displayMode != Manga.DISPLAY_NAME
sort_method_group.check(
binding.hideTitles.isChecked = presenter.manga.displayMode != Manga.DISPLAY_NAME
binding.sortMethodGroup.check(
if (presenter.manga.sorting == Manga.SORTING_SOURCE) R.id.sort_by_source else {
R.id.sort_by_number
}
)
set_as_default_sort.visInvisIf(
binding.setAsDefaultSort.visInvisIf(
defPref != presenter.manga.sortDescending() &&
presenter.manga.usesLocalSort()
)
sort_group.setOnCheckedChangeListener { _, checkedId ->
binding.sortGroup.setOnCheckedChangeListener { _, checkedId ->
presenter.setSortOrder(checkedId == R.id.sort_newest)
set_as_default_sort.visInvisIf(
binding.setAsDefaultSort.visInvisIf(
defPref != presenter.manga.sortDescending() &&
presenter.manga.usesLocalSort()
)
}
set_as_default_sort.setOnClickListener {
val desc = sort_group.checkedRadioButtonId == R.id.sort_newest
binding.setAsDefaultSort.setOnClickListener {
val desc = binding.sortGroup.checkedRadioButtonId == R.id.sort_newest
presenter.setGlobalChapterSort(desc)
defPref = desc
set_as_default_sort.invisible()
binding.setAsDefaultSort.invisible()
}
sort_method_group.setOnCheckedChangeListener { _, checkedId ->
binding.sortMethodGroup.setOnCheckedChangeListener { _, checkedId ->
presenter.setSortMethod(checkedId == R.id.sort_by_source)
}
hide_titles.setOnCheckedChangeListener { _, isChecked ->
binding.hideTitles.setOnCheckedChangeListener { _, isChecked ->
presenter.hideTitle(isChecked)
}
}

View File

@ -27,7 +27,6 @@ import eu.kanade.tachiyomi.util.view.scrollViewWith
import eu.kanade.tachiyomi.util.view.setStyle
import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.util.view.withFadeTransaction
import kotlinx.android.synthetic.main.download_bottom_sheet.*
import kotlinx.android.synthetic.main.recent_chapters_controller.*
import kotlinx.android.synthetic.main.recent_chapters_controller.empty_view
import timber.log.Timber
@ -114,7 +113,6 @@ class RecentChaptersController(bundle: Bundle? = null) :
super.onActivityResumed(activity)
if (view != null) {
refresh()
dl_bottom_sheet?.update()
}
}

View File

@ -13,11 +13,11 @@ import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.databinding.SourceFilterSheetBinding
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.view.RecyclerWindowInsetsListener
import eu.kanade.tachiyomi.util.view.expand
import eu.kanade.tachiyomi.util.view.setEdgeToEdge
import kotlinx.android.synthetic.main.source_filter_sheet.*
import uy.kohesive.injekt.injectLazy
class SourceSearchSheet(activity: Activity) :
@ -43,34 +43,34 @@ class SourceSearchSheet(activity: Activity) :
var onResetClicked = {}
private val binding = SourceFilterSheetBinding.inflate(activity.layoutInflater)
init {
val view = activity.layoutInflater.inflate(R.layout.source_filter_sheet, null)
setContentView(view)
toolbar_title.text = context.getString(R.string.search_filters)
search_btn.setOnClickListener { dismiss() }
reset_btn.setOnClickListener { onResetClicked() }
setContentView(binding.root)
binding.toolbarTitle.text = context.getString(R.string.search_filters)
binding.searchBtn.setOnClickListener { dismiss() }
binding.resetBtn.setOnClickListener { onResetClicked() }
sheetBehavior = BottomSheetBehavior.from(view.parent as ViewGroup)
sheetBehavior = BottomSheetBehavior.from(binding.root.parent as ViewGroup)
sheetBehavior.skipCollapsed = true
sheetBehavior.expand()
setEdgeToEdge(
activity,
view,
binding.root,
50.dpToPx
)
recycler.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(context)
recycler.clipToPadding = false
recycler.adapter = adapter
recycler.setHasFixedSize(true)
recycler.setOnApplyWindowInsetsListener(RecyclerWindowInsetsListener)
binding.recycler.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(context)
binding.recycler.clipToPadding = false
binding.recycler.adapter = adapter
binding.recycler.setHasFixedSize(true)
binding.recycler.setOnApplyWindowInsetsListener(RecyclerWindowInsetsListener)
// the spinner in the recycler can break the sheet's layout on change
// this is to reset it back
source_filter_sheet.post {
(source_filter_sheet?.parent as? View)?.fitsSystemWindows = false
source_filter_sheet.viewTreeObserver.addOnDrawListener {
(source_filter_sheet?.parent as? View)?.fitsSystemWindows = false
binding.sourceFilterSheet.post {
(binding.sourceFilterSheet.parent as? View)?.fitsSystemWindows = false
binding.sourceFilterSheet.viewTreeObserver.addOnDrawListener {
(binding.sourceFilterSheet.parent as? View)?.fitsSystemWindows = false
}
}
@ -86,19 +86,19 @@ class SourceSearchSheet(activity: Activity) :
}
)
recycler.addOnScrollListener(
binding.recycler.addOnScrollListener(
object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
val atTop = !recycler.canScrollVertically(-1)
val atTop = !binding.recycler.canScrollVertically(-1)
if (atTop != isNotElevated) {
elevationAnimator?.cancel()
isNotElevated = atTop
elevationAnimator?.cancel()
elevationAnimator = ObjectAnimator.ofFloat(
title_layout,
binding.titleLayout,
"elevation",
title_layout.elevation,
binding.titleLayout.elevation,
if (atTop) 0f else 10f.dpToPx
)
elevationAnimator?.duration = 100
@ -113,7 +113,7 @@ class SourceSearchSheet(activity: Activity) :
callback: ActionMode.Callback?,
type: Int
): ActionMode? {
(source_filter_sheet.parent as View).fitsSystemWindows = false
(binding.sourceFilterSheet.parent as View).fitsSystemWindows = false
return super.onWindowStartingActionMode(callback, type)
}

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<eu.kanade.tachiyomi.ui.manga.chapter.ChapterFilterLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
@ -52,4 +52,4 @@
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/show_bookmarked_chapters" />
</LinearLayout>
</eu.kanade.tachiyomi.ui.manga.chapter.ChapterFilterLayout>

View File

@ -66,7 +66,7 @@
android:text="@string/oldest_first" />
</RadioGroup>
<eu.kanade.tachiyomi.ui.manga.chapter.ChapterFilterLayout
<include layout="@layout/chapter_filter_layout"
android:id="@+id/chapter_filter_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
@ -121,7 +121,7 @@
android:alpha="0.25"
android:contentDescription="@string/drag_handle"
android:src="@drawable/draggable_pill"
android:tint="?android:attr/textColorPrimary" />
app:tint="?android:attr/textColorPrimary" />
<ImageView
android:id="@+id/close_button"
@ -135,5 +135,5 @@
android:contentDescription="@string/close"
android:focusable="true"
android:src="@drawable/ic_close_24dp"
android:tint="@color/gray_button" />
app:tint="@color/gray_button" />
</FrameLayout>