flutter - How to auto scroll to index with dynamic height programmatically flutter - How to auto scroll to index with dynamic height programmatically flutter flutter

flutter - How to auto scroll to index with dynamic height programmatically


Your question

so, What's a temporary solution to make ListView with AutoScroll for dynamic height?

Screen Record

enter image description here

solution

scroll-to-index package

This package provides the scroll to index mechanism for fixed/variable row height for Flutter scrollable widget.

This is a widget level library, means you can use this mechanism inside any Flutter scrollable widget.

Usage

pubspec.yaml

 scroll_to_index: any

Example From quire-io/scroll-to-index: scroll to index with fixed/variable row height inside Flutter scrollable widget

Usage - Controller

controller.scrollToIndex(index, preferPosition: AutoScrollPosition.begin)

Usage - ListView

ListView(scrollDirection: scrollDirection,controller: controller,children: randomList.map<Widget>((data) {    final index = data[0];    final height = data[1];    return AutoScrollTag(    key: ValueKey(index),    controller: controller,    index: index,    child: Text('index: $index, height: $height'),    highlightColor: Colors.black.withOpacity(0.1),    );}).toList(),)

Extra anunixercoder asked

Is this for finite or infinite list ?

Using ListView.builder to simulate an infinite list

    ListView.builder(    scrollDirection: scrollDirection,    controller: controller,    itemBuilder: (context, i) => Padding(      padding: EdgeInsets.all(8),      child: _getRow(i, (min + rnd.nextInt(max - min)).toDouble()),    ),

It got 18 right of 22 tries , about (81%) or near to it

Screen Record

enter image description here

so it not suported 100%

Ref :

1st screen record code

//Copyright (C) 2019 Potix Corporation. All Rights Reserved.//History: Tue Apr 24 09:29 CST 2019// Author: Jerry Chenimport 'dart:math' as math;import 'package:flutter/material.dart';import 'package:scroll_to_index/scroll_to_index.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {  // This widget is the root of your application.  @override  Widget build(BuildContext context) {    return MaterialApp(      title: 'Scroll To Index Demo',      theme: ThemeData(        primarySwatch: Colors.blue,      ),      home: MyHomePage(title: 'Scroll To Index Demo'),    );  }}class MyHomePage extends StatefulWidget {  MyHomePage({Key key, this.title}) : super(key: key);  final String title;  @override  _MyHomePageState createState() => _MyHomePageState();}class _MyHomePageState extends State<MyHomePage> {  static const maxCount = 100;  final random = math.Random();  final scrollDirection = Axis.vertical;  AutoScrollController controller;  List<List<int>> randomList;  @override  void initState() {    super.initState();    controller = AutoScrollController(      viewportBoundaryGetter: () => Rect.fromLTRB(0, 0, 0, MediaQuery.of(context).padding.bottom),      axis: scrollDirection    );    randomList = List.generate(maxCount, (index) => <int>[index, (1000 * random.nextDouble()).toInt()]);  }  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(        title: Text(widget.title),      ),      body: ListView(        scrollDirection: scrollDirection,        controller: controller,        children: randomList.map<Widget>((data) {          return Padding(            padding: EdgeInsets.all(8),            child: _getRow(data[0], math.max(data[1].toDouble(), 50.0)),          );        }).toList(),      ),      floatingActionButton: FloatingActionButton(        onPressed: _scrollToIndex,        tooltip: 'Increment',        child: Text(counter.toString()),      ),    );  }  int counter = -1;  Future _scrollToIndex() async {    setState(() {      counter++;      if (counter >= maxCount)        counter = 0;    });    await controller.scrollToIndex(counter, preferPosition: AutoScrollPosition.begin);    controller.highlight(counter);  }  Widget _getRow(int index, double height) {    return _wrapScrollTag(      index: index,      child: Container(        padding: EdgeInsets.all(8),        alignment: Alignment.topCenter,        height: height,        decoration: BoxDecoration(          border: Border.all(            color: Colors.lightBlue,            width: 4          ),          borderRadius: BorderRadius.circular(12)        ),        child: Text('index: $index, height: $height'),      )    );  }  Widget _wrapScrollTag({int index, Widget child})  => AutoScrollTag(    key: ValueKey(index),    controller: controller,    index: index,    child: child,    highlightColor: Colors.black.withOpacity(0.1),  );}

2nd screen record code :

//Copyright (C) 2019 Potix Corporation. All Rights Reserved.//History: Tue Apr 24 09:29 CST 2019// Author: Jerry Chenimport 'dart:math' as math;import 'package:flutter/material.dart';import 'package:scroll_to_index/scroll_to_index.dart';void main() => runApp(MyApp());class MyApp extends StatelessWidget {  // This widget is the root of your application.  @override  Widget build(BuildContext context) {    return MaterialApp(      title: 'Scroll To Index Demo',      theme: ThemeData(        primarySwatch: Colors.blue,      ),      home: MyHomePage(title: 'Scroll To Index Demo'),    );  }}class MyHomePage extends StatefulWidget {  MyHomePage({Key key, this.title}) : super(key: key);  final String title;  @override  _MyHomePageState createState() => _MyHomePageState();}class _MyHomePageState extends State<MyHomePage> {  final scrollDirection = Axis.vertical;  var rnd = math.Random();  int min = 50;  int max = 200;  AutoScrollController controller;  @override  void initState() {    super.initState();    controller = AutoScrollController(        viewportBoundaryGetter: () =>            Rect.fromLTRB(0, 0, 0, MediaQuery.of(context).padding.bottom),        axis: scrollDirection);  }  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(        title: Text(widget.title),      ),      body: ListView.builder(        scrollDirection: scrollDirection,        controller: controller,        itemBuilder: (context, i) => Padding(          padding: EdgeInsets.all(8),          child: _getRow(i, (min + rnd.nextInt(max - min)).toDouble()),        ),      ),      floatingActionButton: FloatingActionButton(        onPressed: _scrollToIndex,        tooltip: 'Increment',        child: Text(counter.toString()),      ),    );  }  int counter = -1;  Future _scrollToIndex() async {    setState(() {      counter++;    });    await controller.scrollToIndex(counter,        preferPosition: AutoScrollPosition.begin);    controller.highlight(counter);  }  Widget _getRow(int index, double height) {    return _wrapScrollTag(        index: index,        child: Container(          padding: EdgeInsets.all(8),          alignment: Alignment.topCenter,          height: height,          decoration: BoxDecoration(              border: Border.all(color: Colors.lightBlue, width: 4),              borderRadius: BorderRadius.circular(12)),          child: Text('index: $index, height: $height'),        ));  }  Widget _wrapScrollTag({int index, Widget child}) => AutoScrollTag(        key: ValueKey(index),        controller: controller,        index: index,        child: child,        highlightColor: Colors.black.withOpacity(0.1),      );}


This package might be the one you are looking for. You can assign id for each widget and enable an animation just like tags in HTML.

https://pub.dev/packages/scroll_to_id

import 'package:flutter/material.dart';import 'package:scroll_to_id/scroll_to_id.dart';void main() {  runApp(MyApp());}class MyApp extends StatefulWidget {  @override  _MyAppState createState() => _MyAppState();}class _MyAppState extends State<MyApp> {  final ScrollToId scrollToId = ScrollToId();  @override  Widget build(BuildContext context) {    return MaterialApp(      title: 'Scroll to ID',      theme: ThemeData(        primarySwatch: Colors.blue,      ),      home: Scaffold(        appBar: AppBar(          title: const Text('Scroll to ID'),        ),        body: Stack(          alignment: Alignment.topRight,          children: [            InteractiveScrollViewer(              scrollToId: scrollToId,              children: [                ScrollContent(                  id: '1',                  child: Container(                    height: 600,                    color: Colors.green,                  ),                ),                ScrollContent(                  id: '2',                  child: Container(                    height: 800,                    color: Colors.red,                  ),                ),                ScrollContent(                  id: '3',                  child: Container(                    height: 300,                    color: Colors.yellow,                  ),                ),                ScrollContent(                  id: '4',                  child: Container(                    height: 700,                    color: Colors.blue,                  ),                ),              ],            ),            Container(              decoration: BoxDecoration(                border: Border.all(color: Colors.white, width: 3),              ),              child: Column(                mainAxisSize: MainAxisSize.min,                children: [                  GestureDetector(                    child: Container(                      width: 100,                      alignment: Alignment.center,                      height: 50,                      child: Text('1', style: TextStyle(color: Colors.white),),                      color: Colors.green,                    ),                    onTap: () {                      scrollToId.scroll(id: '1');                    },                  ),                  GestureDetector(                    child: Container(                      width: 100,                      alignment: Alignment.center,                      height: 50,                      child: Text('2', style: TextStyle(color: Colors.white),),                      color: Colors.red,                    ),                    onTap: () {                      scrollToId.scroll(id: '2');                    },                  ),                  GestureDetector(                    child: Container(                      width: 100,                      alignment: Alignment.center,                      height: 50,                      child: Text('3', style: TextStyle(color: Colors.white),),                      color: Colors.yellow,                    ),                    onTap: () {                      scrollToId.scroll(id: '3');                    },                  ),                  GestureDetector(                    child: Container(                      width: 100,                      alignment: Alignment.center,                      height: 50,                      child: Text('4', style: TextStyle(color: Colors.white),),                      color: Colors.blue,                    ),                    onTap: () {                      scrollToId.scroll(id: '4');                    },                  ),                ],              ),            )          ],        ),      ),    );  }}


How observe current offset index?

    controller.addListener(() {      AutoScrollTagState sts = controller.tagMap[0];      print(sts);    });