Search code examples
androidkotlinandroid-collapsingtoolbarlayoutandroid-appbarlayout

Enable snap scrolling in colloapsing toolbar layout only when scrolling upwards


I am trying to enable snap scrolling in collapsing toolbar in app bar layout only when scroll direction is upwards. Like scrolling up 50% of the app bar content should expand or collapse the toolbar. Scrolling downwards should not enable snap behavior in the collapsing toolbar layout and should behave like normal scroll.

Below is the code that I've tried so far,

appBarLayout.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset ->
            val viewHeight = abs(appBarLayout.totalScrollRange) - abs(verticalOffset)
            val viewingPercentage =
                viewHeight.toFloat() / abs(appBarLayout.totalScrollRange).toFloat()
            

            if(isToolBarHalfScrolled && viewingPercentage >= .5f){
                isToolBarHalfScrolled = false
                val params: AppBarLayout.LayoutParams =
                    collapsing_toolbar.layoutParams as AppBarLayout.LayoutParams
                params.scrollFlags = SCROLL_FLAG_SNAP or SCROLL_FLAG_SCROLL
                collapsing_toolbar.layoutParams = params
            } else if(!isToolBarHalfScrolled && viewingPercentage < .5f){
                isToolBarHalfScrolled = true
                val params: AppBarLayout.LayoutParams =
                    collapsing_toolbar.layoutParams as AppBarLayout.LayoutParams
                params.scrollFlags = SCROLL_FLAG_SCROLL
                collapsing_toolbar.layoutParams = params
            }
            
        })

Solution

  • I am checking if the value of the vertical offset is increasing or decreasing to determine if the appbarlayout is being scroll up or down. Below is the code,

    var nowVerticalOffset = 0
    var thenVerticalOffset = 0
    appBarLayout.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset ->
            val viewHeight = abs(appBarLayout.totalScrollRange) - abs(verticalOffset)
            val viewingPercentage =
                viewHeight.toFloat() / abs(appBarLayout.totalScrollRange).toFloat()
            
    
            nowVerticalOffset = (verticalOffset*-1)
            if (nowVerticalOffset > thenVerticalOffset) {
                if(!isToolBarHalfScrolled){
                    isToolBarHalfScrolled = true
                    val params: AppBarLayout.LayoutParams =
                        collapsing_toolbar.layoutParams as AppBarLayout.LayoutParams
                    params.scrollFlags = SCROLL_FLAG_SCROLL
                    collapsing_toolbar.layoutParams = params
                }
            } else if ( nowVerticalOffset < thenVerticalOffset) {
                if (isToolBarHalfScrolled && (viewingPercentage >= .5f || viewingPercentage < .5f)) {
                    isToolBarHalfScrolled = false
                    val params: AppBarLayout.LayoutParams =
                        collapsing_toolbar.layoutParams as AppBarLayout.LayoutParams
                    params.scrollFlags = SCROLL_FLAG_SNAP or SCROLL_FLAG_SCROLL
                    collapsing_toolbar.layoutParams = params
                }
            }
            thenVerticalOffset = nowVerticalOffset
            
        })