kherel / animated_theme_switcher

Flutter animated theme switcher
https://pub.dev/packages/animated_theme_switcher
MIT License
278 stars 28 forks source link

Gives an exception | Multiple animations stopped working #48

Closed sxdpz23 closed 2 years ago

sxdpz23 commented 2 years ago

1. Giving an exception

I'm unsure why the exception was occurring; I believe it's a framework problem. Please guide me through the solution.

Exception -

The following LateError was thrown building ThemeSwitchingArea(dirty, dependencies: [ThemeModelInheritedNotifier]):
LateInitializationError: Field 'image' has not been initialized.

The relevant error-causing widget was
ThemeSwitchingArea -----                           lib\…\shared\appbar.dart:34
When the exception was thrown, this was the stack
#0      ThemeModel.image (package:animated_theme_switcher/src/theme_provider.dart) ----    package:animated_theme_switcher/src/theme_provider.dart:1
#1      ThemeSwitchingArea.build ----                        package:animated_theme_switcher/src/theme_switching_area.dart:28
#2      StatelessElement.build ----                      package:flutter/…/widgets/framework.dart:4662

Exception Occurred Exception

Below shown is my lib..\shared\appbar.dart file,

import 'package:animated_theme_switcher/animated_theme_switcher.dart';
import 'package:flutter/material.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart';

import '../shared/logo.dart';
import '../../essentials/constants.dart';

class CustomAppBar extends StatefulWidget {
  const CustomAppBar({Key? key, required this.child}) : super(key: key);

  final Widget child;

  @override
  _CustomAppBarState createState() => _CustomAppBarState();
}

final double _height = totsHeight - allPaddings.top - allPaddings.bottom;

class _CustomAppBarState extends State<CustomAppBar> {
  final Duration _duration = Duration(milliseconds: 800);
  bool menu = false;

  @override
  Widget build(BuildContext context) {
    return Container(
      height: totsHeight,
      width: totsWidth,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(30.0),
        color: ThemeModelInheritedNotifier.of(context)
            .theme
            .scaffoldBackgroundColor,
      ),
      child: ThemeSwitchingArea(                                                                         /// # Line <1>
        child: Stack(children: <Widget>[
          // View
          Positioned.fill(
            child: Container(
              height: totsHeight,
              width: totsWidth,
              color: ThemeModelInheritedNotifier.of(context)
                  .theme
                  .scaffoldBackgroundColor,
              child: SingleChildScrollView(
                child: widget.child,
              ),
            ),
          ),

          // Top expandable dialog box
          Positioned(
            top: allPaddings.top,
            left: 0.0,
            right: 0.0,
            child: LimitedBox(
              maxHeight: _height * 0.6,
              child: AnimatedContainer(                                                                 /// # Line <3>
                decoration: BoxDecoration(
                  color: ThemeModelInheritedNotifier.of(context)
                      .theme
                      .scaffoldBackgroundColor,
                  boxShadow: menu
                      ? [
                          BoxShadow(
                            blurRadius: totsHeight,
                            color: Colors.black26,
                            offset: Offset(0, totsHeight * 0.1),
                          ),
                        ]
                      : [],
                  borderRadius: BorderRadius.circular(20.0),
                ),
                duration: _duration,
                width: totsWidth,
                height: menu ? _height * 0.4 : _height * 0.1,
                child: Column(
                  children: <Widget>[
                    Padding(
                      padding: EdgeInsets.only(top: 10.0),
                      child: Row(
                        children: <Widget>[
                          Padding(
                            padding: EdgeInsets.only(left: 20.0),
                            child: AnimatedRotation(                                                /// # Line <4>
                              duration: _duration,
                              turns: !menu ? 0.0 : 0.5,
                              child: IconButton(
                                icon: Icon(Feather.grid),
                                color: ThemeModelInheritedNotifier.of(context)
                                    .theme
                                    .textTheme
                                    .bodyText1!
                                    .color,
                                onPressed: () => setState(() => menu = !menu),
                                tooltip: "Menu",
                              ),
                            ),
                          ),
                          Expanded(
                            child: AnimatedSwitcher(                                               /// # Line <5>
                              child: menu
                                  ? Opacity(
                                      opacity: 0.0,
                                      child: Padding(
                                        padding: EdgeInsets.only(
                                            top: 10.0, left: 10.0),
                                        child: Logo(),
                                      ),
                                    )
                                  : Padding(
                                      padding: EdgeInsets.only(
                                          top: 10.0, left: 10.0),
                                      child: Logo(),
                                    ),
                              duration: _duration,
                            ),
                          ),
                          ThemeSwitcher(                                                                 /// # Line <2>
                              clipper: const ThemeSwitcherCircleClipper(),
                              builder: (context) => GestureDetector(
                                    onTap: () => setState(() {
                                      ThemeSwitcher.of(context).changeTheme(
                                        theme: ThemeModelInheritedNotifier.of(
                                                        context)
                                                    .theme ==
                                                socialTheme
                                            ? professionalTheme
                                            : socialTheme,
                                      );
                                      provider.mode = !provider.mode;
                                    }),
                                    child: Tooltip(
                                      message: provider.mode
                                          ? "Social Switch"
                                          : "Professional Switch",
                                      child: Container(
                                        margin: EdgeInsets.only(
                                          right: 25.0,
                                        ),
                                        height: 50.0,
                                        width: 50.0,
                                        decoration: BoxDecoration(
                                          shape: BoxShape.circle,
                                          color: provider.mode
                                              ? socialTheme
                                                  .scaffoldBackgroundColor
                                              : professionalTheme
                                                  .scaffoldBackgroundColor,
                                        ),
                                        child: Icon(
                                          provider.mode
                                              ? Feather.users
                                              : Feather.briefcase,
                                          color: provider.mode
                                              ? socialTheme
                                                  .textTheme.bodyText1!.color
                                              : professionalTheme
                                                  .textTheme.bodyText1!.color,
                                          size: 25.0,
                                        ),
                                      ),
                                    ),
                                  )),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
          // Bottom Dock Floating Action Buttons
          Positioned(
            bottom: allPaddings.bottom + 30.0,
            right: 25.0,
            child: Container(
              height: 80.0,
              width: 130.0,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: <Widget>[
                  _fab(icon: Feather.plus, label: "Add Post"),
                  SizedBox(width: 15.0),
                  _fab(icon: Feather.menu, label: "Feeds Categories"),
                ],
              ),
            ),
          ),
        ]),
      ),
    );
  }

  Widget _fab({required IconData icon, required String label}) =>
      GestureDetector(
        onTap: () {},
        child: Tooltip(
          message: label,
          child: AnimatedContainer(
            duration: _duration,
            height: 50.0,
            width: 50.0,
            decoration: BoxDecoration(
              shape: BoxShape.circle,
              color: ThemeModelInheritedNotifier.of(context)
                  .theme
                  .floatingActionButtonTheme
                  .backgroundColor,
            ),
            child: Icon(
              icon,
              color: ThemeModelInheritedNotifier.of(context)
                  .theme
                  .floatingActionButtonTheme
                  .foregroundColor,
              size: 20.0,
            ),
          ),
        ),
      );
}

I've implemented ThemeSwitchingArea() in Line <1> and ThemeSwitcher() in Line <2> .

2. Multiple Animations stopped working

In the above "appbar.dart", I've referenced the lines for Other Animations I embedded to the screen which stopped working after implementation of the animated_theme_switcher button. I'm unsure whether the animations stopped working due to the exception occurring on the runtime or just incompatible with the package when used. The lines referenced and their actions - Line <3> - The dialog box should expand in that duration Line <4> - The icon button should rotate on press when the dialog box is expanding and closing Line <5> - The logo should fade slowly in the background when the dialog box is expanding and closing

https://user-images.githubusercontent.com/47190721/147377852-85f7c441-2624-46b5-865e-83d299e5ffef.mp4

sxdpz23 commented 2 years ago

@kherel , I solved both the issues. The animations were stopped due to the exception.

I solved the exception via changing the late initialization to Nullable ui.Image? image. We can also give a default value to the image variable when initialized with late, as an alternative, in the theme_provider.dart file of the package.

Closing the issue. Thanks anyways.