简体   繁体   中英

Flutter how to change state of stateless widget

I am creating a web panel in flutter and I have a stateless widget. I need to change just an int which is on another file on this behalf my color of fonts is changing.

main.dart

void main() {
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primaryColor: Color(0xfff00B074),
        textTheme: const TextTheme(
          bodyText1: TextStyle(
              fontSize: 18.0,
              fontFamily: 'Barlow-Medium',
              color: Color(0xff464255)),
        ),
      ),
      home: MainScreen(),
    );
  }
}

main_screen.dart

class MainScreen extends StatelessWidget {
  const MainScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Row(
          children: [
            if (Responsive.isDesktop(context))
              Expanded(
                // default flex = 1
                child: SideMenu(),
              ),
            Expanded(
              flex: 5,
              child: Container(),
            ),
          ],
        ),
      ),
    );
  }
}

And my side menu

class SideMenu extends StatelessWidget {
  const SideMenu({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: ListView(
        children: [
          Padding(
            padding: const EdgeInsets.only(top: 30, bottom: 15),
            child: SvgPicture.asset(
              "assets/icon/logo.svg",
            ),
          ),
          DrawerListTile(
            intKey: 1,
            title: "Dashboard",
            svgSrc: "assets/icon/home_deactive.svg",
            press: () {
              sideMenuValue = 1;
              print('asd');
            },
          ),
          DrawerListTile(
            intKey: 2,
            title: "Transaction",
            svgSrc: "assets/icon/home_deactive.svg",
            press: () {
              sideMenuValue = 2;
            },
          ),
          DrawerListTile(
            intKey: 3,
            title: "Task",
            svgSrc: "assets/icon/home_deactive.svg",
            press: () {
              sideMenuValue = 3;
            },
          ),
          DrawerListTile(
            intKey: 4,
            title: "Documents",
            svgSrc: "assets/icon/home_deactive.svg",
            press: () {
              sideMenuValue = 4;
            },
          ),
          DrawerListTile(
            intKey: 5,
            title: "Store",
            svgSrc: "assets/icon/home_deactive.svg",
            press: () {
              sideMenuValue = 5;
            },
          ),
          DrawerListTile(
            intKey: 6,
            title: "Notification",
            svgSrc: "assets/icon/home_deactive.svg",
            press: () {
              sideMenuValue = 6;
            },
          ),
          DrawerListTile(
            intKey: 7,
            title: "Profile",
            svgSrc: "assets/icon/home_deactive.svg",
            press: () {},
          ),
          DrawerListTile(
            intKey: 8,
            title: "Settings",
            svgSrc: "assets/icon/home_deactive.svg",
            press: () {},
          ),
        ],
      ),
    );
  }
}

class DrawerListTile extends StatelessWidget {
  const DrawerListTile({
    Key? key,
    // For selecting those three line once press "Command+D"
    required this.intKey,
    required this.title,
    required this.svgSrc,
    required this.press,
  }) : super(key: key);

  final String title, svgSrc;
  final VoidCallback press;
  final int intKey;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: press,
      child: Padding(
        padding: const EdgeInsets.only(left: 30, bottom: 30),
        child: Container(
            child: Row(
          children: [
            SvgPicture.asset(
              svgSrc,
              height: 18,
            ),
            SizedBox(
              width: 13,
            ),
            Text(
              title,
              style: sideMenuValue == intKey
                  ? TextStyle(
                      fontSize: 18.0,
                      fontFamily: 'Barlow-Medium',
                      color: Color(0xfff00B074))
                  : Theme.of(context).textTheme.bodyText1,
            ),
          ],
        )),
      ),
    );
  }
}

You can see on press I am changing the value of sideMenuValue which is not changing because I am using the stateless widget and not want to use the stateful widget.

Change the class that needs to change mode as follows

class HomePage extends StatefullWidget {
  const HomePage({
    Key? key,
  }) : super(key: key);

 @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<_HomePage> {
 @override
  Widget build(BuildContext context) {
    return Scaffold(
      ..........
    );
}

Please refer below code

ValueNotifer & ValueListenableBuilder can be used to hold value and update widget by notifying its listeners and reducing number of times widget tree getting rebuilt.

main.dart file


import 'package:elastic_search/SideMenu.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());


/* 
Since sideMenuValue is declared in main.dart file its available globally everywhere in the app
In order to update any value from other files we can make use of ValueNotifer 
and to update widget we can use ValueListenableBuilder which updates the particular widget when the value changes (ValueNotifier value)
*/
final ValueNotifier sideMenuValue = ValueNotifier(0);


class MyApp extends StatelessWidget {
  MyApp({Key key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primaryColor: Color(0xfff00B074),
        textTheme: const TextTheme(
          bodyText1: TextStyle(
              fontSize: 18.0,
              fontFamily: 'Barlow-Medium',
              color: Color(0xff464255)),
        ),
      ),
      home: MainScreen(),
    );
  }
}

class MainScreen extends StatelessWidget {
  const MainScreen({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Row(
          children: [
            Expanded(
              child: SideMenu(),
            ),
            // Expanded(
            //   flex: 5,
            //   child: Container(),
            // ),
          ],
        ),
      ),
    );
  }
}

SideMenu.dart file

import 'package:flutter/material.dart';
import 'package:elastic_search/main.dart';

class SideMenu extends StatelessWidget {
  const SideMenu({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: ListView(
        children: [
          // Padding(
          //   padding: const EdgeInsets.only(top: 30, bottom: 15),
          //   child: SvgPicture.asset(
          //     "assets/icon/logo.svg",
          //   ),
          // ),
          DrawerListTile(
            intKey: 1,
            title: "Dashboard",
            svgSrc: "assets/icon/home_deactive.svg",
            press: () {
              sideMenuValue.value = 1;
              print('asd');
            },
          ),
          DrawerListTile(
            intKey: 2,
            title: "Transaction",
            svgSrc: "assets/icon/home_deactive.svg",
            press: () {
              sideMenuValue.value = 2;
            },
          ),
          DrawerListTile(
            intKey: 3,
            title: "Task",
            svgSrc: "assets/icon/home_deactive.svg",
            press: () {
              sideMenuValue.value = 3;
            },
          ),
          DrawerListTile(
            intKey: 4,
            title: "Documents",
            svgSrc: "assets/icon/home_deactive.svg",
            press: () {
              sideMenuValue.value = 4;
            },
          ),
          DrawerListTile(
            intKey: 5,
            title: "Store",
            svgSrc: "assets/icon/home_deactive.svg",
            press: () {
              sideMenuValue.value = 5;
            },
          ),
          DrawerListTile(
            intKey: 6,
            title: "Notification",
            svgSrc: "assets/icon/home_deactive.svg",
            press: () {
              sideMenuValue.value = 6;
            },
          ),
          DrawerListTile(
            intKey: 7,
            title: "Profile",
            svgSrc: "assets/icon/home_deactive.svg",
            press: () {
              sideMenuValue.value = 7;
            },
          ),
          DrawerListTile(
            intKey: 8,
            title: "Settings",
            svgSrc: "assets/icon/home_deactive.svg",
            press: () {
              sideMenuValue.value = 8;
            },
          ),
        ],
      ),
    );
  }
}

class DrawerListTile extends StatelessWidget {
  const DrawerListTile({
    Key key,
    // For selecting those three line once press "Command+D"
    @required this.intKey,
    @required this.title,
    @required this.svgSrc,
    @required this.press,
  }) : super(key: key);

  final String title, svgSrc;
  final VoidCallback press;
  final int intKey;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: press,
      child: Padding(
        padding: const EdgeInsets.only(left: 30, bottom: 30),
        child: Container(
            child: Row(
          children: [
            // SvgPicture.asset(
            //   svgSrc,
            //   height: 18,
            // ),
            SizedBox(
              width: 13,
            ),
            /* 
              In order update widget we can use ValueListenableBuilder which updates the particular widget when the value changes (ValueNotifier value)
            */
            ValueListenableBuilder(
                valueListenable: sideMenuValue,
                builder: (context, snapshot, child) {
                  return Text(
                    title,
                    style: sideMenuValue.value == intKey
                        ? TextStyle(
                            fontSize: 18.0,
                            fontFamily: 'Barlow-Medium',
                            color: Color(0xfff00B074))
                        : Theme.of(context).textTheme.bodyText1,
                  );
                }),
          ],
        )),
      ),
    );
  }
}


The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM