updatable_ticker 1.0.6 copy "updatable_ticker: ^1.0.6" to clipboard
updatable_ticker: ^1.0.6 copied to clipboard

A flutter widget for a smooth scrolling text ticker which integrates text updates cleanly so that scrolling is glitch-free and uninterrupted.

example/lib/main.dart

import 'dart:async';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:ipsum/ipsum.dart';
import 'package:updatable_ticker/updatable_ticker.dart';

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

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

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

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

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final LinearGradient gradient = LinearGradient(
    colors: <Color>[Color.fromARGB(0, 0, 0, 0), Color.fromARGB(255, 0, 0, 0)],
    begin: Alignment.topLeft,
    end: Alignment.bottomRight,
  );
  final Duration oneSec = Duration(milliseconds: 500);
  final double minDesktopWidth = 768;
  final double linePadding = 20;
  final double gradientWidthInPx = 80;
  final double borderSpace = 64;
  final int fontMinSize = 12;
  final int fontMaxSize = 80;
  final int maxLines = 4;

  Orientation orientation = Orientation.portrait;
  DateTime lastUpdate = DateTime.now();
  String updatableText = '';
  double width = 1280;
  double height = 768;
  double gradientWidth = 0;
  double scrollSpeedDevice = 1.0;
  double fontSize = 12.0;
  int rng = -1;
  int seconds = 0;
  bool withGradient = false;

  @override
  void initState() {
    super.initState();

    randomUpdates();

    Timer.periodic(
      oneSec,
      (Timer t) => setState(() {
        final int value =
            rng - DateTime.now().difference(lastUpdate).inSeconds - 1;
        seconds = value > 0 ? value : 0;
      }),
    );
  }

  int random(int min, int max) {
    return min + Random().nextInt(max - min);
  }

  String textGenerator() {
    final int rng = random(5, 20);
    return Ipsum().words(rng);
  }

  randomUpdates() {
    rng = rng == -1 ? 2 : random(4, 60);

    Future.delayed(Duration(seconds: rng), () {
      SchedulerBinding.instance.addPostFrameCallback((_) async {
        if (mounted) {
          setState(() {
            lastUpdate = DateTime.now();
            updatableText = textGenerator();
          });
        }
      });

      randomUpdates();
    });
  }

  List<Widget> sliders() => [
        Row(
          children: [
            SizedBox(
                width: width > minDesktopWidth ? null : 64.0,
                child: Text('Speed: ')),
            SizedBox(
              width: 170,
              child: Slider(
                value: scrollSpeedDevice,
                min: 0.75,
                max: 10,
                divisions: 100,
                thumbColor: Colors.red.shade700,
                activeColor: Colors.green.shade200,
                inactiveColor: Colors.grey.shade700,
                onChanged: (double value) {
                  setState(() {
                    scrollSpeedDevice = value;
                  });
                },
              ),
            ),
            Text('${(50 * scrollSpeedDevice).floor()} px/s'),
          ],
        ),
        if (width > minDesktopWidth) Expanded(child: SizedBox()),
        Row(
          children: [
            SizedBox(width: 64.0, child: Text('Fontsize: ')),
            SizedBox(
              width: 170,
              child: Slider(
                value: fontSize,
                min: fontMinSize.toDouble(),
                max: fontMaxSize.toDouble(),
                divisions: fontMaxSize - fontMinSize,
                thumbColor: Colors.red.shade700,
                activeColor: Colors.green.shade200,
                inactiveColor: Colors.grey.shade700,
                onChanged: (double value) {
                  setState(() {
                    fontSize = value;
                  });
                },
              ),
            ),
            Text('$fontSize px'),
          ],
        ),
      ];

  @override
  Widget build(BuildContext context) {
    width = MediaQuery.of(context).size.width;
    height = MediaQuery.of(context).size.height;
    gradientWidth =
        width > 0 ? 1 / (width - borderSpace) * gradientWidthInPx : 0;

    return MaterialApp(
      title: 'Updatable Ticker',
      themeMode: ThemeMode.system,
      home: Material(
        child: SafeArea(
          child: Center(
            child: SizedBox(
              width: MediaQuery.of(context).size.width - 64,
              child: OrientationBuilder(
                  builder: (BuildContext context, Orientation o) {
                orientation = o;

                return NotificationListener<SizeChangedLayoutNotification>(
                  onNotification: (notification) {
                    width = MediaQuery.of(context).size.width;
                    height = MediaQuery.of(context).size.height;
                    build(context);
                    return false;
                  },
                  child: SizeChangedLayoutNotifier(
                    child: Container(
                      padding: EdgeInsets.only(top: 16.0),
                      key: ValueKey(
                        'UpdatableTickerWrapper-${orientation == Orientation.portrait ? 'portrait' : 'landscape'}-$width',
                      ),
                      width: width - 16,
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Wrap(
                            crossAxisAlignment: WrapCrossAlignment.center,
                            children: [
                              SizedBox(
                                width: 150.0,
                                child: Row(
                                  children: [
                                    Text(
                                      'width: ',
                                      style: TextStyle(
                                          fontWeight: FontWeight.bold),
                                    ),
                                    Text('${width - 16}'),
                                  ],
                                ),
                              ),
                              SizedBox(
                                width: 220.0,
                                child: Row(
                                  mainAxisSize: MainAxisSize.min,
                                  children: [
                                    Text(
                                      'orientation: ',
                                      style: TextStyle(
                                          fontWeight: FontWeight.bold),
                                    ),
                                    Text(orientation.name),
                                  ],
                                ),
                              ),
                              Row(
                                mainAxisSize: MainAxisSize.min,
                                children: [
                                  Checkbox(
                                    value: withGradient,
                                    onChanged: (bool? mode) {
                                      setState(() {
                                        withGradient = !withGradient;
                                      });
                                    },
                                  ),
                                  Text('with opacity fading'),
                                ],
                              ),
                            ],
                          ),
                          Padding(
                            padding: EdgeInsets.only(top: linePadding),
                            child: SizedBox(
                              height: maxLines * 20,
                              child: Row(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: [
                                  Text(
                                    'new text: ',
                                    style:
                                        TextStyle(fontWeight: FontWeight.bold),
                                  ),
                                  Flexible(
                                    child: Text(
                                      updatableText,
                                      maxLines: maxLines,
                                      overflow: TextOverflow.ellipsis,
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                          Padding(
                            padding: EdgeInsets.only(top: linePadding),
                            child: Row(
                              children: [
                                Text(
                                  'next update: ',
                                  style: TextStyle(fontWeight: FontWeight.bold),
                                ),
                                Text('in $seconds seconds'),
                              ],
                            ),
                          ),
                          Padding(
                            padding: EdgeInsets.only(top: linePadding),
                            child: width > minDesktopWidth
                                ? Row(
                                    children: sliders(),
                                  )
                                : SizedBox(
                                    height: 100.0,
                                    child: SizedBox(
                                      height: 100.0,
                                      child: Column(
                                        crossAxisAlignment:
                                            CrossAxisAlignment.start,
                                        children: sliders(),
                                      ),
                                    ),
                                  ),
                          ),
                          if (width > minDesktopWidth)
                            Expanded(
                              child: SizedBox(),
                            ),
                          Padding(
                            padding: const EdgeInsets.only(bottom: 8.0),
                            child: Stack(
                              children: [
                                SizedBox(
                                  height: (fontMaxSize * 1.2).toDouble(),
                                  child: UpdatableTicker(
                                    key: ValueKey(
                                      'UpdatableTickerExamplePage-${orientation == Orientation.portrait ? 'portrait' : 'landscape'}-$width-$fontSize',
                                    ),
                                    updatableText: updatableText,
                                    style: TextStyle(
                                      fontFamily: 'whiteCupertino subtitle',
                                      fontSize: fontSize,
                                      color: Colors.black,
                                    ),
                                    pixelsPerSecond: 50 * scrollSpeedDevice,
                                    forceUpdate: false,
                                    separator: '    ////    ',
                                  ),
                                ),
                                withGradient
                                    ? Container(
                                        height: (fontMaxSize * 1.2).toDouble(),
                                        decoration: BoxDecoration(
                                          gradient: LinearGradient(
                                              colors: [
                                                Theme.of(context)
                                                    .scaffoldBackgroundColor,
                                                Theme.of(context)
                                                    .scaffoldBackgroundColor
                                                    .withValues(alpha: 0.0),
                                                Theme.of(context)
                                                    .scaffoldBackgroundColor
                                                    .withValues(alpha: 0.0),
                                                Theme.of(context)
                                                    .scaffoldBackgroundColor,
                                              ],
                                              begin: Alignment.centerLeft,
                                              end: Alignment.centerRight,
                                              stops: [
                                                0.0,
                                                gradientWidth,
                                                1 - gradientWidth,
                                                1.0
                                              ]),
                                        ),
                                      )
                                    : SizedBox(),
                              ],
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                );
              }),
            ),
          ),
        ),
      ),
    );
  }
}
1
likes
160
points
111
downloads

Publisher

verified publisherwilhelm-devblog.de

Weekly Downloads

A flutter widget for a smooth scrolling text ticker which integrates text updates cleanly so that scrolling is glitch-free and uninterrupted.

Repository (GitHub)
View/report issues

Topics

#animation #text #ticker #ui

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on updatable_ticker