Skip to content

feat: support custom AutoScrollController for Scrollbar compatibility#232

Open
MTsung wants to merge 5 commits into
asjqkkkk:mainfrom
MTsung:master
Open

feat: support custom AutoScrollController for Scrollbar compatibility#232
MTsung wants to merge 5 commits into
asjqkkkk:mainfrom
MTsung:master

Conversation

@MTsung
Copy link
Copy Markdown

@MTsung MTsung commented Jul 7, 2025

遇到問題

想使用 Scrollbar 或 RawScrollbar 顯示捲軸時出現錯誤訊息

════════ Exception caught by scheduler library ═════════════════════════════════
The following assertion was thrown during a scheduler callback:
The Scrollbar's ScrollController has no ScrollPosition attached.
A Scrollbar cannot be painted without a ScrollPosition.
The Scrollbar attempted to use the provided ScrollController. This ScrollController should be associated with the ScrollView that the Scrollbar is being applied to.
When providing your own ScrollController, ensure both the Scrollbar and the Scrollable widget use the same one.

修改方式

參考 Stack Overflow 69853729,允許從外部傳入 AutoScrollController。

修改後使用範例

import 'package:flutter/material.dart';
import 'package:markdown_widget/markdown_widget.dart';
import 'package:scroll_to_index/scroll_to_index.dart';

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

  @override
  TestPageState createState() => TestPageState();
}

class TestPageState extends State<TestPage> {
  final AutoScrollController controller = AutoScrollController();

  String md() {
    return '''test
''';
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('test')),
      body: Container(
        color: Colors.white,
        padding: EdgeInsets.all(10),
        height: 250,
        child: RawScrollbar(
          controller: controller,
          thumbVisibility: true,
          child: MarkdownWidget(
            autoScrollController: controller,
            padding: EdgeInsets.all(12),
            shrinkWrap: true,
            data: md() * 100,
          ),
        ),
      ),
    );
  }
}

截圖

截圖 2025-07-07 上午8 22 22

@RoBoT095
Copy link
Copy Markdown

Maybe add null check to _controller.dispose() as the user will probably be disposing controller

@override
void dispose() {
  clearState();
  if (widget.controller == null) _controller.dispose();
  _tocController?.jumpToIndexCallback = null;
  super.dispose();
}

As well as a way to remove controller from ListView.builder without not making controller null

controller: widget.autoScrollController != null &&
        widget.physics != NeverScrollableScrollPhysics()
    ? null
    : _controller,

This is what I did to make scroll position syncing between edit and preview mode, but also be able to use table of contents jump to index

@rebaz94
Copy link
Copy Markdown

rebaz94 commented Sep 10, 2025

controller: widget.autoScrollController != null &&
widget.physics != NeverScrollableScrollPhysics()
? null
: _controller

@RoBoT095

I have same problem of syncing position, just providing the controller fix the issue and be sure not disposing if controller provided.

@MTsung
Copy link
Copy Markdown
Author

MTsung commented Sep 15, 2025

Thanks @RoBoT095 and @rebaz94 for raising this 🙏
I’ve updated the code so that the controller is now safely disposed

-    _controller.dispose();
+    if (widget.autoScrollController == null) _controller.dispose();

GhostenEditor and others added 2 commits September 26, 2025 15:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants