Coder Social home page Coder Social logo

Comments (6)

osipxd avatar osipxd commented on September 4, 2024 2

This workaround works for me:

@Composable
public fun CollapsingToolbarScaffold(
    state: CollapsingToolbarScaffoldState,
    modifier: Modifier = Modifier,
    scrollStrategy: ScrollStrategy = ScrollStrategy.ExitUntilCollapsed,
    enabled: Boolean = true,
    toolbarModifier: Modifier = Modifier,
    toolbar: @Composable CollapsingToolbarScope.() -> Unit,
    content: @Composable BoxWithConstraintsScope.() -> Unit,
) {
    var collapsable by remember { mutableStateOf(false) }

    LaunchedEffect(collapsable) {
        @OptIn(ExperimentalToolbarApi::class)
        if (!collapsable) state.toolbarState.expand()
    }

    CollapsingToolbarScaffold(
        modifier = modifier,
        toolbarModifier = toolbarModifier,
        state = state,
        enabled = collapsable && enabled, // Force disable collapsing if it is not needed
        scrollStrategy = scrollStrategy,
        toolbar = toolbar,
        body = {
            var contentHeight by remember { mutableStateOf(0) }
            BoxWithConstraints(Modifier.onGloballyPositioned { contentHeight = it.size.height }) {
                collapsable = with(LocalDensity.current) {
                    val toolbarMaxOffset = state.toolbarState.maxHeight - state.toolbarState.minHeight
                    contentHeight > maxHeight.toPx() - toolbarMaxOffset
                }
                content()
            }
        },
    )
}

UPD: Simplified workaround

Look at the first version of workaround
@Composable
public fun CollapsingToolbarScaffold(
    state: CollapsingToolbarScaffoldState,
    modifier: Modifier = Modifier,
    scrollStrategy: ScrollStrategy = ScrollStrategy.ExitUntilCollapsed,
    enabled: Boolean = true,
    toolbarModifier: Modifier = Modifier,
    toolbar: @Composable CollapsingToolbarScope.() -> Unit,
    content: @Composable CollapsingToolbarContentScope.() -> Unit,
) {
    CollapsingToolbarScaffold(
        modifier = modifier,
        toolbarModifier = toolbarModifier,
        state = state,
        enabled = enabled,
        scrollStrategy = scrollStrategy,
        toolbar = toolbar,
        body = {
            var contentHeight by remember { mutableStateOf(0) }
            BoxWithConstraints(Modifier.onGloballyPositioned { contentHeight = it.size.height }) {
                CollapsingToolbarContentScopeImpl(
                    scope = this,
                    density = LocalDensity.current,
                    toolbarOffset = state.toolbarState.maxHeight - state.toolbarState.minHeight,
                    contentHeightPx = contentHeight,
                ).content()
            }
        },
    )
}

@Stable
public interface CollapsingToolbarContentScope : BoxWithConstraintsScope {
    /** The content height in [Dp]. */
    public val contentHeight: Dp

    /** The max height that may fit without toolbar collapsing. */
    public val maxHeightWhenExpanded: Dp

    /** Returns `true` if content can not fit on screen without toolbar collapsing. */
    public val collapsingNeeded: Boolean
}

private data class CollapsingToolbarContentScopeImpl(
    private val scope: BoxWithConstraintsScope,
    private val density: Density,
    private val toolbarOffset: Int,
    private val contentHeightPx: Int,
) : CollapsingToolbarContentScope, BoxWithConstraintsScope by scope {

    override val contentHeight: Dp
        get() = with(density) { contentHeightPx.toDp() }
    override val maxHeightWhenExpanded: Dp
        get() = maxHeight - with(density) { toolbarOffset.toDp() }
    override val collapsingNeeded: Boolean
        get() = contentHeight > maxHeightWhenExpanded
}

With this you can disable scrolling and make toolbar always expanded if content fits on the screen looking at collapsingNeeded flag in CollapsingToolbarContentScope:

val state = rememberCollapsingToolbarScaffoldState()
CollapsingToolbarScaffold(
    state = state,
    toolbar = { /* Toolbar content here */ }
) {
    LaunchedEffect(collapsingNeeded) {
        // We don't want the state when scroll is disabled but toolbar is not expanded
        @OptIn(ExperimentalToolbarApi::class)
        if (!collapsingNeeded) state.toolbarState.expand()
    }

    Column(
        // Disable scrolling if content fits on screen
        modifier = Modifier.verticalScroll(rememberScrollState(), enabled = collapsingNeeded),
    ) {
        // Content here
    }
}

from compose-collapsing-toolbar.

onebone avatar onebone commented on September 4, 2024

I looked into the behavior of androidx's CollapsingToolbarLayout, looks like it collapses only if the height of a body layout is large enough to scroll which is different from the current behavior of my library.
One point I want to think of is when the height of the body layout is somewhere between body hole + collapsed toolbar and body hole + expanded toolbar. AndroidX leaves some space if the actual height of body layout is smaller than that of body hole, maybe I could give some options to choose this behavior?

스크린샷 2022-03-07 오후 11 38 29

from compose-collapsing-toolbar.

edharkhimich avatar edharkhimich commented on September 4, 2024

Thank you for so quick response.

Yes, in CollapsingToolbarLayout it checks if the content height is more than the screen height and only then make it collapsable when scrolling.
In your library it scrolls and collapse always.

Sorry but I didn't get your question:
AndroidX leaves some space if the actual height of body layout is smaller than that of body hole, maybe I could give some options to choose this behavior?

Could you please rephrase it ?

from compose-collapsing-toolbar.

osipxd avatar osipxd commented on September 4, 2024

Is there any workaround for this case? For example disable vertical scroll if content fits to screen. But how to detect "if content fits"?

from compose-collapsing-toolbar.

onebone avatar onebone commented on September 4, 2024

I meant the edge case where the body content's height is not tall enough to cover the whole screen when the toolbar is collapsed but it fills the screen when toolbar is expanded.
By the way, I didn't tested myself though did you try calculating available height with CollapsingToolbarState.maxHeight as a workaround?

from compose-collapsing-toolbar.

GIGAMOLE avatar GIGAMOLE commented on September 4, 2024

Hi, I have already created PR for this: #85

By the way, if you want to use this feature, I created a separated remote dependency, while this PR is under review:

Add it in your root build.gradle at the end of repositories:

all projects {
	repositories {
		...
		maven { url 'https://jitpack.io' }
	}
}

Step 2. Add the dependency

dependencies {
        implementation 'com.github.GIGAMOLE:ComposeCollapsingToolbar:latest-version'
}

Or you can simply download it from there:

https://github.com/GIGAMOLE/ComposeCollapsingToolbar/releases

from compose-collapsing-toolbar.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.