带有滚动条的文本字段?

问题描述 投票:0回答:1

我不想制作一个带有滚动条的文本字段,但具有特定的设计,但我无法移动这个栏,如果有人有解决方案,我会搜索一个包或某个解决方案,但我没有,所以我问也许有人可以帮助我。

有一张我试图达到的目标的图片。

这就是我所拥有的。

我的代码,


MediaQuery.removePadding(
  context: context,
  removeTop: true,
  child: Scrollbar(
    radius: const Radius.circular(5),
    interactive: true,
    isAlwaysShown: true,
    trackVisibility: true,
    controller: scrollController,
    child: TextField(
      scrollController: scrollController,
      scrollPhysics: const BouncingScrollPhysics(),
      scrollPadding: EdgeInsets.zero,

谢谢您的光临。

flutter widget textfield
1个回答
0
投票

您可以使用

ScrollableTexField
创建自己的
SingleChildScrollView
,如下所示:

class ScrollableTextField extends StatefulWidget {
  const ScrollableTextField({
    super.key,
    required this.placeholder,
    required this.controller,
  });

  final String placeholder;
  final TextEditingController controller;

  @override
  State<ScrollableTextField> createState() => _ScrollableTextFieldState();
}

class _ScrollableTextFieldState extends State<ScrollableTextField> {
  final ScrollController _scrollController = ScrollController();

  double _thumbHeight = 0;
  double _thumbTop = 0;

  @override
  void initState() {
    super.initState();
    _scrollController.addListener(_updateThumbPosition);
  }

  void _updateThumbPosition() {
    double maxScroll = _scrollController.position.maxScrollExtent;
    double currentScroll = _scrollController.position.pixels;
    double viewportHeight = _scrollController.position.viewportDimension;
    setState(() {
      if (maxScroll != 0) {
        _thumbTop = (currentScroll / maxScroll) * (viewportHeight - _thumbHeight);
        _thumbHeight = viewportHeight * viewportHeight / (maxScroll + viewportHeight);
      } else {
        _thumbTop = 0;
        _thumbHeight = 0;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) {
        return Stack(
          children: <Widget>[
            SingleChildScrollView(
              controller: _scrollController,
              child: TextField(
                controller: widget.controller,
                keyboardType: TextInputType.multiline,
                maxLines: null,
                decoration: InputDecoration(
                  hintText: widget.placeholder,
                  border: InputBorder.none,
                  counterText: '',
                ),
                onChanged: (value) {
                  WidgetsBinding.instance.addPostFrameCallback((_) {
                    _updateThumbPosition(); // Update the scroll thumb position and height
                  });
                },
              ),
            ),

            // Track
            Positioned(
              top: 0,
              right: 0,
              child: _thumbHeight == 0
                  ? Container()
                  : Container(
                      width: 10,
                      height: constraints.maxHeight,
                      decoration: BoxDecoration(
                        color: Colors.grey[300],
                        borderRadius: BorderRadius.circular(5),
                      )),
            ),

            // Thumb
            Positioned(
              top: _thumbTop,
              right: 0,
              child: Container(
                width: 10,
                height: _thumbHeight,
                decoration: BoxDecoration(
                  color: Colors.blue,
                  borderRadius: BorderRadius.circular(5),
                ),
              ),
            ),
          ],
        );
      },
    );
  }
}

该小部件有两个参数提供

Placeholder
TextEditingController

在代码中,我使用

TextField
进行多行输入,并在更改文本时更新拇指位置。
PostFrameCallback
用于确保拇指在例如全选和删除操作后更新。
Positioned
小部件用于可视化拇指和轨迹。

可以这样使用。我在小部件本身之外添加了一些

Decoration
,但它可以嵌入到内部。

Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Container(
              height: 300,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(8),
                border: Border.all(
                  color: Colors.black,
                  width: 1,
                ),
              ),
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: ScrollableTextField(
                  placeholder: 'Placeholder',
                  controller: TextEditingController(),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

© www.soinside.com 2019 - 2024. All rights reserved.