# Welcome you are visitor number 12345

DevFeed: [Welcome you are visitor number 12345](<https://devfeed.tech/articles/welcome-you-are-visitor-number-12345-32085.md>)

Original publisher: [Read original article](<https://www.maiatoday.net/p/welcome-you-are-visitor-number-12345/>)

Published: 2021-07-12T19:44:03Z

Content type: tutorial

Language: en

Sources: [maiatoday](<https://devfeed.tech/sources/maiatoday.md>)

Topics: [ui](<https://devfeed.tech/topics/ui.md>), [Code](<https://devfeed.tech/topics/code.md>), [navigation](<https://devfeed.tech/topics/navigation.md>)

Tags: [90s-website](<https://devfeed.tech/tags/90s-website.md>), [animate](<https://devfeed.tech/tags/animate.md>), [code](<https://devfeed.tech/tags/code.md>), [components](<https://devfeed.tech/tags/components.md>), [compose](<https://devfeed.tech/tags/compose.md>), [coroutine](<https://devfeed.tech/tags/coroutine.md>), [snippet](<https://devfeed.tech/tags/snippet.md>), [state](<https://devfeed.tech/tags/state.md>), [stateflow](<https://devfeed.tech/tags/stateflow.md>), [stateless](<https://devfeed.tech/tags/stateless.md>), [ui](<https://devfeed.tech/tags/ui.md>), [viewmodel](<https://devfeed.tech/tags/viewmodel.md>), [visitor-counter](<https://devfeed.tech/tags/visitor-counter.md>)

## AI overview

A tutorial on building an animated visitor counter in a classic 1990s website style. It explains how to animate each digit independently, manage the counter and counting direction in a view model, keep composable UI components stateless and reusable, and connect the screen through navigation and Hilt.

## Source excerpt

Another step forward in recreating the icon 90s website look is the hit counter, visitor counter or web counter in classic squemorphic odometer style. I was inspired by a recent episode of Code with Italians where they animated a time field. I wanted to change the counter component to animate each number individually to get that odometer look. Before doing this though there was a question of state. I wanted to make a counter that would auto increment in a coroutine. It had to change direction up or down if you tapped it. To do this I decided to store the state and the counting direction in a view model. This allowed me to keep the components as stateless as possible. The components are re-usable because the logic that makes the numbers go up or down is held outside of the composable functions. The recommendation from Google is when you use a view model to hold state, keep it close to the root screen. I made a screen for my visitor counter and added it to my navigation code. Since I already had Hilt enabled in the project it was pretty easy to get hold of the viewmodel. The code snippet in the Navigation looks like this: NavHost(navController, startDestination = "overview") { //... other routes go here composable(route = "counter") { val viewModel: CounterViewModel = hiltViewModel() //<--- get the viewmodel from Hilt val count by viewModel.counter.collectAsState() //<--- the viewmodel exposes the counter as a StateFlow CounterScreen( count = count, onClick = { viewModel.onClick() } // <--- the viewmodel provides a method for when the element is clicked ) } } The CounterScreen is stateless and gets the value of the counter and the event handler as parameters. The CounterScreen has a Counter composable. The role of the Counter composable is to create a row of individual odometer numbers from the passed values. Also it should intercept a click and call the click handler. @Composable fun Counter( onClick: () -> Unit, count: Int, width: Int ) { val displayWidth = maxOf(3,