You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter自定义文本编辑器问题:选中容器文本下划线编辑失效

问题

开发一款不依赖flutter_quill等第三方包的自定义文本编辑器,需求是选中对应容器后,仅为该容器内的TextFormField文本添加下划线效果,但当前代码执行后无任何变化,需要修改代码实现逐个编辑的功能。

问题代码

View 代码

import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'editing_state.dart';

class EditingView extends StatefulWidget {
  const EditingView({super.key});

  @override
  State<EditingView> createState() => _EditingViewState();
}

class _EditingViewState extends State<EditingView> {

  final stateView = EditingState();

  final GlobalKey _formKey = GlobalKey();
  final GlobalKey _formKey2 = GlobalKey();

  TextDecoration? textDecoration;
  int selectedIndex = 1;

  final postItController = TextEditingController();
  final postItController2 = TextEditingController();

final Map<String, int> fontTextDecorationMap = {
  'None': 0,
  'Underline': 1,
};

final Map<String, List> formulasTextDecoration= {
  '0': [TextDecoration.none],
  '1': [TextDecoration.underline],
};

  List<TextDecoration> fontListTextDecoration = [
    TextDecoration.none,
    TextDecoration.none
  ];

@override
  Widget build(BuildContext context) {

void changeTextDecoration(textDecoration) {
      int? font = fontTextDecorationMap[textDecoration];
      var resultado = formulasTextDecoration[font.toString()]?[0];

      for(int i = 0; i < fontList.length; i ++){
        if (selectedIndex == 1) {
          fontListTextDecoration[i + 1] = resultado;
        } else {
          fontListTextDecoration[selectedIndex] = resultado;    
        }
      }
    }
return Scaffold(
    appBar: AppBar( title: const Text('Editing')),
    body: Column(
        children: [ 
            Container(
                height: 50, 
                color:const Color(0xFFEBEEF3),
                padding: const EdgeInsets.all(5),
                child: Row(
                    children: [
                        Observer( 
                            return GestureDetector(
                                onTap: (){ 
                                    textDecoration = TextDecoration.underline;
                                    changeTextDecoration(textDecoration); 
                                },
                                child: Container(
                                           decoration: BoxDecoration(
                                                borderRadius: const BorderRadius.all(Radius.circular(4)), 
                                                color: stateView.highlight ? Colors.transparent : const Color(0x5FA1BFF8), 
                                           ), 
                                           child: const Icon(  Icons.format_underline, color: Color(0xFF1F3359), 
                                            ), 
                                        ), 
                                ); 
                            } 
                        ), 
                    ]
                ), 
             ),
            GestureDetector( 
                onTap: () { 
                    setState(() { 
                        selectedIndex = 0; 
                    }); 
                }, 
                child: Container( 
                    height: 300, 
                    width: 300, 
                    padding: const EdgeInsets.all(15), 
                    decoration: 
                        BoxDecoration( 
                            color: Colors.red, 
                            boxShadow: const [ 
                                BoxShadow( 
                                    color: Color(0x3CC2C2C2), 
                                    offset: Offset(5, 5), 
                                    blurRadius: 2, 
                                    spreadRadius: 0.01, 
                                ), 
                            ], 
                       ), 
                    child: Form( 
                        key: _formKey, 
                        child: TextFormField( 
                            controller: postItController, 
                            style: TextStyle( 
                                decoration: fontListTextDecoration[0], 
                            ), 
                        ), 
                    ), 
                ), 
             ),
             GestureDetector( 
                onTap: () { 
                    setState(() { 
                        selectedIndex = 0; 
                    }); 
                }, 
                child: Container( 
                    height: 300, 
                    width: 300, 
                    padding: const EdgeInsets.all(15), 
                    decoration: 
                        BoxDecoration( 
                            color: Colors.blue, 
                            boxShadow: const [ 
                                BoxShadow( 
                                    color: Color(0x3CC2C2C2), 
                                    offset: Offset(5, 5), 
                                    blurRadius: 2, 
                                    spreadRadius: 0.01, 
                                ), 
                            ], 
                       ), 
                    child: Form( 
                        key: _formKey2, 
                        child: TextFormField( 
                            controller: postItController2, 
                            style: TextStyle( 
                                decoration: fontListTextDecoration[1], 
                            ), 
                        ), 
                    ), 
                ), 
             )
           ],
         ),
      );
    }
}

State 代码

import 'package:mobx/mobx.dart';

part 'editing_state.g.dart';

class EditingState = _EditingState with _$EditingState;

abstract class _EditingState with Store {

@observable
bool _highlight  = true;

@computed
bool get highlight  => _highlight ;

@action
void changeHighlight() {
_highlight  = !_highlight ;
}

@action
void resetState() {
_highlight = true;
}
}

editing_state.g.dart 代码

// GENERATED CODE - DO NOT MODIFY BY HAND

part of 'editing_state.dart';

// **************************************************************************
// StoreGenerator
// **************************************************************************

// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic, no_leading_underscores_for_local_identifiers

mixin _$EditingState on _EditingState, Store {
  Computed<bool>? _$highlightComputed;

  @override
  bool get highlight=> (_$highlightComputed ??=
          Computed<bool>(() => super.highlight, name: '_EditingState.highlight'))
      .value;

  late final _$_highlightAtom =
      Atom(name: '_EditingState._highlight', context: context);

  @override
  bool get _highlight {
    _$_highlightAtom.reportRead();
    return super._highlight;
  }

  @override
  set _highlight(bool value) {
    _$_highlightAtom.reportWrite(value, super._highlight, () {
      super._highlight = value;
    });
  }

  late final _$_EditingStateActionController =
      ActionController(name: '_EditingState', context: context);

  @override
  void changeHighlight() {
    final _$actionInfo = _$_EditingStateActionController.startAction(
        name: '_EditingState.changeHighlight');
    try {
      return super.changeHighlight();
    } finally {
      _$_EditingStateActionController.endAction(_$actionInfo);
    }
  }

  @override
  void resetState() {
    final _$actionInfo = _$_EditingStateActionController.startAction(
        name: '_EditingState.resetState');
    try {
      return super.resetState();
    } finally {
      _$_EditingStateActionController.endAction(_$actionInfo);
    }
  }

  @override
  String toString() {
    return '''
highlight: ${highlight}
    ''';
  }
}
修复方案

以下是核心修改点及完整修复代码:

  • 修正容器选中索引:第二个GestureDetector的selectedIndex设为1,确保选中第二个容器时对应正确的文本框索引。
  • 修复下划线功能参数传递:changeTextDecoration接收字符串参数(匹配fontTextDecorationMap的key),而非TextDecoration对象,避免映射匹配失败。
  • 简化样式更新逻辑:移除不必要的循环,直接更新选中索引对应的样式,修改后调用setState触发UI刷新。
  • 修正Observer语法:Observer通过builder回调返回Widget,符合Mobx组件规范。
  • 修正GestureDetector结构:确保child属性正确包裹容器,语法符合Flutter要求。

修改后的完整View代码

import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'editing_state.dart';

class EditingView extends StatefulWidget {
  const EditingView({super.key});

  @override
  State<EditingView> createState() => _EditingViewState();
}

class _EditingViewState extends State<EditingView> {
  final stateView = EditingState();

  final GlobalKey _formKey = GlobalKey();
  final GlobalKey _formKey2 = GlobalKey();

  int selectedIndex = 0; // 默认选中第一个容器

  final postItController = TextEditingController();
  final postItController2 = TextEditingController();

  final Map<String, int> fontTextDecorationMap = {
    'None': 0,
    'Underline': 1,
  };

  final Map<String, TextDecoration> formulasTextDecoration = {
    '0': TextDecoration.none,
    '1': TextDecoration.underline,
  };

  List<TextDecoration> fontListTextDecoration = [
    TextDecoration.none,
    TextDecoration.none
  ];

  void changeTextDecoration(String decorationType) {
    int? fontType = fontTextDecorationMap[decorationType];
    if (fontType != null) {
      TextDecoration? newDecoration = formulasTextDecoration[fontType.toString()];
      if (newDecoration != null) {
        setState(() {
          fontListTextDecoration[selectedIndex] = newDecoration;
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: const AppBar(title: Text('Editing')),
      body: Column(
        children: [
          Container(
            height: 50,
            color: const Color(0xFFEBEEF3),
            padding: const EdgeInsets.all(5),
            child: Row(
              children: [
                Observer(builder: (context) {
                  return GestureDetector(
                    onTap: () {
                      stateView.changeHighlight();
                      changeTextDecoration('Underline');
                    },
                    child: Container(
                      decoration: BoxDecoration(
                        borderRadius: const BorderRadius.all(Radius.circular(4)),
                        color: stateView.highlight ? Colors.transparent : const Color(0x5FA1BFF8),
                      ),
                      child: Icon(
                        Icons.format_underline,
                        color: stateView.highlight ? const Color(0xFF1F3359) : const Color.fromARGB(255, 20, 33, 56),
                      ),
                    ),
                  );
                }),
              ],
            ),
          ),
          GestureDetector(
            onTap: () {
              setState(() {
                selectedIndex = 0;
              });
            },
            child: Container(
              height: 300,
              width: 300,
              padding: const EdgeInsets.all(15),
              decoration: BoxDecoration(
                color: Colors.red,
                boxShadow: const [
                  BoxShadow(
                    color: Color(0x3CC2C2C2),
                    offset: Offset(5, 5),
                    blurRadius: 2,
                    spreadRadius: 0.01,
                  ),
                ],
              ),
              child: Form(
                key: _formKey,
                child: TextFormField(
                  controller: postItController,
                  style: TextStyle(
                    decoration: fontListTextDecoration[0],
                  ),
                ),
              ),
            ),
          ),
          GestureDetector(
            onTap: () {
              setState(() {
                selectedIndex = 1; // 修正为1,对应第二个文本框
              });
            },
            child: Container(
              height: 300,
              width: 300,
              padding: const EdgeInsets.all(15),
              decoration: BoxDecoration(
                color: Colors.blue,
                boxShadow: const [
                  BoxShadow(
                    color: Color(0x3CC2C2C2),
                    offset: Offset(5, 5),
                    blurRadius: 2,
                    spreadRadius: 0.01,
                  ),
                ],
              ),
              child: Form(
                key: _formKey2,
                child: TextFormField(
                  controller: postItController2,
                  style: TextStyle(
                    decoration: fontListTextDecoration[1],
                  ),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

修复说明

  1. 索引匹配:第二个容器选中索引改为1,与fontListTextDecoration的索引一一对应,确保样式更新目标正确。
  2. 参数修正:传递字符串'Underline'给changeTextDecoration,正确匹配映射表中的key,获取对应的下划线样式。
  3. UI刷新触发:修改样式后调用setState,强制Flutter重新渲染文本框,应用新的样式。
  4. 组件规范修正:修复Observer的builder结构,符合Mobx的正确使用方式;调整GestureDetector的子组件包裹逻辑,解决语法错误。
  5. 性能优化:将changeTextDecoration移到build方法外,避免每次build重复创建函数。

内容的提问来源于stack exchange,提问作者user121212121

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 15:24:56