Web Navigators¶
The Readium toolkit offers new navigators based on Jetpack Compose: ReflowableWebRendition and FixedWebRendition.
Unlike the legacy EpubNavigatorFragment, these new navigators are built as Composable functions and provide separate state and controller objects for better integration with modern Android apps.
| Composable | State | Supported publications |
|---|---|---|
ReflowableWebRendition |
ReflowableWebRenditionState |
Reflowable EPUB |
FixedWebRendition |
FixedWebRenditionState |
Fixed-layout EPUB |
[!WARNING] These new navigators are still experimental and have not been battle tested. You may face bugs that didn't exist in the legacy EPUB navigator and the APIs are subject to change.
Setup¶
To use the web navigators, add the following dependencies to your build.gradle.kts file:
dependencies {
implementation("org.readium.kotlin-toolkit:readium-navigator-web-reflowable:$readium_version")
implementation("org.readium.kotlin-toolkit:readium-navigator-web-fixedlayout:$readium_version")
}
Instantiating a Rendition¶
To use the new navigators, you first create a Factory for your publication type, then use it to create a RenditionState.
1. Create a Factory¶
The factory is responsible for creating the state.
val navigatorFactory = ReflowableWebRenditionFactory(
application = application,
publication = publication,
configuration = ReflowableWebConfiguration(...)
)
2. Create the Rendition State¶
The RenditionState holds the internal state of the navigator and is used by the Composable.
val renditionState = navigatorFactory.createRenditionState(
initialPreferences = initialPreferences,
initialLocation = initialLocation
).getOrElse {
// Handle error cases
}
3. Compose the Rendition¶
Finally, call the rendition Composable in your UI. The rendition will fill the maximum size provided by its parent.
ReflowableWebRendition(
state = renditionState
)
Input and Hyperlinks¶
You can react to user interactions by providing listeners to the rendition Composable.
val inputListener = object : InputListener {
override fun onTap(event: TapEvent, context: TapContext) {
// Handle tap
}
}
val hyperlinkListener = object : HyperlinkListener {
override fun onReadingOrderLinkActivated(url: Url, context: LinkContext?) {
// Handle internal navigation
}
override fun onExternalLinkActivated(url: AbsoluteUrl, context: LinkContext?) {
// Handle URL opening
}
}
Navigating the contents¶
The RenditionState provides a controller property that becomes available after the first composition. This controller implements NavigationController and other interfaces for interacting with the rendition.
val controller = renditionState.controller ?: return
// Navigate to a specific href
controller.goTo(url)
// Navigate forward or backward
controller.moveForward()
controller.moveBackward()
User preferences¶
You update the user preferences through the controller, which implements PreferencesController.
ReflowableWebPreferences and FixedWebPreferences¶
These classes hold the user-selected preferences (e.g., font size, theme). They are immutable data classes.
val preferences = ReflowableWebPreferences(
fontSize = 1.5,
scroll = true
)
Updating Preferences¶
To update the preferences, simply assign a new Preferences object to the controller.preferences property. The controller will automatically resolve the new settings and update the rendition.
val controller = renditionState.controller ?: return
controller.preferences = controller.preferences.copy(
fontSize = 2.0
)
Observing Settings¶
If you need to access the resolved settings (the values actually used by the rendition after merging preferences with defaults and publication metadata), you can use the controller.settings property.
val currentSettings = controller.settings
val actualFontSize = currentSettings.fontSize
Preference constraints¶
Depending on the publication, defaults and other preferences, some reflowable preferences might be ignored or have limited effect.
Scroll vs paginated¶
The columnCount preference is available only when in paginated mode (scroll = false).
Language specific preferences¶
Some preferences are not available for all languages and layout.
| Preference | LTR | RTL | CJK |
|---|---|---|---|
paragraphIndent |
:white_check_mark: | :white_check_mark: | |
textAlign |
:white_check_mark: | :white_check_mark: | |
ligatures |
:white_check_mark: | :white_check_mark: | |
letterSpacing |
:white_check_mark: | ||
wordSpacing |
:white_check_mark: | ||
hyphens |
:white_check_mark: |
Decorations¶
The new navigators support decorations, allowing you to render highlights or other annotations over the content.
val highlights = listOf(
Decoration(
id = Decoration.Id("highlight-1"),
location = location,
style = Decoration.Style.Highlight(tint = Color.Yellow)
)
)
controller.decorations.set("highlights", highlights)