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

Flutter:如何在程序化选中文本后显示两端光标

在Flutter中实现选中文本两端显示光标

默认Flutter的TextField在选中文本时仅显示选区末尾的单个光标,要实现选中区域两端都显示光标,可通过自定义光标绘制逻辑实现:

修改后的代码

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

class ExampleActivity extends StatefulWidget {
  ExampleActivity({super.key});

  @override
  State<ExampleActivity> createState() => _ExampleActivityState();
}

class _ExampleActivityState extends State<ExampleActivity> {
  final _controller = TextEditingController();

  @override
  void initState() {
    super.initState();
    _controller.text = "Lorem Ipsum " * 5;
    _controller.selection = const TextSelection(baseOffset: 12, extentOffset: 23);
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: TextField(
          controller: _controller,
          keyboardType: TextInputType.multiline,
          maxLines: null,
          autofocus: true,
          showCursor: true,
          expands: true,
          enableInteractiveSelection: true,
          toolbarOptions: const ToolbarOptions(
            copy: false,
            cut: false,
            paste: false,
            selectAll: false,
          ),
          buildCursor: (context, offset, cursorColor, cursorRadius, cursorWidth) {
            final selection = _controller.selection;
            if (!selection.isCollapsed) {
              return Stack(
                children: [
                  _buildCursor(context, selection.baseOffset, cursorColor, cursorRadius, cursorWidth),
                  _buildCursor(context, selection.extentOffset, cursorColor, cursorRadius, cursorWidth),
                ],
              );
            }
            return _buildCursor(context, offset, cursorColor, cursorRadius, cursorWidth);
          },
        ),
      ),
    );
  }

  Widget _buildCursor(BuildContext context, int offset, Color cursorColor, Radius cursorRadius, double cursorWidth) {
    final renderEditable = context.findRenderObject() as RenderEditable;
    final caretOffset = renderEditable.getOffsetForCaret(TextPosition(offset: offset), Rect.zero);
    return Positioned(
      left: caretOffset.dx,
      top: 0,
      bottom: 0,
      child: Container(
        width: cursorWidth,
        decoration: BoxDecoration(
          color: cursorColor,
          borderRadius: BorderRadius.all(cursorRadius),
        ),
      ),
    );
  }
}

核心逻辑

  1. 利用TextField的buildCursor回调自定义光标渲染逻辑
  2. 检测文本选中状态:当selection.isCollapsed为false时,判定存在选中区域
  3. 分别基于选区的baseOffset(起始位置)和extentOffset(结束位置)绘制两个独立光标
  4. 通过RenderEditable获取光标在屏幕上的精确偏移量,确保光标与文本位置精准对齐

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 11:55:59