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

Overview

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:

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() } } } } }">
@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()
                }
            }
        }
    }
}
You might also like...
Sae Hoon Scheduling System With Kotlin
Sae Hoon Scheduling System With Kotlin

SaeHoonSchedulingSystem 약속을 편하게 관리할 수 있는 안드로이드 어플리케이션 입니다. Getting Started / 어떻게 시작하나요? SaeHoon's Scheduling System Api Server를 먼저 실행 후 Android Studio

Android app with a simple NFC payment system to manage visitor consumption at short-duration events and festivals. (Research project)
Android app with a simple NFC payment system to manage visitor consumption at short-duration events and festivals. (Research project)

Clevent Também disponível em Português Clevent is an Android application developed for a Undergraduate Research that uses NFC technology to create a p

Real time gps location based alarming system tracking the road accident and providing medical assitance plus concern from near by police station.
Real time gps location based alarming system tracking the road accident and providing medical assitance plus concern from near by police station.

Real time gps location based alarming system tracking the road accident and providing medical assitance plus concern from near by police station.

The App Store for the BlazeOS operating system project.

By: Seanpm2001, Et; Al. Top README.md Read this article in a different language Sorted by: A-Z Sorting options unavailable ( af Afrikaans Afrikaans |

A semi-official port of the open source Anki spaced repetition flashcard system to Android
A semi-official port of the open source Anki spaced repetition flashcard system to Android

AnkiDroid A semi-official port of the open source Anki spaced repetition flashcard system to Android. Memorize anything with AnkiDroid! Features night

Android-easy-permissions-kt - EasyPermissionsKt - A lightweight Android library that abstracts all runtime permission boilerplate code to simplify the system permissions managemen Simple media hosting system written in kotlin.
Simple media hosting system written in kotlin.

media-server This project is a simple media server implementation that allows you to upload and share files. This project was made in Kotlin and HTML,

AVTS App - S.I.T Global PBL 2021 - Automatic Visitor Tracking System Android Application

S.I.T Global PBL 2021 - Automatic Visitor Tracking System Android Application De

MyTraining - Application project for Android system using Kotlin
MyTraining - Application project for Android system using Kotlin

MyTraining Projeto de aplicação para sistema Android utilizando linguagem Kotlin

Comments
  • Add support for multiplatform

    Add support for multiplatform

    This library looks cool, going through the dependencies, it seems that you don't depend on android only code, it could be migrated to compose-jb to make it available for Desktop as well(web and iOS in the future).

    opened by dragossusi 0
  • Support restoring navigation state from saved state

    Support restoring navigation state from saved state

    • FractalNavState should have a Saver implementation that stores only the string key of the active child.
    • When restoring it puts that key in a property in the state: childToRestore: String.
    • When FractalNavChild is called it checks if the state has a key to restore. If that key matches its key, then during composition it updates the state to look as though a zoom in just finished: sets the state's activeChild and snaps the zoom factor to 1 (direction is left null). Since activeChild is now the current child, it won't call its movable content in place.
    • When the content finishes composing, the host will compose the now-active child itself, and immediately recompose to remove the content from the composition.
    • The content should have a layout modifier that checks if the content is about to be removed for this restore case and, if so, doesn't measure or place it.
    • If the content doesn't use SubcomposeLayout, that's it. When the content finishes
    • Otherwise, there are two more cases to handle since the child to restore might only be composed during the measure or placement phases.
    • If the content's layout modifier sees that the child to restore hasn't been composed yet, it should measure the content, then check again.
    • If the active child has been set after measure, that means it was subcomposed during measure. It should not place the content. The next composition will compose the child in the main composition.
    • If no active child has been set after measure, then place it and check again to see if it was subcomposed during placement.

    In addition,

    • The content should check after every phase (composition, measure, placement) to see if a child is being restored, and only participate in as many phases as necessary to determine that. Subsequent phases should be skipped (don't measure, don't place, don't draw) to avoid unnecessary work but more importantly to avoid drawing the content on the first frame.
    • If the child to restore is subcomposed after the initial composition pass, then we need to make sure the child's movable content is actually present in the composition somewhere. We can still have it draw for the first frame: The host's composition should check if it is trying to restore a child but the child has not been composed yet after the content composable returns. If so, it should compose a SubcomposeLayout that checks for the child to restore after measure and placement passes, and if it finds one, subcomposes its movable content to fill the viewport. On the next frame, the subcompose layout will be removed and the movable content will be moved to the main composition.
    opened by zach-klippenstein 0
Owner
Zach Klippenstein
Engineer at Google, previously Square, Amazon. Opinions my own.
Zach Klippenstein
A bare minimum proof-of-concept for Log4j2 JNDI RCE vulnerability (CVE-2021-44228/Log4Shell)

Log4j2 RCE Vulnerability POC A bare minimum proof-of-concept for Log4j2 JNDI Remote-Code-Execution vulnerability (CVE-2021-44228). This is intended fo

Sola 4 Aug 17, 2022
STxMobile is a proof of concept of an Android app for remotely controlling the Raymarine ST2000+ tiller pilot from an Android phone.

STxMobile STxMobile is a proof of concept of an Android app for remotely controlling the Raymarine ST2000+ tiller pilot from an Android phone. The app

Marco 8 Sep 1, 2022
Simple bottom navigation with side navigation drawer using Jetpack navigation UI made in Kotlin

BottomNavWithSideNavApp simple bottom navigation with side navigation drawer usi

Arvind Meshram 6 Oct 31, 2022
Implementation of Instagram with Material Design (originally based on Emmanuel Pacamalan's concept)

InstaMaterial Updated Current source code contains UI elements from Design Support Library. If you still want to see how custom implementations of e.g

Mirosław Stanek 5k Dec 27, 2022
Words App which acts as a dictionary. Use the concept of Intent.

Words App This folder contains the source code for the Words app codelab. Introduction Words app allows you to select a letter and use Intents to navi

Naman Agarwal 6 Dec 6, 2021
Space recommendation system and augmenting informations with ARCore SDK

Space recommendation system and augmenting informations with ARCore SDK

PNU-Sinbaram 4 Sep 3, 2021
An unofficial companion app for DJI's Digital FPV System.

fpv-dvca An unofficial companion app for DJI's Digital FPV System for Android devices. Plug your Android device into your Googles and watch a live fee

Matthias Urhahn 73 Dec 12, 2022
Android Mobile Application for Movie Reservation System.

Movie-Reservation-Android-App Android Mobile Application for Movie Reservation System Brief Description of the Project ?? “BlueSky Cinema” is an onlin

M. D. Janani Malshika 1 Oct 10, 2021
An android app that lists all planets in our solar system and brings some information about them.

SolarSystem This application was developed in Android Studio and uses Kotlin as programming language. In short, it is an app that lists all the planet

Dayon Oliveira 0 Nov 3, 2021
Phone booking system with kotlin

phone-booking-system Too lazy to introspect openapi? No worries, basic CURLs below; however, one needs to start the docker-compose file located in the

Dan Zaru 0 Nov 7, 2021