LazyTimetable

July 11, 2025 ยท View on GitHub

Ask DeepWiki JitPack Lint Vital Check

A high-performance, lazy-loading timetable composable for Android Jetpack Compose.
Perfect for creating festival schedules, conference schedules, and any time-based multi-column layouts.

โœจ Features

  • ๐Ÿš€ High Performance: Lazy loading with viewport culling for smooth scrolling even with large datasets
  • โฐ Time-based Positioning: Items are positioned based on duration in seconds with automatic layout calculation
  • ๐Ÿ“ฑ Bi-directional Scrolling: Smooth horizontal and vertical scrolling
  • ๐ŸŽจ Highly Customizable: Configure colors, spacing, and content appearance
  • ๐Ÿ”ง Type-safe DSL: Clean, declarative API for defining timetable structure

๐Ÿ› ๏ธ Installation

Add it in your settings.gradle.kts at the end of repositories if you haven't added JitPack Repo yet.

dependencyResolutionManagement {
  repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
  repositories {
    mavenCentral()
    maven { url = uri("https://jitpack.io") }
  }
}

Add the dependency in your app/build.gradle.kt

dependencies {
  implementation("com.github.MoyuruAizawa:LazyTimetable:${version}")
}

๐Ÿš€ Quick Start

Here's a simple example of creating a timetable:

LazyTimetable(
  contentPadding = contentPaddings,
  horizontalSpacing = 4.dp,
  columnWidth = 120.dp,
  // This value is used to determine how much height to allocate for the period on the Timetable.
  heightPerMinute = 1.5.dp,
  columnHeaderHeight = 80.dp,
  columnHeaderColor = Color.White,
  timeColumnWidth = 100.dp,
  timeColumnColor = Color.White,
  // the start time of the initial period in Epoch Seconds.
  baseEpochSec = tomorrowland.startAt,
  // A Composable function that generates labels placed in the TimeColumn displayed on the left side of the timetable.
  timeLabel = { TimeLabel(it) },
  modifier = Modifier.fillMaxSize(),
) {
  festival.stages.forEach { stage ->
    // A DSL for generating Columns with Headers
    column(header = { Header(stage) }) {
      stage.periods.forEach { period ->
        // A DSL for generating periods within a column.
        item(period.durationSec) {
          when (period) {
            is Period.Empty -> Spacer(Modifier)
            is Period.Show -> Show(period.title)
          }
        }
      }
    }
  }
}

๐Ÿ“š API Reference

LazyTimetable

The main composable function for creating a timetable.

@Composable
fun LazyTimetable(
    modifier: Modifier = Modifier,
    listState: LazyTimetableState = rememberLazyTimetableState(),
    horizontalSpacing: Dp = 0.dp,
    contentPadding: PaddingValues = PaddingValues(),
    columnWidth: Dp,
    heightPerMinute: Dp,
    columnHeaderHeight: Dp,
    columnHeaderColor: Color,
    timeColumnWidth: Dp,
    timeColumnColor: Color,
    baseEpochSec: Long,
    timeLabel: @Composable (Long) -> Unit,
    content: LazyTimetableScope.() -> Unit
)

Parameters

ParameterTypeDescription
listStateLazyTimetableStateState object that provides scroll state information
horizontalSpacingDpHorizontal spacing between columns
contentPaddingPaddingValuesPadding around the entire timetable
columnWidthDpWidth of each column in the timetable
heightPerMinuteDpHeight allocated per minute
columnHeaderHeightDpHeight of the column headers
columnHeaderColorColorBackground color of the column headers
timeColumnWidthDpWidth of the time column (left side time labels)
timeColumnColorColorBackground color of the time column (left side time labels)
baseEpochSecLongBase timestamp in epoch seconds used as the reference point for time calculations
timeLabel@Composable (Long) -> UnitComposable function for rendering time labels, receives epoch seconds as parameter
contentLazyTimetableScope.() -> UnitDSL block for defining the timetable structure using LazyTimetableScope

LazyTimetableScope

The receiver scope for defining timetable content.

interface LazyTimetableScope {
    fun column(
        header: @Composable () -> Unit,
        columnContent: LazyTimetableColumnScope.() -> Unit
    )
}

Functions

  • column: Adds a column to the timetable with a header and column content

LazyTimetableColumnScope

The receiver scope for defining column content.

interface LazyTimetableColumnScope {
    fun item(
        durationSec: Int,
        content: @Composable () -> Unit
    )
}

Functions

  • item: Adds an item to the column with specified duration in seconds