Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How change the bottom-bar-index on page change? #6

Closed
LiveLikeCounter opened this issue Mar 13, 2019 · 5 comments
Closed

How change the bottom-bar-index on page change? #6

LiveLikeCounter opened this issue Mar 13, 2019 · 5 comments
Labels
enhancement New feature or request

Comments

@LiveLikeCounter
Copy link

Great job, looks great!

I just tried the CurvedNavigationBar. I stuck with one question/problem: I use Pageview to show the content. When you swipe to another page, I want to change the selected bottombar also, but there is only a initialIndex. How can I change the selected bottombaritem afterwards?

@rafalbednarczuk
Copy link
Owner

thanks,
In order to do this it's necessary to add some kind of ScrollController to widget.
It's important feature

@rafalbednarczuk rafalbednarczuk added the enhancement New feature or request label Mar 15, 2019
@rafalbednarczuk
Copy link
Owner

fixed in
a55b819

@stargazing-dino
Copy link

stargazing-dino commented Apr 26, 2019

Hi, sorry, dumb question but is this how one would make it swipable? I mean, the bottom bar successfully changes index if someone swipes but it also seems like it significantly lags behind the swipe action. Not sure if it's just the emulator though or I'm messing up with the addListener or something else.

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

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

class _HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  final List<Widget> _tabs = <Widget>[
    /* tabs */
  ];

  TabController _controller;
  int _currentIndex = 0;

  @override
  void initState() {
    super.initState();
    _controller = TabController(
      vsync: this,
      length: _tabs.length,
      initialIndex: 0,
    );
    _controller.addListener(() {
      setState(() {
        _currentIndex = _controller.index;
      });
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBody: true,
      body: TabBarView(
          controller: _controller,
          children: _tabs.map<Widget>((Widget tab) {
            return SafeArea(
              top: false,
              bottom: false,
              child: Container(
                key: ObjectKey(tab),
                child: tab,
              ),
            );
          }).toList()),
      bottomNavigationBar: CurvedNavigationBar(
        index: _currentIndex,
        items: <Widget>[
          /* icons */
        ],
        backgroundColor: Colors.transparent,
        animationCurve: Curves.easeInOut,
        animationDuration: Duration(milliseconds: 600),
        onTap: (index) {
          _controller.animateTo(index);
        },
      ),
    );
  }
}

@rafalbednarczuk
Copy link
Owner

It should work with _controller.jumpTo(index) instead of _controller.animateTo(index), but you won't get animation effect

@stargazing-dino
Copy link

stargazing-dino commented Apr 30, 2019

I really like that animation though.

I've done a lot of searching and it doesn't look like there's a any advice on this. However, I think the tabs source code successfully does something like this. I am very new to Flutter and Dart so maybe this will make more sense to you @rafalbednarczuk but in their tabs they add some listeners like

if (_controller != null) {
  _controller.animation.addListener(_handleTabControllerAnimationTick);
  _controller.addListener(_handleTabControllerTick);
  _currentIndex = _controller.index;
}

And the listeners look like this:

void _handleTabControllerAnimationTick() {
  assert(mounted);
  if (!_controller.indexIsChanging && widget.isScrollable) {
    // Sync the TabBar's scroll position with the TabBarView's PageView.
    _currentIndex = _controller.index;
    _scrollToControllerValue();
  }
}

void _handleTabControllerTick() {
  if (_controller.index != _currentIndex) {
    _currentIndex = _controller.index;
    if (widget.isScrollable)
      _scrollToCurrentIndex();
  }
  setState(() {
    // Rebuild the tabs after a (potentially animated) index change
    // has completed.
  });
}

Maybe this isn't the whole picture but what do you make of it? I'll do some testing later too and let you know how it goes.

[Edit]
Oh, now I know why this would be difficult. You'd need to animate the bottom bar based off the controller's value as they do it in their code and not based off any one event given off by a listener (because you can't preemptively change the bottombar's index until you know for sure they've swiped to the other screen.)

void _scrollToControllerValue() {
  final double leadingPosition = _currentIndex > 0 ? _tabCenteredScrollOffset(_currentIndex - 1) : null;
  final double middlePosition = _tabCenteredScrollOffset(_currentIndex);
  final double trailingPosition = _currentIndex < maxTabIndex ? _tabCenteredScrollOffset(_currentIndex + 1) : null;

  final double index = _controller.index.toDouble();
  final double value = _controller.animation.value;
  double offset;
  if (value == index - 1.0)
    offset = leadingPosition ?? middlePosition;
  else if (value == index + 1.0)
    offset = trailingPosition ?? middlePosition;
  else if (value == index)
    offset = middlePosition;
  else if (value < index)
    offset = leadingPosition == null ? middlePosition : lerpDouble(middlePosition, leadingPosition, index - value);
  else
    offset = trailingPosition == null ? middlePosition : lerpDouble(middlePosition, trailingPosition, value - index);

  _scrollController.jumpTo(offset);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants