flutterflutter-layoutrowsinglechildscrollview

How to Automaticallly scroll to a position of a Row inside SingleChildScrollView in Flutter


I am using a SingleChildScrollView. Its scrollDirection is set to Horizontal with >20 child widgets placed inside a Row Widget. I want to programmatically scroll to a position widget(i.e, 5th or 6th position) in the Row. Is there any way to do it programmatically ?

SingleChildScrollView(
    scrollDirection: Axis.horizontal,
    child: Row(
      children: buttons,
    ),
  )

Solution

  • The easiest way to doing this is using Scrollable.ensureVisible.

    ensureVisible method

    Scrolls the scrollables that enclose the given context so as to make the given context visible.

    Please see the code below :

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: const MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _value = 0;
      static final List<GlobalKey> _key = List.generate(20, (index) => GlobalKey());
      final List<Widget> buttons = List.generate(
        20,
        (index) => RaisedButton(
          onPressed: () {},
          color: index % 2 == 0 ? Colors.grey : Colors.white,
          child: Text("Button No # ${index + 1}", key: _key[index]),
        ),
      );
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Column(
            children: [
              SingleChildScrollView(
                scrollDirection: Axis.horizontal,
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: buttons,
                ),
              ),
              DropdownButton(
                value: _value,
                items: List.generate(
                  20,
                  (index) => DropdownMenuItem(
                      child: Text("Goto Button # ${index + 1}"), value: index),
                ),
                onChanged: (value) {
                  setState(() {
                    _value = value;
                    print("calling");
                    Scrollable.ensureVisible(_key[value].currentContext);
                  });
                },
              )
            ],
          ),
        );
      }
    }