How to change positon of SingleChildScrollView according to user gestures and text changes

50 Views Asked by At

I want the user to be able to scroll manually, but also automatically scroll to the bottom when the text changes and when text is out of bound.

This is my calculator app. As you can see, I didn't solve my problem.

enter image description here


class _CalculatorDisplayWidgetState extends State<_CalculatorDisplayWidget> {
  final ScrollController controller = ScrollController();

  @override
  void initState() {
    super.initState();
    controller.addListener(listener);
  }

  void listener() {
    if (controller.offset < controller.position.maxScrollExtent) {
      controller.jumpTo(
        controller.position.maxScrollExtent,
      );
    }
  }

  @override
  void dispose() {
    super.dispose();
    controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Container(
        width: MediaQuery.of(context).size.width,
        color: Colors.yellow,
        padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            Expanded(
              child: SingleChildScrollView(/// TODO
                controller: controller,
                child: Text(
                  widget.state.expression,
                  style: textStyle.copyWith(
                    fontSize: 40,
                  ),
                  textAlign: TextAlign.right,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

in this code, i wrote controller and listener, but it is not what i want.

if there are some solutions, please help me :) Thanks.

2

There are 2 best solutions below

0
On

I solved my problem by didUpdateWidget. here is my code.

class _CalculatorDisplayWidgetState extends State<_CalculatorDisplayWidget> {
  final ScrollController _controller = ScrollController();

  void listener() {
    _controller.jumpTo(
      _controller.position.maxScrollExtent,
    );
  }

  @override
  void didUpdateWidget(covariant _CalculatorDisplayWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    WidgetsBinding.instance.addPostFrameCallback((_) {
      // Execute the listener after the frame is rendered
      listener();
    });
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Container(
        width: MediaQuery.of(context).size.width,
        color: Colors.yellow,
        padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            Expanded(
              child: SingleChildScrollView(
                controller: _controller,
                child: Text(
                  widget.state.expression,
                  style: textStyle.copyWith(
                    fontSize: 40,
                  ),
                  textAlign: TextAlign.right,
                ),
              ),
            ),
            ......

0
On

just change Expanded to container inside the SingleChildScrollView

class _CalculatorDisplayWidgetState extends State<_CalculatorDisplayWidget> {
  final ScrollController controller = ScrollController();

  @override
  void initState() {
    super.initState();
    controller.addListener(listener);
  }

  void listener() {
    if (controller.offset < controller.position.maxScrollExtent) {
      controller.jumpTo(
        controller.position.maxScrollExtent,
      );
    }
  }

  @override
  void dispose() {
    super.dispose();
    controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Container(
        width: MediaQuery.of(context).size.width,
        color: Colors.yellow,
        padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            SingleChildScrollView( 
              controller: controller,
              child: Container(
                height:150,// add your convenient 
                child: Text(
                  widget.state.expression,
                  style: textStyle.copyWith(
                    fontSize: 40,
                  ),
                  textAlign: TextAlign.right,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}