build method

  1. @override
Widget build(
  1. BuildContext context
)
override

Builds the main UI for the classification screen.

This method creates a responsive layout that adapts to different states:

  • Shows upload hints when no image is selected
  • Displays image preview during processing
  • Shows classification results with species information
  • Provides action buttons for camera, gallery, and reset

The layout uses a Scaffold with an AppBar and a scrollable body containing the main content area with image preview and action buttons.

context The build context for accessing theme and localization data. Returns a Widget representing the complete classification screen UI.

Implementation

@override
Widget build(BuildContext context) {
  final localizations = AppLocalizations.of(context)!;

  return ChangeNotifierProvider<ClassificationViewModel>.value(
    value: locator<ClassificationViewModel>(),
    child: Scaffold(
      appBar: AppBar(
        title: Text(localizations.classificationScreenTitle),
        centerTitle: true,
      ),
      body: Consumer<ClassificationViewModel>(
        builder: (context, viewModel, child) {
          return SingleChildScrollView(
            padding: const EdgeInsets.all(16.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                Visibility(
                  visible: !viewModel.hasImage,
                  maintainState: true,
                  child: Card(
                    elevation: 2,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(12),
                    ),
                    child: Padding(
                      padding: const EdgeInsets.all(16.0),
                      child: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          const Icon(
                            Icons.info_outline,
                            color: Colors.teal,
                            size: 32,
                          ),
                          const SizedBox(height: 8),
                          Text(
                            localizations.uploadImageHint,
                            textAlign: TextAlign.center,
                            style: const TextStyle(fontSize: 16),
                          ),
                          const SizedBox(height: 4),
                          Text(
                            localizations.uploadImageSubHint,
                            textAlign: TextAlign.center,
                            style: TextStyle(
                              fontSize: 14,
                              color: Colors.grey.shade600,
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
                if (!viewModel.hasImage) const SizedBox(height: 16),
                _buildImagePreview(context, viewModel, localizations),
                if (viewModel.errorMessage != null)
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Text(
                      viewModel.errorMessage!,
                      style: const TextStyle(color: Colors.red),
                      textAlign: TextAlign.center,
                    ),
                  ),
                if (viewModel.state == ClassificationState.success &&
                    viewModel.result != null)
                  _buildResultCard(context, viewModel, localizations)
                else if (viewModel.state == ClassificationState.submitted &&
                    viewModel.submissionResult != null)
                  _buildSubmissionResult(context, viewModel, localizations),
                Padding(
                  padding: const EdgeInsets.symmetric(vertical: 16.0),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: [

                      _buildActionButton(
                        icon: Icons.camera_alt,
                        label: localizations.cameraButtonLabel,
                        onPressed: () => _getImage(context, viewModel,
                            ImageSource.camera, localizations),
                      ),
                      _buildActionButton(
                        icon: Icons.photo_library,
                        label: localizations.galleryButtonLabel,
                        onPressed: () => _getImage(context, viewModel,
                            ImageSource.gallery, localizations),
                      ),

                      if (viewModel.hasImage)
                        _buildActionButton(
                          icon: Icons.refresh,
                          label: localizations.resetButtonLabel,
                          onPressed: () => viewModel.reset(),
                        ),
                    ],
                  ),
                ),
              ],
            ),
          );
        },
      ),
    ),
  );
}