UI: Custom UI Components
Relevant source files
The following files were used as context for generating this wiki page:
- app/src/main/java/com/musagenius/ocrapp/presentation/ui/components/GridOverlay.kt
- app/src/main/java/com/musagenius/ocrapp/presentation/ui/ocr/OCRResultScreen.kt
- app/src/main/java/com/musagenius/ocrapp/presentation/ui/editor/ImageEditorScreen.kt
- app/src/main/java/com/musagenius/ocrapp/MainActivity.kt
- app/src/main/java/com/musagenius/ocrapp/presentation/ui/theme/Theme.kt
- app/src/main/java/com/musagenius/ocrapp/presentation/ui/theme/Color.kt
- app/src/main/java/com/musagenius/ocrapp/presentation/ui/theme/Type.kt
The OCR Android App leverages Jetpack Compose to create a modern, reactive, and visually appealing user interface following Material Design 3 principles. The UI is constructed from a combination of standard Material 3 components and several custom-built composables tailored for specific application features. These custom components encapsulate complex UI logic, enhance user experience, and provide visual aids for core functionalities like camera interaction, image editing, and results display.
The application's UI is designed to be state-driven, with composables reacting to state changes from ViewModels. This architecture promotes a clear separation of concerns and results in a maintainable and testable UI layer. Key custom components include camera overlays, state-specific views for OCR processing, and a dedicated image editor.
Theming and Styling
The application implements a flexible theming system that supports both light and dark modes, as well as dynamic coloring on Android 12+ devices. This is managed through a central OCRAppTheme composable.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/ui/theme/Theme.kt, app/src/main/java/com/musagenius/ocrapp/presentation/ui/theme/Color.kt, app/src/main/java/com/musagenius/ocrapp/presentation/ui/theme/Type.kt
OCRAppTheme
The OCRAppTheme composable wraps the entire application's UI content. It determines which color scheme to apply based on the system settings and Android version.
- Dynamic Color: On Android 12 (API 31) and higher, it uses
dynamicDarkColorSchemeordynamicLightColorSchemeto derive colors from the user's wallpaper, providing a personalized experience. - Static Themes: On older Android versions or when dynamic color is disabled, it falls back to predefined
LightColorSchemeandDarkColorScheme. - Typography: It applies a custom
Typographyscale defined inType.ktto ensure consistent text styling across the app.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/ui/theme/Theme.kt:59-73
@Composable
fun OCRAppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/ui/theme/Theme.kt:59-73
The diagram below shows how OCRAppTheme selects the appropriate color scheme.
Camera UI Components
To assist with image capture, the app provides overlay components that are rendered on top of the camera preview.
GridOverlay
The GridOverlay is a custom composable that draws a "rule of thirds" grid over the camera preview. This helps users compose better-quality photos of documents by aligning them with the grid lines. It is implemented using the Canvas composable.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/ui/components/GridOverlay.kt
Parameters
| Parameter | Type | Default Value | Description |
|---|---|---|---|
modifier | Modifier | Modifier | The modifier to be applied to the Canvas. |
color | Color | MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f) | The color of the grid lines. |
strokeWidth | Float | 1.dp | The thickness of the grid lines. |
Table Source: app/src/main/java/com/musagenius/ocrapp/presentation/ui/components/GridOverlay.kt:16-20
Implementation
The component calculates the positions for two vertical and two horizontal lines to divide the screen into nine equal parts.
@Composable
fun GridOverlay(
modifier: Modifier = Modifier,
color: Color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f),
strokeWidth: Float = with(LocalDensity.current) { 1.dp.toPx() }
) {
Canvas(modifier = modifier.fillMaxSize()) {
val width = size.width
val height = size.height
// Draw vertical lines (rule of thirds)
for (i in 1..2) {
val x = width * i / 3f
drawLine(...)
}
// Draw horizontal lines (rule of thirds)
for (i in 1..2) {
val y = height * i / 3f
drawLine(...)
}
}
}
Source: app/src/main/java/com/musagenius/ocrapp/presentation/ui/components/GridOverlay.kt:15-43
OCR Result Screen Components
The OCRResultScreen is composed of several smaller, state-specific custom components to display the outcome of the OCR process. It adapts its content based on whether the process is ongoing, has succeeded, or has failed.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/ui/ocr/OCRResultScreen.kt
The following diagram illustrates the component hierarchy within the OCRResultScreen.
Component Breakdown
| Component | Description |
|---|---|
OCRResultTopBar | A TopAppBar with a back navigation icon and a "Save" action button. The save icon changes to a checkmark and becomes disabled once the result is saved. |
OCRProcessingView | Displays a CircularProgressIndicator and informational text while OCR is in progress. |
OCRErrorView | Shows an error icon, a failure message, and a "Retry" button when the OCR process fails. |
OCRResultContent | The main success view. It contains the scanned image, a stats card (StatItem), action buttons (Copy, Share), and the extracted text within a SelectionContainer. |
StatItem | A small, reusable composable to display a key-value statistic, such as "Confidence" or "Processing Time". |
Table Source: app/src/main/java/com/musagenius/ocrapp/presentation/ui/ocr/OCRResultScreen.kt
Image Editor Screen
The ImageEditorScreen provides a simple but essential utility for pre-processing images selected from the gallery. Its primary function is to allow users to rotate an image in 90-degree increments before sending it to the OCR engine.
Sources: app/src/main/java/com/musagenius/ocrapp/presentation/ui/editor/ImageEditorScreen.kt
User Flow and Components
The screen is built around a central AsyncImage preview that is updated with a rotation transformation based on the uiState.
The user flow is as follows:
- The screen is initialized with an image URI.
- The user can tap "Rotate Left" or "Rotate Right" buttons.
- The
ImageEditorViewModelupdates therotationDegreesin theuiState. - The
AsyncImagerecomposes with the new rotation angle. - The user can reset the rotation or save the image.
- Saving the image applies the rotation, saves a new file, and navigates to the results screen with the new URI.
Key custom UI elements include:
- TopAppBar Actions: Contains "Close", "Reset Rotation", and "Save" buttons.
- Rotation Controls: A
Rowat the bottom of the screen withFilledIconButtons for rotating left/right and aSurfacein the middle displaying the current rotation angle. - Processing Overlay: A semi-transparent
Boxwith aCircularProgressIndicatorthat covers the UI while the image is being saved.
Source: app/src/main/java/com/musagenius/ocrapp/presentation/ui/editor/ImageEditorScreen.kt:60-170
Utility Components
PlaceholderScreen
For features planned but not yet implemented (e.g., History, Settings), a generic PlaceholderScreen composable is used. This component provides a consistent look for incomplete sections of the app, clearly communicating their status to developers and testers. It consists of a Scaffold with a TopAppBar and centered text displaying a title and subtitle.
@Composable
fun PlaceholderScreen(
title: String,
subtitle: String,
onNavigateBack: () -> Unit
) {
// ... Scaffold with TopAppBar and centered Text
}
Source: app/src/main/java/com/musagenius/ocrapp/MainActivity.kt:156-189