如果选择要显示边框 - 颤振

Want to show border if selected - flutter

我想在我的 flutter 应用程序中实现主题 - 我已经到了可以成功更改主题的地步,并且更改主题的对话框按预期弹出...现在我想向用户显示选择了哪个主题所以我想要一个围绕所选主题的边框,如屏幕截图所示

这就是我目前用来选择主题和显示主题选择器容器的代码

    class MultiThemeModel {
      int index;
      String themeName;
      Color color;
      bool selected;
    
      MultiThemeModel(
          {required this.index,
          required this.themeName,
          required this.color,
          required this.selected});
    }
    
    titlesForThemeModel(int index) {
      switch (index) {
        case 0:
          return 'Luxury Purple';
        case 1:
          return 'Red Wine';
      }
      return 'No theme for index';
    }
    
    colorsForThemeModel(int index) {
      switch (index) {
        case 0:
          return purpleBackgroundColor;
        case 1:
          return redBackgroundColor;
      }
    }
    
    selectedForThemeModel(int index) {
      switch (index) {
        case 0:
          return true;
        case 1:
          return false;
      }
    }
    
    List<MultiThemeModel> get themes => List<MultiThemeModel>.generate(
        2,
        (index) => MultiThemeModel(
            index: index,
            themeName: titlesForThemeModel(index),
            color: colorsForThemeModel(index),
            selected: selectedForThemeModel(index)));
    
    List<Widget> get widgets => themes
        .map((themeData) => MultipleThemeViewerWidget(themeData: themeData))
        .toList();
    
    class MultipleThemeViewerWidget extends StatefulWidget {
  MultipleThemeViewerWidget({Key? key, required this.themeData})
      : super(key: key);
  final MultiThemeModel themeData;

  @override
  State<MultipleThemeViewerWidget> createState() =>
      _MultipleThemeViewerWidgetState();
}

class _MultipleThemeViewerWidgetState extends State<MultipleThemeViewerWidget> {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        getThemeManager(context).selectThemeAtIndex(widget.themeData.index);
        setState(() {
          // selectedForThemeModel(widget.themeData.index) =
          widget.themeData.selected = !widget.themeData.selected;
        });
      },
      child: Container(
        height: 60,
        width: 105,
        decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(10),
            color: widget.themeData.color.withOpacity(.3),
            border: widget.themeData.selected
                ? Border.all(color: widget.themeData.color, width: 3)
                : Border.all(color: Colors.white)),
        child: Center(
          child: Text(
            widget.themeData.themeName,
            style: GoogleFonts.poppins(
              textStyle: TextStyle(
                fontSize: 12,
                fontWeight: FontWeight.bold,
                color: widget.themeData.color,
              ),
            ),
          ),
        ),
      ),
    );
  }
}

现在据我所知,如果 id 能够在 MultipleThemeViewerWidget 的 onTap 函数中更改 selectedForThemeModel 的 return 语句,它应该可以工作...我的问题是我不知道这是否可能,如果可能,将如何在 onTap 函数中实现

提前感谢您的帮助!

我认为你需要的是一点重建,尝试转换为有状态的小部件并尝试下面的操作

 return GestureDetector(
      onTap: () {
        getThemeManager(context).selectThemeAtIndex(themeData.index);

        setState(() {});
      },

编辑 稍微提神一下正是我们所需要的,但 setState 不是答案。

使用 ValueNotifier,我们可以立即更新状态。

更改如下

class MultiThemeModel {
  int index;
  String themeName;
  Color color;
  ValueNotifier<bool> selected;

  MultiThemeModel(
      {required this.index,
      required this.themeName,
      required this.color,
      required this.selected});
}

selectedForThemeModel(int index) {
  switch (index) {
    case 0:
      return ValueNotifier(true);
    case 1:
      return ValueNotifier(false);
  }
}

class MultipleThemeViewerWidget extends StatefulWidget {
  MultipleThemeViewerWidget(
      {Key? key, required this.themeData, required this.themes})
      : super(key: key);
  MultiThemeModel themeData;
  List<MultiThemeModel> themes;
  @override
  State<MultipleThemeViewerWidget> createState() =>
      _MultipleThemeViewerWidgetState();
}

class _MultipleThemeViewerWidgetState extends State<MultipleThemeViewerWidget> {
  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder(
        valueListenable: widget.themeData.selected,
        builder: (context, bool selected, _) {
          return GestureDetector(
            onTap: () {
              getThemeManager(context)
                  .selectThemeAtIndex(widget.themeData.index);
              if (!selected) {
                widget.themeData.selected.value = true;
                widget.themes
                    .elementAt(widget.themeData.index == 0 ? 1 : 0)
                    .selected
                    .value = false;
              }
            },
            child: Container(
              height: 60,
              width: 105,
              decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(10),
                  color: widget.themeData.color.withOpacity(.3),
                  border: selected
                      ? Border.all(color: widget.themeData.color, width: 3)
                      : Border.all(color: Colors.white)),
              child: Center(
                child: Text(
                  widget.themeData.themeName,
                  style: TextStyle(
                    fontSize: 12,
                    fontWeight: FontWeight.bold,
                    color: widget.themeData.color,
                  ),
                ),
              ),
            ),
          );
        });
  }

  @override
  void dispose() {
    widget.themeData.selected.dispose();
    super.dispose();
  }
}