Flow text...

rO_Or·2024년 6월 17일

Dart 그리고 Flutter

목록 보기
16/19

import 'package:flutter/material.dart';

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

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Marquee Text Example'),
        ),
        body: const Center(
          child: SizedBox(
            width: 250,
            child: MarqueeText(
              text: '짧은 글입니다. 짧은 글입니다. 짧은 글입니다. 짧은 글입니다.',
            ),
          ),
        ),
      ),
    );
  }
}

class MarqueeText extends StatefulWidget {
  final String text;
  final TextStyle style;
  final Duration duration;

  const MarqueeText({
    super.key,
    required this.text,
    this.style = const TextStyle(fontSize: 24),
    this.duration = const Duration(seconds: 5),
  });

  
  _MarqueeTextState createState() => _MarqueeTextState();
}

class _MarqueeTextState extends State<MarqueeText>
    with SingleTickerProviderStateMixin {
  late final ScrollController _scrollController;
  late final AnimationController _animationController;
  late final Animation<double> _animation;

  
  void initState() {
    super.initState();
    _scrollController = ScrollController();
    _animationController = AnimationController(
      vsync: this,
      duration: Duration(
        milliseconds: widget.text.length * 150,
      ),
    );
    _animation = Tween<double>(begin: 0, end: 1).animate(_animationController)
      ..addListener(() {
        if (_scrollController.hasClients) {
          _scrollController.jumpTo(
              _scrollController.position.maxScrollExtent * _animation.value);
        }
      })
      ..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          _animationController.repeat(
            reverse: true,
          );
        }
      });

    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (_scrollController.hasClients) {
        _animationController.forward();
      }
    });
  }

  
  void dispose() {
    _animationController.dispose();
    _scrollController.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return ShaderMask(
      shaderCallback: (Rect bounds) {
        return const LinearGradient(
          begin: Alignment.centerLeft,
          end: Alignment.centerRight,
          colors: [
            Colors.transparent,
            Colors.black,
            Colors.black,
            Colors.transparent
          ],
          stops: [0.0, 0.05, 0.95, 1.0],
        ).createShader(bounds);
      },
      blendMode: BlendMode.dstIn,
      child: SingleChildScrollView(
        controller: _scrollController,
        scrollDirection: Axis.horizontal,
        child: Text(
          widget.text,
          style: widget.style,
        ),
      ),
    );
  }
}
profile
즐거워지고 싶다.

0개의 댓글