Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[scrollable_positioned_list] expose ScrollPosition as unstableScrollPosition in ScrollOffsetController #535

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

yakagami
Copy link

@yakagami yakagami commented Jun 23, 2024

Description

This PR exposes _scrollableListState.primary.scrollController.position as unstableScrollPosition. This allows developers to use the ScrollPosition of the ScrollablePositionedList to make local jumps eg. jump to 100px from the current index or jump 100px from the current position. The documentation makes clear that position.jumpTo does not work the same way that it does in a ListView. The usage I have in mind for position is the following.

Usage
class _SplDemoState extends State<SplDemo> {
  ScrollOffsetController controller = ScrollOffsetController();
  Drag? _drag;
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onVerticalDragStart: (DragStartDetails details){
        //do something
        _drag = controller.position.drag(details, (){});
      },
      onVerticalDragUpdate: (DragUpdateDetails details){
        //do something
        _drag?.update(details);
      },
      child: ScrollablePositionedList.builder(
        scrollOffsetController: controller,
          itemCount: 100000,
          itemBuilder: (context, index) => Text('Item $index'),
      ),
    );
  }
}

The methods/fields I personally need from position are drag, hold, jumpTo and pixels. I feel at that point it makes sense to just expose the ScrollPositon and let developers use it at their own risk. Note that the current method in ScrollOffsetController, animateScroll, also falls to the same issues around only being relative to the current origin of the list. The

I am also fine with only exposing drag, hold and relativeJumpTo which would look like this:

void relativeJumpTo(double offset){
    final currentPosition = _scrollableListState!.primary.scrollController.offset;
    final newPosition = currentPosition + offset;
    _scrollableListState!.primary.scrollController.jumpTo(newPosition);
  }

I also made the following widget to manually test the functionality of the JumpTo method (as well as the unit test I added)

jumpTo test
import 'package:flutter/material.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';

void main() {
  runApp(const MaterialApp(home: SplTest()));
}

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

  @override
  State<SplTest> createState() => _SplTestState();
}

class _SplTestState extends State<SplTest> {
  final ScrollOffsetController scrollOffsetController = ScrollOffsetController();
  final TextEditingController indexController = TextEditingController();
  final TextEditingController jumpToController = TextEditingController();
  final ItemScrollController itemScrollController = ItemScrollController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Expanded(
            child: ScrollablePositionedList.builder(
              itemScrollController: itemScrollController,
              scrollOffsetController: scrollOffsetController,
              itemCount: 100000000,
              itemBuilder: (context, index) => Text('Item $index'),
            ),
          ),
          Row(
            children: [
              Expanded(
                child: TextField(
                  controller: jumpToController,
                  keyboardType: TextInputType.number,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    hintText: 'Enter an offset',
                  ),
                ),
              ),
              TextButton(
                  onPressed: (){
                    final value = double.parse(jumpToController.value.text);
                    scrollOffsetController.position.jumpTo(value);
                  },
                  child: const Text("jump to offset")
              )
            ],
          ),
          Row(
            children: [
              Expanded(
                child: TextField(
                  controller: indexController,
                  keyboardType: TextInputType.number,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    hintText: 'Enter an index',
                  ),
                ),
              ),
              TextButton(
                  onPressed: (){
                    final value = int.parse(indexController.value.text);
                    itemScrollController.jumpTo(index: value);
                  },
                  child: const Text("jump to index")
              )
            ],
          ),
        ],
      ),
    );
  }
}

I'd like to receive input on this PR and what other options there are to achieve this functionality if exposing the ScrollPosition is not an option. Simply allowing the developer to provide their own ScrollController would work as well. If that is better I'm fine with that too.

Related Issues

#151
#293
#415
#460
#487
#513
#515

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I signed the CLA.
  • All tests from running flutter test pass.
  • flutter analyze does not report any problems on my PR.
  • I am willing to follow-up on review comments in a timely manner.

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.

1 participant