Mark
Mark

Reputation: 3849

How can I pass color and theme information between widgets?

I'm attempting to pass color/theme information different widgets. My app consists of a news page which then opens up individual articles. These articles should have different colors depending on which of several news pages opens them, so I want to direct the theme/color information from outside my article widget.

I made a class to hold some color/theme information as follows:

class NewsTheme0 {

  static Color headerColor = Color.fromRGBO(30, 60, 90, 1);

  static TextStyle headerFontStyle() {
    return TextStyle(
        color:Color.fromRGBO(200,100,0,1),
        fontSize:28.5,
        letterSpacing: -1.4,
        fontWeight: FontWeight.w700
    );
  }

}

class NewsTheme1 {

  static Color headerColor = Color.fromRGBO(0, 0, 0, 1);

  static TextStyle headerFontStyle() {
    return TextStyle(
        color:Color.fromRGBO(255, 255, 255, 1),
        fontSize:15,
        fontWeight: FontWeight.w700
    );
  }

}

And then inside my News page in my appBar I'm successfully retrieving this color information:

Scaffold(
            appBar: AppBar(
                centerTitle: false,
                backgroundColor: NewsTheme0.headerColor,
                title: Text('News',
                    style: NewsTheme0.headerFontStyle()),
                elevation: 0,
            ) ...

From my main News page I open an Article page and when I open the article widget, I pass the color information

         Navigator.push(
           context,
          MaterialPageRoute(builder: (context) => OpenAnArticle(articleid: 231, theme: NewsTheme0)));

And inside my article looks like this:

class OpenAnArticle extends StatefulWidget {
  OpenAnArticle({ Key? key, required this.articleid, required this.theme}) : super(key: key);
  final int articleid;
  final theme;

  @override
  _OpenAnArticle createState() => _OpenAnArticle();

}

BUT when I try to use this theme information in my article, it fails miserably. I need to pass the theme information because I will not know ahead of time from which of my various color theme pages they will be arriving from.

Scaffold(
            appBar: AppBar(
                centerTitle: false,
                backgroundColor: widget.theme.headerColor,
                title: Text('Article',
                    style: widget.theme.headerFontStyle()),
                elevation: 0,
            ) ...

Upvotes: 1

Views: 585

Answers (1)

enzo
enzo

Reputation: 11486

That's because when you do NewsTheme0, you're accessing an object of type Type and you can't access the (static) methods of a class using only its type. You can use a "enum" as seen here:

// Declaring the abstract class which each theme will inherit from
abstract class NewsTheme {
  static const NewsTheme theme0 = _NewsTheme0();
  static const NewsTheme theme1 = _NewsTheme1();

  const NewsTheme();

  Color get headerColor;

  TextStyle headerFontStyle();
}

class _NewsTheme0 extends NewsTheme {
  const _NewsTheme0() : super();

  @override
  Color get headerColor => Color.fromRGBO(30, 60, 90, 1);

  @override
  TextStyle headerFontStyle() {
    return TextStyle(
        color:Color.fromRGBO(200,100,0,1),
        fontSize:28.5,
        letterSpacing: -1.4,
        fontWeight: FontWeight.w700
    );
  }
}

class _NewsTheme1 extends NewsTheme {
  const _NewsTheme1() : super();

  @override
  Color get headerColor => Color.fromRGBO(0, 0, 0, 1);

  @override
  TextStyle headerFontStyle() {
    return TextStyle(
        color:Color.fromRGBO(255, 255, 255, 1),
        fontSize:15,
        fontWeight: FontWeight.w700
    );
  }
}

In your widget's code:

class OpenAnArticle extends StatefulWidget {
  final int articleid;
  // Expect a NewsTheme object
  final NewsTheme theme;

  const OpenAnArticle({ Key? key, required this.articleid, required this.theme}) : super(key: key);
 
  @override
  _OpenAnArticle createState() => _OpenAnArticle();
}

Then, if you want to pass a theme to its constructor, you can just access the static fields of NewsTheme:

Navigator.push(
  context,
  MaterialPageRoute(builder: (_) => OpenAnArticle(articleid: 231, theme: NewsTheme.theme0)),
);

Upvotes: 3

Related Questions