diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt index c2ebf5639c..036d0f18bc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt @@ -61,11 +61,10 @@ import eu.kanade.tachiyomi.util.system.dpToPxEnd import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.launchUI import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController -import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsets import eu.kanade.tachiyomi.util.view.getItemView import eu.kanade.tachiyomi.util.view.gone import eu.kanade.tachiyomi.util.view.hide -import eu.kanade.tachiyomi.util.view.marginTop +import eu.kanade.tachiyomi.util.view.scrollViewWith import eu.kanade.tachiyomi.util.view.setBackground import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener import eu.kanade.tachiyomi.util.view.setStartTranslationX @@ -245,12 +244,6 @@ class LibraryController( fast_scroller.setStartTranslationX(!alwaysShowScroller) fast_scroller.setBackground(!alwaysShowScroller) - show_all.isChecked = preferences.showAllCategories().get() - show_all.setOnCheckedChangeListener { _, isChecked -> - preferences.showAllCategories().set(isChecked) - presenter.getLibrary() - } - adapter = LibraryCategoryAdapter(this) adapter.expandItemsAtStartUp() adapter.isRecursiveCollapse = true @@ -312,7 +305,15 @@ class LibraryController( appbar?.y = 0f recycler.suppressLayout(true) (recycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset( - itemPosition, 0 + itemPosition, if (adapter.isSingleCategory) { + 0 + } else { + if (itemPosition == 0) { + 0 + } else { + (-40).dpToPx + } + } ) recycler.suppressLayout(false) } @@ -330,25 +331,18 @@ class LibraryController( scrollToHeader(it) showCategories(false) } - swipe_refresh.setDistanceToTriggerSync(150.dpToPx) - val marginTop = category_layout.marginTop - recycler.doOnApplyWindowInsets { recyclerView, insets, _ -> - recyclerView.updateLayoutParams { - topMargin = marginTop + insets.systemWindowInsetTop - } + category_recycler.onShowAllClicked = { isChecked -> + preferences.showAllCategories().set(isChecked) + presenter.getLibrary() + } + scrollViewWith(recycler, swipeRefreshLayout = swipe_refresh, afterInsets = { insets -> category_layout?.updateLayoutParams { - topMargin = marginTop + insets.systemWindowInsetTop - } - recycler_cover?.updateLayoutParams { - topMargin = marginTop + insets.systemWindowInsetTop + topMargin = recycler?.paddingTop ?: 0 } fast_scroller?.updateLayoutParams { topMargin = insets.systemWindowInsetTop } - swipe_refresh?.setProgressViewOffset( - true, (marginTop + insets.systemWindowInsetTop) + (-60).dpToPx, marginTop + insets.systemWindowInsetTop + 10.dpToPx - ) - } + }) swipe_refresh.setOnRefreshListener { swipe_refresh.isRefreshing = false @@ -605,11 +599,16 @@ class LibraryController( private fun showCategories(show: Boolean) { recycler_cover.isClickable = show recycler_cover.isFocusable = show - val translateY = if (show) category_layout.height.toFloat() + 12f.dpToPx else 0f + val translateY = if (show) { + category_layout.height.toFloat() + recycler.paddingTop + } else { + 0f + } recycler.animate().translationY(translateY).start() recycler_cover.animate().translationY(translateY).start() recycler_cover.animate().alpha(if (show) 0.75f else 0f).start() if (show) { + activity?.appbar?.y = 0f elevateFunc(false) activity?.dropdown?.setImageResource(R.drawable.ic_arrow_drop_up_24dp) } else { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryItem.kt index 40b0c4401f..6356779c8e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryItem.kt @@ -1,25 +1,41 @@ package eu.kanade.tachiyomi.ui.library.category import android.view.View +import android.widget.CheckBox import android.widget.TextView import com.mikepenz.fastadapter.FastAdapter import com.mikepenz.fastadapter.items.AbstractItem +import com.tfcporciuncula.flow.Preference import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Category +import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get -class CategoryItem(val category: Category) : -AbstractItem() { +class CategoryItem(val category: Category) : AbstractItem>() { /** defines the type defining this item. must be unique. preferably an id */ - override val type: Int = R.id.category_text + override val type: Int = if (category.id == -1) { + R.id.auto_checkbox + } else { + R.id.category_text + } /** defines the layout which will be used for this item in the list */ - override val layoutRes: Int = R.layout.catergory_text_view + override val layoutRes: Int = if (category.id == -1) { + R.layout.auto_ext_checkbox + } else { + R.layout.catergory_text_view + } override var identifier = category.id?.toLong() ?: -1L - override fun getViewHolder(v: View): ViewHolder { - return ViewHolder(v) + override fun getViewHolder(v: View): FastAdapter.ViewHolder { + return if (category.id == -1) { + ShowAllViewHolder(Injekt.get().showAllCategories(), v) + } else { + ViewHolder(v) + } } class ViewHolder(view: View) : FastAdapter.ViewHolder(view) { @@ -33,4 +49,19 @@ AbstractItem() { categoryTitle.text = null } } + + class ShowAllViewHolder(val pref: Preference, view: View) : + FastAdapter.ViewHolder(view) { + + val checkbox: CheckBox? = view.findViewById(R.id.auto_checkbox) + + init { + checkbox?.setText(R.string.show_all_categories) + } + + override fun bindView(item: CategoryItem, payloads: List) { + checkbox?.isChecked = pref.get() + } + override fun unbindView(item: CategoryItem) {} + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryRecyclerView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryRecyclerView.kt index 1275af58c2..f805f38aef 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryRecyclerView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/category/CategoryRecyclerView.kt @@ -2,16 +2,19 @@ package eu.kanade.tachiyomi.ui.library.category import android.content.Context import android.util.AttributeSet +import android.view.View import android.view.ViewGroup +import android.widget.CheckBox import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.mikepenz.fastadapter.FastAdapter import com.mikepenz.fastadapter.adapters.ItemAdapter +import com.mikepenz.fastadapter.listeners.CustomEventHook import com.mikepenz.fastadapter.listeners.OnBindViewHolderListenerImpl import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Category +import eu.kanade.tachiyomi.data.database.models.CategoryImpl import eu.kanade.tachiyomi.util.view.marginBottom -import eu.kanade.tachiyomi.util.view.marginTop class CategoryRecyclerView @JvmOverloads constructor( context: Context, @@ -21,8 +24,12 @@ class CategoryRecyclerView @JvmOverloads constructor( val manager = LinearLayoutManager(context) private val fastAdapter: FastAdapter var onCategoryClicked: (Int) -> Unit = { _ -> } + var onShowAllClicked: (Boolean) -> Unit = { } private val itemAdapter = ItemAdapter() var selectedCategory: Int = 0 + val headerItem = CategoryItem(CategoryImpl().apply { + id = -1 + }) init { fastAdapter = FastAdapter.with(itemAdapter) @@ -31,35 +38,52 @@ class CategoryRecyclerView @JvmOverloads constructor( } fun setCategories(items: List) { - itemAdapter.set(items.map(::CategoryItem)) - fastAdapter.onBindViewHolderListener = (object : OnBindViewHolderListenerImpl() { - override fun onBindViewHolder( - viewHolder: ViewHolder, - position: Int, - payloads: List - ) { - super.onBindViewHolder(viewHolder, position, payloads) - (viewHolder as? CategoryItem.ViewHolder)?.categoryTitle?.isSelected = - selectedCategory == position - } - }) + itemAdapter.set(listOf(headerItem) + items.map(::CategoryItem)) + fastAdapter.onBindViewHolderListener = + (object : OnBindViewHolderListenerImpl() { + override fun onBindViewHolder( + viewHolder: ViewHolder, + position: Int, + payloads: List + ) { + super.onBindViewHolder(viewHolder, position, payloads) + (viewHolder as? CategoryItem.ViewHolder)?.categoryTitle?.isSelected = + selectedCategory + 1 == position + } + }) fastAdapter.onClickListener = { _, _, item, _ -> - onCategoryClicked(item.category.order) + if (item.category.id != -1) + onCategoryClicked(item.category.order) true } + fastAdapter.addEventHook(object : CustomEventHook() { + override fun onBind(viewHolder: ViewHolder): View? { + return if (viewHolder is CategoryItem.ShowAllViewHolder) { + viewHolder.checkbox + } else { + null + } + } + + override fun attachEvent(view: View, viewHolder: ViewHolder) { + (view as? CheckBox)?.setOnCheckedChangeListener { _, isChecked -> + onShowAllClicked(isChecked) + } + } + }) } fun setCategories(selected: Int) { selectedCategory = selected for (i in 0..manager.itemCount) { (findViewHolderForAdapterPosition(i) as? CategoryItem.ViewHolder)?.categoryTitle?.isSelected = - selectedCategory == i + selectedCategory + 1 == i } } override fun onMeasure(widthSpec: Int, heightSpec: Int) { val recyclerView = (parent.parent as ViewGroup).findViewById(R.id.recycler) - val top = recyclerView.marginTop + val top = recyclerView.paddingTop val bottom = recyclerView.marginBottom val parent = recyclerView.measuredHeight - top - bottom val heightS = if (parent > 0) diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/view/ControllerExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/view/ControllerExtensions.kt index 8c22f22fba..5fa6447ead 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/view/ControllerExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/view/ControllerExtensions.kt @@ -96,7 +96,7 @@ fun Controller.scrollViewWith( elevate = el if (liftOnScroll != null) { liftOnScroll.invoke(el) - } else { + } else if (recycler.translationY == 0f) { elevationAnim?.cancel() elevationAnim = ValueAnimator.ofFloat( activity!!.appbar.elevation, if (el) 15f else 0f @@ -158,7 +158,9 @@ fun Controller.scrollViewWith( override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { super.onScrolled(recyclerView, dx, dy) if (router?.backstack?.lastOrNull() - ?.controller() == this@scrollViewWith && statusBarHeight > -1 && activity != null && activity!!.appbar.height > 0 + ?.controller() == this@scrollViewWith && statusBarHeight > -1 && + activity != null && activity!!.appbar.height > 0 && + recycler.translationY == 0f ) { if (!recycler.canScrollVertically(-1)) { val shortAnimationDuration = resources?.getInteger( @@ -185,7 +187,9 @@ fun Controller.scrollViewWith( super.onScrollStateChanged(recyclerView, newState) if (newState == RecyclerView.SCROLL_STATE_IDLE) { if (router?.backstack?.lastOrNull() - ?.controller() == this@scrollViewWith && statusBarHeight > -1 && activity != null && activity!!.appbar.height > 0 + ?.controller() == this@scrollViewWith && statusBarHeight > -1 && + activity != null && activity!!.appbar.height > 0 && + recycler.translationY == 0f ) { val halfWay = abs((-activity!!.appbar.height.toFloat()) / 2) val shortAnimationDuration = resources?.getInteger( diff --git a/app/src/main/res/layout/library_list_controller.xml b/app/src/main/res/layout/library_list_controller.xml index 7366ede656..f091ab494a 100644 --- a/app/src/main/res/layout/library_list_controller.xml +++ b/app/src/main/res/layout/library_list_controller.xml @@ -8,9 +8,9 @@ + android:layout_height="75dp" + android:layout_gravity="center" /> - - + android:orientation="vertical"> + + - + android:layout_height="8dp" + android:alpha="0.1" + android:background="@drawable/shape_gradient_top_shadow" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" /> + + android:alpha="0" + android:background="?android:colorBackground" /> @@ -61,16 +66,16 @@