mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	@@ -31,12 +31,14 @@ import eu.kanade.tachiyomi.ui.base.controller.NucleusController
 | 
			
		||||
import eu.kanade.tachiyomi.ui.base.controller.SecondaryDrawerController
 | 
			
		||||
import eu.kanade.tachiyomi.ui.base.controller.TabbedController
 | 
			
		||||
import eu.kanade.tachiyomi.ui.category.CategoryController
 | 
			
		||||
import eu.kanade.tachiyomi.ui.main.MainActivity
 | 
			
		||||
import eu.kanade.tachiyomi.ui.manga.MangaController
 | 
			
		||||
import eu.kanade.tachiyomi.util.inflate
 | 
			
		||||
import eu.kanade.tachiyomi.util.toast
 | 
			
		||||
import eu.kanade.tachiyomi.widget.DrawerSwipeCloseListener
 | 
			
		||||
import kotlinx.android.synthetic.main.activity_main.*
 | 
			
		||||
import kotlinx.android.synthetic.main.library_controller.view.*
 | 
			
		||||
import rx.Subscription
 | 
			
		||||
import timber.log.Timber
 | 
			
		||||
import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
@@ -118,6 +120,10 @@ class LibraryController(
 | 
			
		||||
     */
 | 
			
		||||
    private var drawerListener: DrawerLayout.DrawerListener? = null
 | 
			
		||||
 | 
			
		||||
    private var tabsVisibilityRelay: BehaviorRelay<Boolean> = BehaviorRelay.create()
 | 
			
		||||
 | 
			
		||||
    private var tabsVisibilitySubscription: Subscription? = null
 | 
			
		||||
 | 
			
		||||
    init {
 | 
			
		||||
        setHasOptionsMenu(true)
 | 
			
		||||
    }
 | 
			
		||||
@@ -173,6 +179,8 @@ class LibraryController(
 | 
			
		||||
        super.onDestroyView(view)
 | 
			
		||||
        adapter = null
 | 
			
		||||
        actionMode = null
 | 
			
		||||
        tabsVisibilitySubscription?.unsubscribe()
 | 
			
		||||
        tabsVisibilitySubscription = null
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun createSecondaryDrawer(drawer: DrawerLayout): ViewGroup {
 | 
			
		||||
@@ -204,6 +212,27 @@ class LibraryController(
 | 
			
		||||
        navView = null
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun configureTabs(tabs: TabLayout) {
 | 
			
		||||
        with(tabs) {
 | 
			
		||||
            tabGravity = TabLayout.GRAVITY_CENTER
 | 
			
		||||
            tabMode = TabLayout.MODE_SCROLLABLE
 | 
			
		||||
        }
 | 
			
		||||
        tabsVisibilitySubscription?.unsubscribe()
 | 
			
		||||
        tabsVisibilitySubscription = tabsVisibilityRelay.subscribe { visible ->
 | 
			
		||||
            val tabAnimator = (activity as? MainActivity)?.tabAnimator
 | 
			
		||||
            if (visible) {
 | 
			
		||||
                tabAnimator?.expand()
 | 
			
		||||
            } else {
 | 
			
		||||
                tabAnimator?.collapse()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun cleanupTabs(tabs: TabLayout) {
 | 
			
		||||
        tabsVisibilitySubscription?.unsubscribe()
 | 
			
		||||
        tabsVisibilitySubscription = null
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun onNextLibraryUpdate(categories: List<Category>, mangaMap: Map<Int, List<LibraryItem>>) {
 | 
			
		||||
        val view = view ?: return
 | 
			
		||||
        val adapter = adapter ?: return
 | 
			
		||||
@@ -227,7 +256,7 @@ class LibraryController(
 | 
			
		||||
        // Restore active category.
 | 
			
		||||
        view.view_pager.setCurrentItem(activeCat, false)
 | 
			
		||||
 | 
			
		||||
        tabs?.visibility = if (categories.size <= 1) View.GONE else View.VISIBLE
 | 
			
		||||
        tabsVisibilityRelay.call(categories.size > 1)
 | 
			
		||||
 | 
			
		||||
        // Delay the scroll position to allow the view to be properly measured.
 | 
			
		||||
        view.post {
 | 
			
		||||
@@ -282,13 +311,6 @@ class LibraryController(
 | 
			
		||||
        adapter.recycle = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun configureTabs(tabs: TabLayout) {
 | 
			
		||||
        with(tabs) {
 | 
			
		||||
            tabGravity = TabLayout.GRAVITY_CENTER
 | 
			
		||||
            tabMode = TabLayout.MODE_SCROLLABLE
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates the action mode if it's not created already.
 | 
			
		||||
     */
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@ class MainActivity : BaseActivity() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private val tabAnimator by lazy { TabsAnimator(tabs) }
 | 
			
		||||
    lateinit var tabAnimator: TabsAnimator
 | 
			
		||||
 | 
			
		||||
    override fun onCreate(savedInstanceState: Bundle?) {
 | 
			
		||||
        setAppTheme()
 | 
			
		||||
@@ -69,6 +69,8 @@ class MainActivity : BaseActivity() {
 | 
			
		||||
        drawerArrow?.color = Color.WHITE
 | 
			
		||||
        toolbar.navigationIcon = drawerArrow
 | 
			
		||||
 | 
			
		||||
        tabAnimator = TabsAnimator(tabs)
 | 
			
		||||
 | 
			
		||||
        // Set behavior of Navigation drawer
 | 
			
		||||
        nav_view.setNavigationItemSelectedListener { item ->
 | 
			
		||||
            val id = item.itemId
 | 
			
		||||
@@ -190,8 +192,8 @@ class MainActivity : BaseActivity() {
 | 
			
		||||
            from.cleanupTabs(tabs)
 | 
			
		||||
        }
 | 
			
		||||
        if (to is TabbedController) {
 | 
			
		||||
            to.configureTabs(tabs)
 | 
			
		||||
            tabAnimator.expand()
 | 
			
		||||
            to.configureTabs(tabs)
 | 
			
		||||
        } else {
 | 
			
		||||
            tabAnimator.collapse()
 | 
			
		||||
            tabs.setupWithViewPager(null)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.main
 | 
			
		||||
 | 
			
		||||
import android.support.design.widget.TabLayout
 | 
			
		||||
import android.view.View
 | 
			
		||||
import android.view.ViewTreeObserver
 | 
			
		||||
import android.view.animation.Animation
 | 
			
		||||
import android.view.animation.DecelerateInterpolator
 | 
			
		||||
import android.view.animation.Transformation
 | 
			
		||||
@@ -9,15 +11,32 @@ import eu.kanade.tachiyomi.util.visible
 | 
			
		||||
 | 
			
		||||
class TabsAnimator(val tabs: TabLayout) {
 | 
			
		||||
 | 
			
		||||
    private var height = 0
 | 
			
		||||
    /**
 | 
			
		||||
     * The default height of the tab layout. It's unknown until the view is layout.
 | 
			
		||||
     */
 | 
			
		||||
    private var tabsHeight = 0
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Whether the last state of the tab layout is [View.VISIBLE] or [View.GONE].
 | 
			
		||||
     */
 | 
			
		||||
    private var isLastStateShown = true
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Interpolator used to animate the tab layout.
 | 
			
		||||
     */
 | 
			
		||||
    private val interpolator = DecelerateInterpolator()
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Duration of the animation.
 | 
			
		||||
     */
 | 
			
		||||
    private val duration = 300L
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Animation used to expand the tab layout.
 | 
			
		||||
     */
 | 
			
		||||
    private val expandAnimation = object : Animation() {
 | 
			
		||||
        override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
 | 
			
		||||
            tabs.layoutParams.height = (height * interpolatedTime).toInt()
 | 
			
		||||
            setHeight((tabsHeight * interpolatedTime).toInt())
 | 
			
		||||
            tabs.requestLayout()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -26,12 +45,24 @@ class TabsAnimator(val tabs: TabLayout) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Animation used to collapse the tab layout.
 | 
			
		||||
     */
 | 
			
		||||
    private val collapseAnimation = object : Animation() {
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Property holding the height of the tabs at the moment the animation is started. Useful
 | 
			
		||||
         * to provide a seamless animation.
 | 
			
		||||
         */
 | 
			
		||||
        private var startHeight = 0
 | 
			
		||||
 | 
			
		||||
        override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
 | 
			
		||||
            if (interpolatedTime == 1f) {
 | 
			
		||||
            if (interpolatedTime == 0f) {
 | 
			
		||||
                startHeight = tabs.height
 | 
			
		||||
            } else if (interpolatedTime == 1f) {
 | 
			
		||||
                tabs.gone()
 | 
			
		||||
            } else {
 | 
			
		||||
                tabs.layoutParams.height = (height * (1 - interpolatedTime)).toInt()
 | 
			
		||||
                setHeight((startHeight * (1 - interpolatedTime)).toInt())
 | 
			
		||||
                tabs.requestLayout()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -46,29 +77,75 @@ class TabsAnimator(val tabs: TabLayout) {
 | 
			
		||||
        collapseAnimation.interpolator = interpolator
 | 
			
		||||
        expandAnimation.duration = duration
 | 
			
		||||
        expandAnimation.interpolator = interpolator
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun expand() {
 | 
			
		||||
        tabs.visible()
 | 
			
		||||
        if (measure() && tabs.measuredHeight != height) {
 | 
			
		||||
            tabs.startAnimation(expandAnimation)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
        isLastStateShown = tabs.visibility == View.VISIBLE
 | 
			
		||||
        tabs.viewTreeObserver.addOnGlobalLayoutListener(
 | 
			
		||||
            object : ViewTreeObserver.OnGlobalLayoutListener {
 | 
			
		||||
                override fun onGlobalLayout() {
 | 
			
		||||
                    if (tabs.height > 0) {
 | 
			
		||||
                        tabs.viewTreeObserver.removeOnGlobalLayoutListener(this)
 | 
			
		||||
 | 
			
		||||
    fun collapse() {
 | 
			
		||||
        if (measure() && tabs.measuredHeight != 0) {
 | 
			
		||||
            tabs.startAnimation(collapseAnimation)
 | 
			
		||||
        } else {
 | 
			
		||||
            tabs.gone()
 | 
			
		||||
        }
 | 
			
		||||
                        // Save the tabs default height.
 | 
			
		||||
                        tabsHeight = tabs.height
 | 
			
		||||
 | 
			
		||||
                        // Now that we know the height, set the initial height and visibility.
 | 
			
		||||
                        if (isLastStateShown) {
 | 
			
		||||
                            setHeight(tabsHeight)
 | 
			
		||||
                            tabs.visible()
 | 
			
		||||
                        } else {
 | 
			
		||||
                            setHeight(0)
 | 
			
		||||
                            tabs.gone()
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns true if the view is measured, otherwise query dimensions and check again.
 | 
			
		||||
     * Sets the height of the tab layout.
 | 
			
		||||
     *
 | 
			
		||||
     * @param newHeight The new height of the tab layout.
 | 
			
		||||
     */
 | 
			
		||||
    private fun measure(): Boolean {
 | 
			
		||||
        if (height > 0) return true
 | 
			
		||||
        height = tabs.measuredHeight
 | 
			
		||||
        return height > 0
 | 
			
		||||
    private fun setHeight(newHeight: Int) {
 | 
			
		||||
        tabs.layoutParams.height = newHeight
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Expands the tab layout with an animation.
 | 
			
		||||
     */
 | 
			
		||||
    fun expand() {
 | 
			
		||||
        cancelCurrentAnimations()
 | 
			
		||||
        tabs.visible()
 | 
			
		||||
        if (isMeasured && (!isLastStateShown || tabs.height != tabsHeight)) {
 | 
			
		||||
            tabs.startAnimation(expandAnimation)
 | 
			
		||||
        }
 | 
			
		||||
        isLastStateShown = true
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Collapse the tab layout with an animation.
 | 
			
		||||
     */
 | 
			
		||||
    fun collapse() {
 | 
			
		||||
        cancelCurrentAnimations()
 | 
			
		||||
        if (isMeasured && (isLastStateShown || tabs.height != 0)) {
 | 
			
		||||
            tabs.startAnimation(collapseAnimation)
 | 
			
		||||
        }
 | 
			
		||||
        isLastStateShown = false
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Cancels all the currently running animations.
 | 
			
		||||
     */
 | 
			
		||||
    private fun cancelCurrentAnimations() {
 | 
			
		||||
        collapseAnimation.cancel()
 | 
			
		||||
        expandAnimation.cancel()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns whether the tab layout has a known height.
 | 
			
		||||
     */
 | 
			
		||||
    val isMeasured: Boolean
 | 
			
		||||
        get() = tabsHeight > 0
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -24,7 +24,6 @@
 | 
			
		||||
                android:id="@+id/tabs"
 | 
			
		||||
                android:layout_width="match_parent"
 | 
			
		||||
                android:layout_height="wrap_content"
 | 
			
		||||
                android:visibility="gone"
 | 
			
		||||
                android:theme="@style/Theme.ActionBar.Tab"
 | 
			
		||||
                app:tabIndicatorColor="@android:color/white"
 | 
			
		||||
                app:tabGravity="center"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user