caduandrade / tabbed_view

Widget inspired by the classic Desktop-style tab component.
MIT License
51 stars 16 forks source link

TabbedView + StreamBuilder = no rebuild until switch to another tab and back #24

Closed rho-cassiopeiae closed 1 year ago

rho-cassiopeiae commented 1 year ago

I want to have one tab's content to be dynamic using StreamBuilder, but when a new event is emitted the tab's content doesn't change until I switch to another tab and back. Tried wrapping TabbedView (which uses contentBuilder) with StreamBuilder and also tried wrapping only an individual tab widget with StreamBuilder, but the result is the same.

caduandrade commented 1 year ago

Hi @rho-cassiopeiae! Sorry for the delay, I'm working on other packages as well.

Did you use the controller to change the tab content?

    getRandomStrings().listen((value) {
      _controller.tabs[1].content = Text(value);
      print(value);
    });

When changing the tab content, the controller will notify and rebuild the tab automatically.

Using the example:

import 'dart:math';

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

void main() {
  runApp(TabbedViewExample());
}

class TabbedViewExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false, home: TabbedViewExamplePage());
  }
}

class TabbedViewExamplePage extends StatefulWidget {
  @override
  _TabbedViewExamplePageState createState() => _TabbedViewExamplePageState();
}

class _TabbedViewExamplePageState extends State<TabbedViewExamplePage> {
  late TabbedViewController _controller;

  Stream<String> getRandomStrings() async* {
    var random = Random();
    while (true) {
      await Future.delayed(Duration(seconds: 5));
      yield random.nextInt(999999999).toRadixString(16);
    }
  }

  @override
  void initState() {
    super.initState();
    List<TabData> tabs = [];

    tabs.add(TabData(
        text: 'Tab 1',
        leading: (context, status) => Icon(Icons.star, size: 16),
        content: Padding(child: Text('Hello'), padding: EdgeInsets.all(8))));
    tabs.add(TabData(
        text: 'Tab 2',
        content:
            Padding(child: Text('Hello again'), padding: EdgeInsets.all(8))));
    tabs.add(TabData(
        closable: false,
        text: 'TextField',
        content: Padding(
            child: TextField(
                decoration: InputDecoration(
                    isDense: true, border: OutlineInputBorder())),
            padding: EdgeInsets.all(8)),
        keepAlive: true));

    _controller = TabbedViewController(tabs);
    // updating the content tab
    getRandomStrings().listen((value) {
      _controller.tabs[1].content = Text(value);
      print(value);
    });
  }

  @override
  Widget build(BuildContext context) {
    TabbedView tabbedView = TabbedView(controller: _controller);
    Widget w =
        TabbedViewTheme(child: tabbedView, data: TabbedViewThemeData.mobile());
    return Scaffold(body: Container(child: w, padding: EdgeInsets.all(32)));
  }
}
rho-cassiopeiae commented 1 year ago

Oh, get it now, thanks. Although, I think it's not very intuitive.