marqueer 2.1.0 copy "marqueer: ^2.1.0" to clipboard
marqueer: ^2.1.0 copied to clipboard

A powerful and customizable Flutter widget that transforms any widget into a smooth scrolling marquee with support for multiple directions, user interactions, and programmatic control. Perfect for dis [...]

example/main.dart

import 'dart:math';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:marqueer/marqueer.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Marqueer Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: ExampleScreen(),
    );
  }
}

class ExampleScreen extends StatelessWidget {
  ExampleScreen({super.key});

  final controller = MarqueerController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: ListView(
        padding: EdgeInsets.zero,
        children: [
          Row(
            children: [
              TextButton.icon(
                onPressed: controller.backward,
                label: const Text('Backward'),
                icon: const Icon(Icons.chevron_left),
              ),
              const Spacer(),
              TextButton.icon(
                onPressed: controller.forward,
                label: const Text('Forward'),
                icon: const Icon(Icons.chevron_right),
              ),
            ],
          ),
          _PostCard(controller: controller),
          SizedBox(
            height: 100,
            child: Marqueer.builder(
              pps: 60,
              scrollablePointerIgnoring: true,
              controller: controller,
              itemBuilder: (context, index) {
                ///
                ///
                return GestureDetector(
                  behavior: HitTestBehavior.opaque,
                  onTap: () {
                    print('Tap');
                  },
                  child: Image.network(
                    'https://picsum.photos/300/300?random=$index',
                    width: 100,
                  ),
                );
              },
            ),
          ),
          const ExchangeBar(),
          SizedBox(
            height: 300,
            child: Marqueer.builder(
              pps: 30,
              controller: controller,
              direction: MarqueerDirection.ltr,
              autoStartAfter: const Duration(seconds: 2),
              itemCount: 10,
              itemBuilder: (context, index) {
                return Image.network(
                  'https://picsum.photos/300/300?random=$index',
                  height: 300,
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

class _PostCard extends StatelessWidget {
  const _PostCard({this.controller});
  final MarqueerController? controller;

  @override
  Widget build(BuildContext context) {
    final mediaQuery = MediaQuery.of(context);
    final size = (mediaQuery.size.width * mediaQuery.devicePixelRatio).toInt();
    final id = Random().nextInt(1000);

    return Stack(
      children: [
        AspectRatio(
          aspectRatio: 1,
          child: Marqueer(
            controller: controller,
            direction: MarqueerDirection.btt,
            child: AspectRatio(
              aspectRatio: 1,
              child: Image.network(
                'https://picsum.photos/$size/$size?random=$id',
                fit: BoxFit.cover,
              ),
            ),
          ),
        ),
        Positioned(
          height: 42,
          bottom: 8,
          left: 0,
          right: 0,
          child: ClipRRect(
            child: BackdropFilter(
              filter: ImageFilter.blur(sigmaX: 12, sigmaY: 12),
              child: ColoredBox(
                color: const Color(0x66000000),
                child: Marqueer(
                  autoStartAfter: const Duration(seconds: 3),
                  child: const Padding(
                    padding: EdgeInsets.all(12),
                    child: Text(
                      'Curabitur nec ex auctor risus scelerisque rhoncus ut porttitor sapien. Pellentesque vestibulum leo a nisi sollicitudin vehicula. Ut fringilla elementum iaculis. Sed risus justo, facilisis at metus sed, interdum euismod lectus. Vivamus tincidunt lorem vel mauris hendrerit, a efficitur felis porttitor. Nulla facilisi.',
                      style: TextStyle(
                        color: Colors.white,
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
      ],
    );
  }
}

class ExchangeBar extends StatelessWidget {
  const ExchangeBar({super.key});
  static const data = <Map<String, dynamic>>[
    {
      'id': 'xu100_index',
      'direction': -1,
      'value': '5.212,38',
      'change_percent': '%-0.93',
      'title': 'BIST 100',
      'currency': '',
    },
    {
      'id': 'usdtry_curncy',
      'direction': -1,
      'value': '18,7993',
      'change_percent': '%-0.32',
      'title': 'Dolar',
      'currency': '₺',
    },
    {
      'id': 'eurtry_curncy',
      'direction': 1,
      'value': '20,0293',
      'change_percent': '%0.24',
      'title': 'Euro',
      'currency': '₺',
    },
    {
      'id': 'eurusd_curncy',
      'direction': 1,
      'value': '1,0636',
      'change_percent': '%0.33',
      'title': 'EUR/USD',
      'currency': r'$',
    },
    {
      'id': 'tahvil2y',
      'direction': -1,
      'value': '10,49',
      'change_percent': '%-1.32',
      'title': 'Faiz',
      'currency': '',
    },
    {
      'id': 'xau_curncy',
      'direction': 1,
      'value': '1.856,48',
      'change_percent': '%1.12',
      'title': 'Altın Ons',
      'currency': r'$',
    },
    {
      'id': 'co1_comdty',
      'direction': 1,
      'value': '85,83',
      'change_percent': '%1.27',
      'title': 'Brent Petrol',
      'currency': r'$',
    },
    {
      'id': 'bdiy_index',
      'direction': 1,
      'value': '1.211,00',
      'change_percent': '%5.76',
      'title': 'Baltık Kuru Yük.',
      'currency': r'$',
    },
    {
      'id': 'btcusdt',
      'title': 'Bitcoin',
      'value': '22,430.00',
      'change_percent': '%0.46',
      'direction': 1,
      'currency': r'$',
    },
    {
      'id': 'ethusdt',
      'title': 'Ethereum',
      'value': '1,570.10',
      'change_percent': '%0.4',
      'direction': 1,
      'currency': r'$',
    },
    {
      'id': 'gldgr',
      'title': 'Altın Gram',
      'value': '1,127.08',
      'change_percent': '%1.01',
      'direction': 1,
      'currency': '₺',
    },
  ];

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 60,
      child: Marqueer.builder(
        separatorBuilder: (_, index) => const Center(
          child: Text('      ~     '),
        ),
        itemBuilder: (context, index) {
          final multiplier = index ~/ data.length;

          var i = index;

          if (multiplier > 0) {
            i = index - (multiplier * data.length);
          }

          final item = data[i];

          final color = switch (item['direction']) {
            1 => Colors.green,
            -1 => Colors.red,
            _ => Colors.grey,
          };

          return Padding(
            padding: const EdgeInsets.symmetric(horizontal: 20),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  "${item['title']}",
                  style: const TextStyle(
                    fontWeight: FontWeight.w600,
                  ),
                ),
                Text(
                  "${item['value']} ${item['currency']}",
                  style: TextStyle(
                    fontSize: 12,
                    color: color,
                  ),
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}
76
likes
140
points
4.65k
downloads

Publisher

verified publishergece.dev

Weekly Downloads

A powerful and customizable Flutter widget that transforms any widget into a smooth scrolling marquee with support for multiple directions, user interactions, and programmatic control. Perfect for displaying scrolling text, images, or any content with configurable speed, direction, and interaction behavior.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on marqueer