Fathi Draws
Fathi Draws

Reputation: 65

How to change the color of a Widget based on a different Widget?

I'm trying to make simple app which displays SvgPicture.assets() and user can change the color of the SvgPicture() using color picker.

I have 2 widgets:

  1. for displaying SvgPicture() called it Svg.dart
  2. main.dart contains BottomNavigationView, and one of the tabs opens color picker, and the Svg.dart

I encountered some errors with setState(() {}) but I managed to fix the error somehow but it does not change the color, when I tried changing the background color of main.dart it worked perfectly.

here is my code:

I tried looking for flutter documentations but I don't really know how/where the issue is, and did not find tutorials, Please help

EDIT

this is the main.dart

    class Main extends StatefulWidget{
      @override
      _MainState createState() => _MainState();
    }
    
    class _Main extends State<Main> {
      int _slectedIndex = 0;
      Color color = MyConstants.darkWhite;
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.black,
          body: Center(
            child: Svg(),
          ),
          bottomNavigationBar: BottomNavigationBar(
            items: const<BottomNavigationBarItem>[
              BottomNavigationBarItem(
                label: "",
                icon: Icon(Icons.home),
              ),
              BottomNavigationBarItem(
                label: "",
                icon: Icon(Icons.home),
              ),
              BottomNavigationBarItem(
                label: "",
                icon: Icon(Icons.home),
              ),
              BottomNavigationBarItem(
                label: "",
                icon: Icon(Icons.home),
              ),
            ],
            onTap: _onItemTap,
          ),
        );
      }
    
      void _onItemTap(int index) {
        setState(() {
          if (index == 0) {
    // do something
          }
          if (index == 1) {
    // do something
          }
    
          if (index == 2) {
    // do something
          }
    
          if (index == 3) {
            showDialog(
              context: context,
              builder: (BuildContext context){
                return AlertDialog(
                  content:
                  SingleChildScrollView(
                    child: new ColorPicker(
                      pickerColor: Colors.red,
                      onColorChanged: (Color colorChanged) {
                        setState(() {
                          color = colorChanged;
                        });
                      },
                    ),
                  ),
                );
              });
          }
        });
      }
    }

and Svg.dart

class Svg extends StatefulWidget{
  //Color picked;
  @override
  SvgState createState() => Svg();
}

class SvgState extends State<Svg> {
  @override
  Widget build(BuildContext context) {
    return CustomMultiChildLayout(
      delegate: SvgDelegate(
          position: Offset.zero
      ),
      children: [
        buildLayoutId(ids.shirtId, MyConstants.shirt, CreateKit().createState().color)
      ],
    );
  }
  LayoutId buildLayoutId(Object id, String item, Color color) {
    return LayoutId(
        id: id,
        child: SvgPicture.asset(
          item,
          color: color,
        ),
      );
  }
}

the class that extends MultiChildLyoutDelegate for CustomMultichildLayout in Svg.dart

class SvgDelegate extends MultiChildLayoutDelegate{
  final Offset position;
  SvgDelegate({
    this.position
});
  @override
  void performLayout(Size size) {

    Size leadSize = Size.zero;
    itemLayout(leadSize, size, ids.shirtId);
  }    
  void itemLayout(Size leadSize, Size size, Object id) {
    if(hasChild(id)){
      leadSize = layoutChild(
        id,
        BoxConstraints.loose(size),
      );
    }
  }    
  @override
  bool shouldRelayout(TempDelegate oldDelegate) {
    return oldDelegate.position != position;
  }   
}

Upvotes: 2

Views: 9917

Answers (2)

EdwardLi
EdwardLi

Reputation: 184

In Flutter everything is a widget and you can create your own custom widgets. Likewise, there are concepts such as hierarchy and state.

A stateless widget is a StatelessWidget such as a label, a background, a title or whatever.

A stateful widget is a StatefulWidget is something that changes such as a switch, an animated background, a page, etc. There is also an InheritedWidget but that is another topic.

setState is used in the StatefulWidget to update the state of that widget, to update a child from the parent, you can use the properties of the child. When setState is called, it rebuilds the widget and its children if necessary.

The Container widget has a color property.

Container(
  color: colorParent,
)

Your custom widget can also have any property such as color or size or colorChild.

ChildWidget(
  colorChild: colorParent,
)

When you want to access the colorChild property of a StatefulWidget you use widget.colorChild, when it has no state, you can simply use colorChild.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark(),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: AppBar(),
        body: Center(
          child: Parent(),
        ),
      ),
    );
  }
}

class Parent extends StatefulWidget {
  @override
  ParentState createState() => ParentState();
}

class ParentState extends State<Parent> {

  // Define the color in parent
  Color colorParent = Colors.red;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: Center(
        child: Row(
          mainAxisSize: MainAxisSize.min,
          children: [

            // Pass the color as a property

            ChildWidget(colorChild: colorParent),
            VerticalDivider(color: colorParent),
            Child2Widget(colorChild: colorParent),
          ],
        ),
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            label: "Tap to Blue",
            icon: Icon(Icons.home),
          ),
          BottomNavigationBarItem(
            label: "Tap to Orange",
            icon: Icon(Icons.dashboard),
          ),
          BottomNavigationBarItem(
            label: "Tap to Green",
            icon: Icon(Icons.palette),
          ),
          // ...
        ],
        onTap: _onItemTap,
      ),
    );
  }

  void _onItemTap(index) {
    // ...
    switch (index) {
      case 0:
        setState(() {
          
          // Update color in parent
          colorParent = Colors.blue;
        });
        break;
      case 1:
        setState(() {
          colorParent = Colors.orange;
        });
        break;
      case 2:
        setState(() {
          colorParent = Colors.green;
        });
        break;
    }
  }
}

class ChildWidget extends StatefulWidget {

  // Define color in child
  final Color colorChild;

  const ChildWidget({Key key, this.colorChild}) : super(key: key);

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

class ChildWidgetState extends State<ChildWidget> {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 100,
      width: 100,
      // Use it
      color: widget.colorChild,
      child: Text('Child 1'),
    );
  }
}

class Child2Widget extends StatelessWidget {

  // Define color in child
  final Color colorChild;

  const Child2Widget({Key key, this.colorChild}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 100,
      width: 100,

      // Use it
      color: colorChild,
      child: Text('Child 2'),
    );
  }
}

Upvotes: 2

Qasim
Qasim

Reputation: 277

please change the default picker color value, please assign the variable that contains any color value, and onTabItem change the value of the variable.

Color _color = Colors.red;

ColorPicker(pickerColor: _color, onColorChanged: (Color colorChanged) { setState(() => _color = colorChanged;},),

Upvotes: 0

Related Questions