0

In Flutter, is there a simple way to create a Widget's subclass, which modifies its default parameters?

Let's say I want to create a ShadedContainer, which always has the same shadow decoration, but besides that, replicates all of Container's behaviour.

The following simplified code works:

import 'package:flutter/material.dart';

class ShadedContainer extends StatelessWidget {
  final Widget? child;
  final double? width;
  final double? height;

  // private
  final Decoration _decoration;
  static const _boxShadow = [
    BoxShadow(
      color: Color(0x60000000),
      offset: Offset(5, 5),
      blurRadius: 7,
      spreadRadius: 1,
    ),
  ];

  // constructor
  ShadedContainer({
    Key? key,
    this.width,
    this.height,
    this.child,
    BoxDecoration? decoration,
  })  : _decoration = (decoration == null)
            ? const BoxDecoration(
                boxShadow: _boxShadow,
              )
            : BoxDecoration(
                boxShadow: _boxShadow,
                color: decoration.color,
                border: decoration.border,
                borderRadius: decoration.borderRadius,
              ),
        super(key: key);

  // builder
  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: _decoration,
      width: width,
      height: height,
      child: child,
    );
  }
}

This really doesn't seem optimal. I have not replicated all of the Container's parameters, and it is quite verbose already.

Is there a way to extend Container directly, instead of creating a new Widget from scratch (and without copying most of Container's source code... hence opening the door to future updates/fixes issues on that Widget)?

Thanks!

1 Answer 1

1

There absolutely is a way to do this. In fact the first time I came across this idea of extending a class was on bloclibrary.dev/

enter image description here

This is from the default Counter app built using the bloc library

import 'package:flutter/material.dart';
import 'counter/counter.dart';
/// {@template counter_app}
/// A [MaterialApp] which sets the `home` to [CounterPage].
/// {@endtemplate}
class CounterApp extends MaterialApp {
  /// {@macro counter_app}
  const CounterApp({Key? key}) : super(key: key, home: const CounterPage());
}

I could extend the same logic to ShadedContainer. Based on your question a shaded container extends a container

class ShadedContainer extends Container {
  ShadedContainer(
      {Decoration? decoration, double? width, double? height, Widget? child})
      : super(
            width: width,
            height: height,
            child: child,
            decoration: decoration ??
                BoxDecoration(boxShadow: [
                  BoxShadow(
                    color: Color(0x60000000),
                    offset: Offset(5, 5),
                    blurRadius: 7,
                    spreadRadius: 1,
                  ),
                ]));
}

It can then be used this way

class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          darkTheme: ThemeData.dark(),
          theme: ThemeData.light(),
          home: Scaffold(
            appBar: AppBar(title: Text('Shaded Container')),
            body: Center(
                child: ShadedContainer(
              width: 100,
              height: 100,
              child: Center(child: Text('Extending')),
            )),
          ),
          debugShowCheckedModeBanner: false,
        );
      }
    }
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot for taking the time to answer. With this approach, I still need to list in the constructor every single Container parameter I want to make accessible when building it, right (like width and height here) ?
OK, that's what it is. Thanks for your suggestion!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.