Flutter 跑马灯

作者: cff70524f5cf | 来源:发表于2019-04-09 21:46 被阅读17次

    本文介绍2种跑马灯效果的实现:连贯式,非连贯式。效果如下图

    marquee image

    连贯式

    实现思路:写一个无限长度的列表(ListView),通过一个定时任务(Timer)每隔一定时间滑动一定距离(ScrollController)。这里面比较tricky的是滑动距离的设置,你不能直接设置一个和时间成正比的值。因为页面可能存在息屏或者跳转到其它页面的不可见状态,此时是不希望有滑动的,就算你给他设置了滑动,系统并不会去滑动它。所以每次轮询都去获取当前列表滑动的距离(scrollController.offset),在它基础上加上一个距离作为要滚动到的位置。

    class _MarqueeContinuousState extends State<MarqueeContinuous> {
      ScrollController _controller;
      Timer _timer;
      double _offset = 0.0;
    
      @override
      void initState() {
        super.initState();
        _controller = ScrollController(initialScrollOffset: _offset);
        _timer = Timer.periodic(widget.duration, (timer) {
          double newOffset = _controller.offset + widget.stepOffset;
          if (newOffset != _offset) {
            _offset = newOffset;
            _controller.animateTo(_offset,
                duration: widget.duration, curve: Curves.linear);
          }
        });
      }
    
      @override
      void dispose() {
        _timer.cancel();
        _controller.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return ListView.builder(
            scrollDirection: Axis.horizontal,
            controller: _controller,
            itemBuilder: (context, index) {
              return widget.child;
            });
      }
    }
    

    非连贯式

    实现思路:通过不断播放平移动画来实现(FractionalTranslation)。这里需要注意的是,动画是全屏幕展示的,如果你要让它只在控件范围内显示,需要把它包裹在ClipRect中(ClipRect会把超出控件部分裁剪掉)。另外要使超出屏幕宽度的文字不被折叠,需要把控件包裹在SingleChildScrollView中。

    class _MarqueeSingleState extends State<MarqueeSingle> with SingleTickerProviderStateMixin {
      AnimationController _controller;
      Animation<Offset> _animation;
    
      @override
      void initState() {
        super.initState();
        _controller =
            AnimationController(vsync: this, duration: Duration(seconds: 10));
        _animation = Tween<Offset>(begin: Offset(1.0, 0.0), end: Offset(-1.0, 0.0))
            .animate(_controller);
        _animation.addListener(() {
          setState(() {});
        });
        _controller.repeat();
      }
    
      @override
      Widget build(BuildContext context) {
        return ClipRect(child: FractionalTranslation(
            translation: _animation.value,
            child: SingleChildScrollView(
                scrollDirection: Axis.horizontal, child: widget.child)));
      }
    
      @override
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
    }
    

    总结

    以上是实现跑马灯效果的2种思路,大家可以根据UI需求进行选择。在此基础上,你还可以做其它的自定义,如设置滚动的速度,滚动的方向等。 最后附上源码,以供参考。

    最后附上相关资料

    点赞+加群免费获取 Android IOC架构设计
    image.png
    Flutter .png

    加群 Android IOC架构设计领取获取往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。

    相关文章

      网友评论

        本文标题:Flutter 跑马灯

        本文链接:https://www.haomeiwen.com/subject/ywjwiqtx.html