ilikerobots/rainbow_color

[Question] Can i use the RainbowColorTween to lerp between 3+ colors?

Closed this issue · 2 comments

I have a TabController that is driving my animations. I want to be able to still lerp correctly if i have more than 2 tabs.

Example with Color Tween

_tabController = TabController(
  vsync: this,
  length: 2,
);
_backgroundAnimation = ColorTween(
  begin: Colors.pink,
  end: Colors.blue,
).animate(_tabController.animation);

Expected to lerp from Colors.pink to Colors.blue

Example with RainbowColorTween

_tabController = TabController(
  vsync: this,
  length: 3,
);
_backgroundAnimation = RainbowColorTween([
  Colors.pink,
  Colors.blue,
  Colors.orange,
]).animate(_tabController.animation);

Expected to lerp from Colors.pink to Colors.blue to Colors.orange

Is it possible to make something like this work?

There's probably a way to do it directly using a RainbowColorTween. You'd need to somehow translate the tabcontroller animation into a double tween between 0 and 1...

But here's a quick example of an alternate approach. If you find a better way, please post:

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

void main() => runApp(MyApp());

/// This is the main application widget.
class MyApp extends StatelessWidget {
  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: MyTabbedPage(),
    );
  }
}

class MyTabbedPage extends StatefulWidget {
  const MyTabbedPage({Key key}) : super(key: key);

  @override
  _MyTabbedPageState createState() => _MyTabbedPageState();
}

class _MyTabbedPageState extends State<MyTabbedPage>
    with SingleTickerProviderStateMixin {
  final List<Tab> myTabs = <Tab>[
    Tab(text: 'LEFT'),
    Tab(text: 'RIGHT'),
    Tab(text: 'UP'),
    Tab(text: 'DOWN'),
  ];

  TabController _tabController;

  Rainbow _rb;

  @override
  void initState() {
    super.initState();
    _rb = Rainbow(rangeStart: 0.0, rangeEnd: myTabs.length, spectrum: [
      Colors.pink,
      Colors.lightBlue,
      Colors.lightGreen,
      Colors.yellow,
    ]);

    _tabController = TabController(vsync: this, length: myTabs.length);

    _tabController.animation.addListener(() {
      setState(() {});
    });
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: _rb[_tabController.animation.value],
        bottom: TabBar(
          controller: _tabController,
          tabs: myTabs,
        ),
      ),
      body: TabBarView(
        controller: _tabController,
        children: myTabs.map((Tab tab) {
          final String label = tab.text.toLowerCase();
          return Center(
            child: Text(
              'This is the $label tab',
              style: const TextStyle(fontSize: 36),
            ),
          );
        }).toList(),
      ),
    );
  }
}

This works, but I had to do

rangeEnd: myTabs.length -1