s_gridview 2.0.1 copy "s_gridview: ^2.0.1" to clipboard
s_gridview: ^2.0.1 copied to clipboard

A lightweight, customizable grid-like Flutter widget with index-based scrolling and tappable scroll indicators

example/lib/main.dart

import 'package:flutter/material.dart';
// ignore: depend_on_referenced_packages
import 'package:indexscroll_listview_builder/indexscroll_listview_builder.dart';
import 'package:s_gridview/s_gridview.dart';

void main() {
  runApp(const ExampleApp());
}

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 's_gridview Example',
      home: const ExampleHome(),
    );
  }
}

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

  @override
  State<ExampleHome> createState() => _ExampleHomeState();
}

class _ExampleHomeState extends State<ExampleHome> {
  final IndexedScrollController _controller = IndexedScrollController();
  Axis _direction = Axis.vertical;
  int _crossAxis = 3;
  bool _showScrollIndicators = true;
  Color? _indicatorColor = Colors.yellow.shade600;
  int? _autoIndex;
  double _scrollFraction = 1.0;
  final TextEditingController _textC = TextEditingController();

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

  @override
  Widget build(BuildContext context) {
    final List<Widget> items = List.generate(
      30,
      (i) => Container(
        width: 100,
        height: 80,
        color: Colors.primaries[i % Colors.primaries.length],
        child: Center(
          child: Text('Item ${i + 1}'),
        ),
      ),
    );

    return Scaffold(
      appBar: AppBar(title: const Text('s_gridview Example')),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Wrap(
              spacing: 8,
              runSpacing: 8,
              children: [
                ElevatedButton(
                  onPressed: () => setState(() => _direction =
                      _direction == Axis.vertical
                          ? Axis.horizontal
                          : Axis.vertical),
                  child: Text(
                      _direction == Axis.vertical ? 'Vertical' : 'Horizontal'),
                ),
                ElevatedButton(
                  onPressed: () =>
                      setState(() => _crossAxis = (_crossAxis % 6) + 1),
                  child: Text('crossAxisItemCount: $_crossAxis'),
                ),
                SwitchListTile(
                  value: _showScrollIndicators,
                  onChanged: (v) => setState(() => _showScrollIndicators = v),
                  title: const Text('Show Scroll Indicators'),
                  dense: true,
                ),
                ElevatedButton(
                  onPressed: () =>
                      setState(() => _indicatorColor = Colors.red.shade400),
                  child: const Text('Indicator Red'),
                ),
                ElevatedButton(
                  onPressed: () =>
                      setState(() => _indicatorColor = Colors.green.shade600),
                  child: const Text('Indicator Green'),
                ),
                ElevatedButton(
                  onPressed: () =>
                      setState(() => _indicatorColor = Colors.blue.shade600),
                  child: const Text('Indicator Blue'),
                ),
                ElevatedButton(
                  onPressed: () async {
                    // Programmatic scroll using the external controller
                    // Clear autoIndex to avoid conflicts
                    setState(() => _autoIndex = null);
                    await _controller.scrollToIndex(
                      20,
                      alignmentOverride: 0.35,
                      itemCount: items.length,
                    );
                    // Mounted check after async operation
                    if (!mounted) return;
                  },
                  child: const Text('Scroll to #21 (via controller)'),
                ),
                SizedBox(
                  width: 160,
                  child: TextField(
                    controller: _textC,
                    decoration: const InputDecoration(
                        hintText: 'Enter index to auto-scroll'),
                    keyboardType: TextInputType.number,
                  ),
                ),
                ElevatedButton(
                  onPressed: () {
                    setState(() {
                      final int? v = int.tryParse(_textC.text);
                      _autoIndex = v;
                    });
                  },
                  child: const Text('Set autoScrollToIndex (build)'),
                ),
                ElevatedButton(
                  onPressed: () {
                    // Example of demonstration clamping: set to large value
                    setState(() => _autoIndex = 999);
                  },
                  child: const Text('Auto scroll (out-of-bounds)'),
                ),
              ],
            ),
          ),
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16.0),
            child: Row(
              children: [
                const Text('Indicator Scroll Distance:'),
                Expanded(
                  child: Slider(
                    value: _scrollFraction,
                    min: 0.1,
                    max: 2.0,
                    divisions: 19,
                    label: '${(_scrollFraction * 100).toStringAsFixed(0)}%',
                    onChanged: (value) {
                      setState(() => _scrollFraction = value);
                    },
                  ),
                ),
                Text(
                  '${(_scrollFraction * 100).toStringAsFixed(0)}% of viewport',
                  style: const TextStyle(fontWeight: FontWeight.bold),
                ),
              ],
            ),
          ),
          Expanded(
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: SGridView(
                controller: _controller,
                crossAxisItemCount: _crossAxis,
                mainAxisDirection: _direction,
                itemPadding: const EdgeInsets.all(6),
                autoScrollToIndex: _autoIndex,
                showScrollIndicators: _showScrollIndicators,
                indicatorColor: _indicatorColor,
                indicatorScrollFraction: _scrollFraction,
                children: items,
              ),
            ),
          ),
        ],
      ),
    );
  }
}
0
likes
160
points
14
downloads

Publisher

unverified uploader

Weekly Downloads

A lightweight, customizable grid-like Flutter widget with index-based scrolling and tappable scroll indicators

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

assorted_layout_widgets, flutter, indexscroll_listview_builder, soundsliced_dart_extensions

More

Packages that depend on s_gridview