Git Product home page Git Product logo

compose-fractal-nav's Introduction

compose-fractal-nav

A proof-of-concept of a fractal/recursive navigation system.

Instead of defining a bunch of top-level routes with navigation moving laterally between them, you define your navigation recursively. You can think of it like showing your entire composable UI at once, where certain parts can be zoomed-into. It's hard to explain and I'm writing this README after 3 straight days of hacking on my vacation, so easier to just show you. This is the app in this repo:

fractal-nav-long-demo.mp4

API

Like most navigation libraries, this one starts with a wrapper composable that defines the navigable area. It's called FractalNavHost. It provides a FractalNavScope to its content composable. Inside that block, you can define "zoomable" children with the FractalNavChild composable. Each child is identified with a string key, and you can zoom into a child by calling zoomToChild().

The content block of a FractalNavChild gets access to a few properties that describe whether or not it's zoomed in, how far it's zoomed, and a function that zooms it back out to its parent.

Children can also define their own children, recursing as deep as you like. The library will only compose what's necessary to show the active child. Everything between the FractalNavHost and the FractalNavChild will be removed from the composition – even when multiple children are nested. When a child zooms back out, its parent content is composed again, with any state from rememberSaveables restored.

For more details, take a look at FractalNavScope and FractalNavChildScope.

API sample

Let's build this simple app:

sample-demo.mp4

Here's the code:

// The host should wrap the root of your app.
FractalNavHost(Modifier.fillMaxSize()) {
    Row(Modifier.wrapContentSize()) {
        Text("Click ")
        Link("here") {
            Text(
                "42",
                // Scale the text in when clicked.
                modifier = Modifier.scaleByZoomFactor(),
                style = MaterialTheme.typography.h1,
                maxLines = 1
            )
        }
        Text(" to learn more.")
    }
}

And here's the Link function:

@Composable
fun FractalNavScope.Link(
    text: String,
    content: @Composable FractalNavChildScope.() -> Unit
) {
    // This creates some content that can be zoomed into.
    FractalNavChild(
        // It's identified by a string key…
        key = "link",
        modifier = Modifier.clickable {
            // …which can be used to expand its content. This will animate
            // the content block below to take up the full screen and also
            // zoom the parent content, that called this composable, out of
            // view.
            zoomToChild("link")
        }
    ) {
        Box(contentAlignment = Alignment.Center) {
            Text(text, Modifier.graphicsLayer {
                // The zoomFactor property is available inside the FractalNavChild
                // block. It starts at 0, then when zoomToChild is called it will
                // be animated up to 1. In this case, we want this text to start
                // at the full size and shrink when zoomed in.
                alpha = 1f - zoomFactor
            })

            // The isActive flag is also provided inside the FractalNavChild
            // content block, and means `zoomFactor > 0` – but is backed by
            // a derivedStateOf so it won't invalidate more than once during
            // the zoom animation.
            if (isActive) {
                content()
                BackHandler {
                    // This will animate zoomFactor back down to 0.
                    zoomToParent()
                }
            }
        }
    }
}

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.