如何根据不同的 Widget 改变 Widget 的颜色?

     2023-02-23     91

关键词:

【中文标题】如何根据不同的 Widget 改变 Widget 的颜色?【英文标题】:How to change the color of a Widget based on a different Widget? 【发布时间】:2021-06-29 18:21:24 【问题描述】:

我正在尝试制作显示SvgPicture.assets() 的简单应用程序,用户可以使用颜色选择器更改SvgPicture() 的颜色。

我有 2 个小部件:

    用于显示 SvgPicture() 将其称为 Svg.dart main.dart 包含 BottomNavigationView,其中一个选项卡打开颜色选择器,Svg.dart

我在使用setState(() ) 时遇到了一些错误,但我设法以某种方式修复了错误,但它并没有改变颜色,当我尝试更改main.dart 的背景颜色时,它工作得很好。

这是我的代码:

BottomNavigationBaronItemTap() 方法

  void _onItemTap(int index) 
  setState(() 
    if (index == 0) 
    // First Tab
    
    if (index == 1) 
    // SecondTab
    
    if (index == 2) 
    // Third Tab
    
    if (index == 3) 
      showDialog(
        context: context,
        builder: (BuildContext context)
          return AlertDialog(
            content:
            SingleChildScrollView(
              child: new ColorPicker(
                pickerColor: Colors.red,
                onColorChanged: (Color colorChanged) 
                  color = colorChanged;
           // (color) is assigned default value of Colors.red
           // here I'm trying to assign new value to (color)
                ,
              ),//ColorPicker
            ),//SingleChildScrollView
          );//AlertDialog
        );
    
  );

然后在Svg.dart 中我创建了另一个变量Color picked = Colors.red 并将红色指定为默认值。这就是Svg.dart 小部件代码的样子:

  Widget build(BuildContext context) 
  setState(() 
    picked = main().createState().color;
  );
  return CustomMultiChildLayout(
    delegate: TempDelegate(
        position: Offset.zero
    ),
    children: [
      buildLayoutId(ids.shirtId, MyConstants.shirt, picked)
    ],
  );

LayoutId buildLayoutId(Object id, String item, Color color) 
  return LayoutId(
      id: id,
      child: SvgPicture.asset(
        item,
        color: color,
      ),
    );

我尝试寻找颤振文档,但我真的不知道问题是如何/在哪里,也没有找到教程,请帮助

编辑

这是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;
                        );
                      ,
                    ),
                  ),
                );
              );
          
        );
      
    

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,
        ),
      );
  

Svg.dart 中为CustomMultichildLayout 扩展MultiChildLyoutDelegate 的类

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;
     

【问题讨论】:

如果svgBottomNavigationBarmain 中,color = colorChanged; 应该被 setState 包围。我认为您不需要在svg 中使用picked,全局变量color 就可以了。你能分享main的代码吗? 你能分享你完整的 StatefulWidget 代码吗?顺便说一句,在构建期间不要使用setState(()) @EdwardLi 我应用了更改并分享了编辑后的代码,请查看。 @Gilang 我不确定是否理解你,我是 noop 哈哈 【参考方案1】:

在 Flutter 中,一切都是小部件,您可以创建自己的自定义小部件。 同样,还有层次结构和状态等概念。

无状态小部件是 StatelessWidget,例如标签、背景、标题或其他任何东西。

有状态的小部件是 StatefulWidget,它是可以变化的东西,例如开关、动画背景、页面等。还有一个 InheritedWidget,但这是另一个主题。

setStateStatefulWidget 中用于更新that 小部件的状态,要从父级更新子级,可以使用子级的属性。 当setState 被调用时,它会在必要时重建小部件及其子部件。

Container 小部件具有 color 属性。

Container(
  color: colorParent,
)

您的自定义小部件还可以具有任何属性,例如 colorsizecolorChild

ChildWidget(
  colorChild: colorParent,
)

当你想访问StatefulWidgetcolorChild 属性时,你使用widget.colorChild,当它没有状态时,你可以简单地使用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'),
    );
  

【讨论】:

成功了!非常感谢你,现在我对颤振的工作原理有了更好的理解。我还有一个问题要了解无状态/完整,当 colorParent 更改时,无状态和有状态小部件颜色都会发生变化,是不是因为 Parent 在每次点击时都会以不同的颜色重建,因此子小部件会跟随父小部件并重建?因为我对它构建一次的无状态小部件的理解就是这样。再次感谢您的解释,这非常有帮助 不客气!,是的,你是对的,statelessWidget 不会重建自己,也就是说,无状态的任何内部操作都不会重建它(这就是为什么 MyApp 是无状态的),但在这种情况下,有一个外部 parent 代理会杀死它(哎哟!)并创建一个新代理。但是,如果要创建不重新构建的小部件,可以在任何小部件之前添加const(这对性能非常有用),但您不能再在其参数中传递变量,只能传递常量。【参考方案2】:

请更改默认选择器颜色值,请分配包含任何颜色值的变量,onTabItem 更改该变量的值。

颜色_color = Colors.red;

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

【讨论】:

Flutter中如何改变Widget在Column或Row中的显示顺序

】Flutter中如何改变Widget在Column或Row中的显示顺序【英文标题】:howtochangethedisplayingorderoftheWidgetsinColumnorRowinFlutter【发布时间】:2021-09-0602:13:50【问题描述】:我正在创建一个基本的聊天应用程序,其中我正在使用一个行小部件... 查看详情

如何在 Widget 之外调度 Bloc 事件?

】如何在Widget之外调度Bloc事件?【英文标题】:HowtodispatchBloceventsoutsideofWidget?【发布时间】:2020-12-0709:10:15【问题描述】:我是Bloc架构的新手,最近看了一些教程。我有一个StatelessWidget页面,在里面我使用BlocProvider在我的UI中... 查看详情

odoo内部视图格式——widget

Odoo视图层的filed有很多种显示风格,根据字段具体内容的不同,可以通过widget属性指明对应的显示风格。其中,内置的有以下几种:widget="statusbar"头部状态条标签widget="email"电子邮件地址标签widget="selection"下拉选择标签widget="mail_... 查看详情

odoo内部视图格式——widget

Odoo视图层的filed有很多种显示风格,根据字段具体内容的不同,可以通过widget属性指明对应的显示风格。其中,内置的有以下几种:widget="statusbar"头部状态条标签widget="email"电子邮件地址标签widget="selection"下拉选择标签widget="mail_... 查看详情

ios14widget小组件开发(widgetextension)

...要渲染的属性。Timeline的刷新策略是会延迟的,并不一定根据你设定的时间精确刷新。同时官方说明了每个widget窗口小部件每天接收的刷新都会有数量限制TimelineProvider官方解释渲染Widget所需的数据模型,需要遵守TimelineEntry协议... 查看详情

如何根据 Widget Kivy 属性更新**动态添加的**椭圆(不使用 Builder)的颜色?

】如何根据WidgetKivy属性更新**动态添加的**椭圆(不使用Builder)的颜色?【英文标题】:HowdoIupdatetheColorofa**dynamicallyadded**Ellipse(notusingBuilder)accordingtoWidgetKivyproperties?【发布时间】:2013-06-0803:05:08【问题描述】:这与thisotherquestion... 查看详情

如何根据 Widget Kivy 属性更新**动态添加的**椭圆(不使用 Builder)的颜色?

】如何根据WidgetKivy属性更新**动态添加的**椭圆(不使用Builder)的颜色?【英文标题】:HowdoIupdatetheColorofa**dynamicallyadded**Ellipse(notusingBuilder)accordingtoWidgetKivyproperties?【发布时间】:2013-06-0803:05:08【问题描述】:这与thisotherquestion... 查看详情

如何将 Future<Widget> 作为小部件返回

】如何将Future<Widget>作为小部件返回【英文标题】:HowtoreturnFuture<Widget>asWidget【发布时间】:2020-10-2118:12:15【问题描述】:下面的代码可能看起来有点复杂,但基本上下面的函数使用一个switchcase根据导航栏的索引号返回... 查看详情

将 Widget Builders 之类的类成员提取到不同的文件中?

...:在为我的Flutter应用程序开发一些屏幕时,我经常需要根据屏幕状态动态渲染小部件。对于需要创建单独的小部件并包含它的情况,我会这样做。但是,在许多用例中,我需要渲染的内容不适合小部件 查看详情

android开发桌面时钟,怎么根据系统时间的变化更新widget

雏形已经写好了,但是就是不知道怎么根据系统时间的变化来更新Widget的时间,百度找了半天也没有找到有用的资料,有个网站有源代码的下载,但是要付费的会员才能下(汗)第一次学着写Widget,很多地方都不懂,哪位大侠有... 查看详情

Flutter 自定义布局,根据子元素决定 widget 的大小

】Flutter自定义布局,根据子元素决定widget的大小【英文标题】:Fluttercustomlayout,decidewidget\'ssizebasedonitschild【发布时间】:2020-10-3014:11:59【问题描述】:understandingconstraints文章对于了解布局的工作原理非常有用。但是,我在创建... 查看详情

如何改变androidprogressbar默认颜色

如何改变AndroidProgressbar默认颜色默认情况下IndeterminateProgressbar是白色的,如果容器的背景也是白色的,这样就根本看不到Progressbar了。幸好Android自带了一些反转样式,你可以采用其中一个合适的:http://stackoverflow.com/questions/2638161... 查看详情

Android-Widget:使用 RemoteView 更改 ListView 选择器颜色

...view设置appWidget上存在的listView的选择器颜色。基本上我想根据用户选择的主题来改变它的颜色,所以我不能在布局xml 查看详情

flutter基础组件:widget简介(代码片段)

...中几乎所有的对象都是一个Widget。与原生开发中“控件”不同的是,Flutter中的Widget的概念更广泛,它不仅可以表示UI元素,也可以表示一些功能性的组件如:用于手势检测的GestureDetectorwidget、用于APP主题数据传递的Theme等等,而... 查看详情

tkinter中widget配置

通过设置属性来改变Widget的外观常见的属性包括text(显示的文字)、color(前景色和背景色)、size(宽度和高度)、commandcallbacks(点击后的回调函数)等等1.设置属性,有3种方式:1)在创建Widget时,通过关键字参数设定widgetclass(master,opti... 查看详情

Flutter Bloc 如何从 Widget 本身更新 BlocBuilder 中的 Widget?

】FlutterBloc如何从Widget本身更新BlocBuilder中的Widget?【英文标题】:FlutterBlocHowtoupdateWidgetinBlocBuilderfromtheWidgetitself?【发布时间】:2021-04-2301:10:51【问题描述】:如何使用Slider从blocWidget本身更新Bloc小部件?图表数据的事件是从另... 查看详情

android如何自定义menu

最近想做个一排6个操作的menu但是默认的menu会换行查了下资料和论坛,很多人说使用PopupWindow,但是这个感觉和menu有很大的区别,因为显示Popupwindow后,界面其他部分不能点击了,他也不会被点击隐藏还有人使用布局的显示隐藏实... 查看详情

如何将 Qline 坐标发送到 QPainter Widget

】如何将Qline坐标发送到QPainterWidget【英文标题】:howtosendQlinecoordinatetoaQPainterWidget【发布时间】:2011-05-2805:22:19【问题描述】:我创建了一个QwidgetForm_temp,它根据在父窗口小部件MainWindow中创建的数据数组绘制线条。我面临的问... 查看详情