view_state_widget 1.0.0+2 copy "view_state_widget: ^1.0.0+2" to clipboard
view_state_widget: ^1.0.0+2 copied to clipboard

A lightweight Flutter widget to manage loading, content, and error states in UI.

example/lib/main.dart

import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:view_state_widget/view_state_widget.dart';
import 'dart:math';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  ViewState _currentState = ViewState.loading;

  late final Connectivity _connectivity;
  late final StreamSubscription<List<ConnectivityResult>> _subscription;

  Future<bool> _isConnected() async {
    final connectivityResults = await Connectivity().checkConnectivity();
    return connectivityResults.any(
      (result) => result != ConnectivityResult.none,
    );
  }

  Future<void> _loadData() async {
    setState(() {
      _currentState = ViewState.loading;
    });

    if (!await _isConnected()) {
      setState(() {
        _currentState = ViewState.networkError;
      });
      return;
    }

    await Future.delayed(const Duration(seconds: 2));

    final options = [
      ViewState.content,
      ViewState.error,
      ViewState.networkError,
    ];
    final randomIndex = Random().nextInt(options.length);

    setState(() {
      _currentState = options[randomIndex];
    });
  }

  @override
  void initState() {
    super.initState();
    _connectivity = Connectivity();
    _subscription = _connectivity.onConnectivityChanged.listen((results) {
      final hasConnection = results.any((r) => r != ConnectivityResult.none);
      if (_currentState == ViewState.networkError && hasConnection) {
        _loadData();
      }
    });

    _loadData();
  }

  @override
  void dispose() {
    _subscription.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrangeAccent),
        useMaterial3: true,
        textTheme: const TextTheme(
          bodyMedium: TextStyle(fontSize: 18, color: Colors.deepOrangeAccent),
        ),
        elevatedButtonTheme: ElevatedButtonThemeData(
          style: ElevatedButton.styleFrom(
            backgroundColor: Colors.deepOrangeAccent,
            foregroundColor: Colors.white,
            padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
            textStyle: const TextStyle(fontSize: 16),
          ),
        ),
      ),
      darkTheme: ThemeData.dark().copyWith(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.lightBlue,
          brightness: Brightness.dark,
        ),
      ),
      themeMode: ThemeMode.system,

      home: Scaffold(
        appBar: AppBar(title: const Text("State View Example")),
        body: ViewStateWidget(
          state: _currentState,
          content: const _SuccessContent(),
          loadingWidget: _LoadingContent(),
          errorWidget: ErrorStateWidget(
            icon: Icons.error_outline,
            message: "Uh-oh! Something didn’t work as expected.",
            onRetry: _loadData,
          ),
          networkErrorWidget: ErrorStateWidget(
            icon: Icons.wifi_off_outlined,
            message: "Internet connection lost. Waiting to reconnect...",
            onRetry: _loadData,
          ),
          onRetry: _loadData,
        ),
      ),
    );
  }
}

class _LoadingContent extends StatelessWidget {
  const _LoadingContent();

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          CircularProgressIndicator(),
          SizedBox(height: 10),
          Text("Loading... Please wait."),
        ],
      ),
    );
  }
}

class _SuccessContent extends StatelessWidget {
  const _SuccessContent();

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text(
            "✨ Yay! Everything's working smoothly!",
            textAlign: TextAlign.center,
            style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600),
          ),
          SizedBox(height: 8),
          Text(
            "You’re all set 🎉",
            style: TextStyle(fontSize: 16, color: Colors.grey),
          ),
        ],
      ),
    );
  }
}

class ErrorStateWidget extends StatelessWidget {
  final IconData icon;
  final String message;
  final VoidCallback onRetry;

  const ErrorStateWidget({
    super.key,
    required this.icon,
    required this.message,
    required this.onRetry,
  });

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(icon, size: 50),
          const SizedBox(height: 10),
          Text(
            message,
            textAlign: TextAlign.center,
            style: Theme.of(context).textTheme.titleMedium,
          ),
          const SizedBox(height: 10),
          ElevatedButton(onPressed: onRetry, child: const Text("Retry")),
        ],
      ),
    );
  }
}
5
likes
160
points
3
downloads

Publisher

unverified uploader

Weekly Downloads

A lightweight Flutter widget to manage loading, content, and error states in UI.

Repository (GitHub)
View/report issues

Topics

#state #ui #error-handling #loading #flutter-widget

Documentation

API reference

License

MIT (license)

Dependencies

cupertino_icons, flutter

More

Packages that depend on view_state_widget