How to Get up and Running with Turbo Android Part 2 - Feel More Native

williamkennedy

William Kennedy

Posted on May 23, 2023

How to Get up and Running with Turbo Android Part 2 - Feel More Native

So far, we’ve covered getting up and running with Turbo Android. Now we can move on to the fun part of Turbo Android, which is about making it feel more native. Compared to Turbo-ios, Turbo Android has a lot built into the framework and can easily route different endpoints.

Getting Setup with Modals

You may have noticed that the Android app doesn’t feel very native. Instead, it feels like a webpage inside an app’s skin. Luckily, we can add some quick changes utilising Turbo Fragments found in the Turbo-Android library. By inheriting from these and updating out Path Configuration, we have routes display different Turbo Fragments.

For now, we will update our codebase so that every route that ends with new and edit will result in a modal popup like the one shown in this gif.

alt text

Update PathConfiguration

We created a path configuration file under assets/json in the previous tutorial. Let’s edit that and add a new rule.

{
  "patterns": [
    "/new$",
    "/edit$"
  ],
  "properties": {
    "context": "modal",
    "uri": "turbo://fragment/web/modal/sheet",
    "pull_to_refresh_enabled": false
  }
}

Enter fullscreen mode Exit fullscreen mode

This is telling our Turbo Android app to use the class that’s annotated with @TurboNavGraphDestination(uri = "turbo://fragment/web/modal/sheet") for any route that ends in new or edit.

Create the Fragment and add it

Now we need to create the fragment. Add a new Kotlin class and call it WebBottomSheetFragment and make sure to inherit from TurboWebBottomSheetDialogFragment()


import dev.hotwire.turbo.fragments.TurboWebBottomSheetDialogFragment
import dev.hotwire.turbo.nav.TurboNavGraphDestination

@TurboNavGraphDestination(uri = "turbo://fragment/web/modal/sheet")
class WebBottomSheetFragment : TurboWebBottomSheetDialogFragment() {}

Enter fullscreen mode Exit fullscreen mode

We’re not done yet. We’ve to add it to the list of registered fragments in our MainSessionNavHost

class MainSessionNavHost : TurboSessionNavHostFragment() {
  ...

    override val registeredFragments: List<KClass<out Fragment>>
    get() = listOf(
        WebFragment::class,
        WebBottomSheetFragment::class,
        )
    ...
}

Enter fullscreen mode Exit fullscreen mode

When we run the app and navigate to any route that ends in new or edit, we display a modal.

Rendering a Native Screen

The exact process that we used to add a modal we can also use it to navigate to a native screen. Let’s navigate to a simple Hello World screen written with Jetpack Compose. Jetpack Compose is Google’s modern UI tool and is similar to SwiftUI.

There is a little setup involved if we use the modern approach to building Android tools. So let’s dive in step by step.

Update build.gradle

We have to add the compose libraries to our app and ensure that it will compile Jetpack Compose.

android {
  ...
    buildFeatures {
      compose true
    }
  ...
}

dependencies {

  implementation 'androidx.compose.ui:ui:1.4.2'
    implementation 'androidx.compose.material:material:1.2.0'
    def composeBom = platform("androidx.compose:compose-bom:2023.03.00")
    implementation(composeBom)
    ....
}

Enter fullscreen mode Exit fullscreen mode

Make sure to sync your changes.

Next, we update our Path Configuration to render specific routes with a native screen.

{
  "patterns": [
    "/hello_world"
  ],
  "properties": {
    "context": "default",
    "uri": "turbo://fragment/hello_world"
  }
},

Enter fullscreen mode Exit fullscreen mode

Now we create the HelloWorldFragment, which inherits from TurboFragment

  @TurboNavGraphDestination(uri = "turbo://fragment/hello_world")
  class HelloWorldFragment : TurboFragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
      return ComposeView(requireContext()).apply {
        setContent {
          Hello()
        }
      }
    }

    @Composable
      fun Hello() {
        Column(
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
            ) {
          Text("Hello World")
        }
      }
  }

Enter fullscreen mode Exit fullscreen mode

Finally, we add this fragment to the list of registered fragments:

class MainSessionNavHost : TurboSessionNavHostFragment() {
  ...

    override val registeredFragments: List<KClass<out Fragment>>
    get() = listOf(
        WebFragment::class,
        WebBottomSheetFragment::class,
        HelloWorldFragment::class 
        )
    ...
}

Enter fullscreen mode Exit fullscreen mode

*NOTE: You may have to change your Kotlin version to 1.7.0 to compile. This can be changed in build.grade(project)

Once we’ve run the app, we should be able to navigate to the /hello\_world route and voila:

alt text

It’s pretty basic, but it’s enough to build on. In the next blog post, we will talk about the JavaScript bridge, and then we will talk about little improvements we can make to our Turbo app to make it even better.

💖 💪 🙅 🚩
williamkennedy
William Kennedy

Posted on May 23, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related