热门在选项卡更改时刷新appBar的操作吗?

时间:2019-11-10 17:12:45

标签: flutter dart

我正在寻找一种方法,当按下tabBar中的特定选项卡时,可以隐藏/更改appBar动作。

调用 import UIKit import CoreBluetooth protocol BLEScanDelegate { func reloadDeviceList() } internal class BLEScanManager: NSObject { private var centralManager: CBCentralManager? var devices : [Bluetooth] = [] var delegate: BLEScanDelegate? let centralManagerDelegate = MyCentralManagerDelegateImplementation() override init() { super.init() centralManagerDelegate.delegate = self centralManager = CBCentralManager(delegate: centralManagerDelegate, queue: .main) } // MARK:- Custom methods func isScanning() -> Bool { return centralManager?.isScanning ?? false } func stopScanning() { centralManager?.stopScan() } func startScanning() { devices.removeAll() let options: [String: Any] = [CBCentralManagerScanOptionAllowDuplicatesKey: NSNumber(value: false)] centralManager?.scanForPeripherals(withServices: nil, options: options) } } private extension BLEScanManager: CentralManagerEventsDelegate { func didUpdateState(){ // Here goes the switch with the startScanning } func didDiscoverPeripheral(...) { // Here goes the logic on new peripheral and the call on self.delegate?.reloadDeviceList } } internal protocol CentralManagerEventsDelegate: class { func didUpdateState() func didDiscoverPeripheral(...) } internal class MyCentralManagerDelegateImplementation: NSObject, CBCentralManagerDelegate { weak var delegate: CentralManagerEventsDelegate? func centralManagerDidUpdateState(_ central: CBCentralManager) { self.delegate?.didUpdateState() } func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { self.delegate?.didDiscoverPeripheral(actualParams) } } 方法会重绘整个小部件以及所有TabController子级/屏幕,这确实很糟糕。

下面是我的代码:

setState(() { })

我们如何重绘enum SelectedTab { items, sales, raw_items, orders } class _MyHomePageState extends State<MyHomePage> { Widget rightActionButton(BuildContext context) { //This is the widget which is expected to be update upon tab change SelectedTab currentTab = Globals.instance.selectedTab; return Visibility ( child: . . . visible: currentTab != SelectedTab.sales, ); } Widget navBar(BuildContext context) { return AppBar( title: Text('Example'), actions: <Widget>[ rightActionButton(context), ], ); } Widget tabBar(BuildContext context) { return Container( child: TabBar( tabs: [ . . . . ], onTap: (index) { Globals.instance.selectedTab = SelectedTab.values[index]; //Refresh rightActionButton }, ), ); } Widget tabScreens(BuildContext context) { return TabBarView( children: [ . . . . ], ); } @override Widget build(BuildContext context) { return DefaultTabController( length: 4, child: Scaffold ( appBar: navBar(context), bottomSheet: tabBar(context), body: tabScreens(context), ), ); } } 而不是重绘支架中的所有小部件?

2 个答案:

答案 0 :(得分:1)

在Flutter中,当您调用setState()时,它将自动跟踪哪些窗口小部件取决于setState()函数中已更改的数据,并重建树中已更改的部分,而不是整个窗口小部件。

因此,不必担心会重新绘制小部件树,Flutter团队会处理这些问题。

答案 1 :(得分:1)

回答我自己的问题:

事实是我们需要在StatefulWidget上调用setState((){})以便重绘。因此,我只是将代码从Widget rightActionButton()移到了StatefulWidget的单独的类扩展中。

class ActionButton extends StatefulWidget
{
  final ActionButtonState abs = ActionButtonState();
  void refresh() {
    abs.refresh();
  }
  @override
  ActionButtonState createState() =>  abs;
}

class  ActionButtonState extends State<ActionButton>
{ 
  void refresh() { 
    setState(() {}); 
  }

  @override
  Widget build(BuildContext context)
  {
    SelectedTab currentTab = Globals.instance.selectedTab;

    return Visibility ( ... )
  }
}

然后我们可以在使用了ActionButton实例的任何地方调用它的refresh()方法。喜欢:

class _MyHomePageState extends State<MyHomePage>
{
  ActionButton actionButton1 = new ActionButton();

  Widget navBar(BuildContext context)
  {
    return AppBar(
      title: Text('Example'),
      actions: <Widget>[
        actionButton1,
      ],
    );
  }

  Widget tabBar(BuildContext context)
  {
    return Container(
      child: TabBar(
        tabs: [ 
          . . . .
        ],
        onTap: (index) {
          Globals.instance.selectedTab = SelectedTab.values[index];
          actionButton1.refresh();
        },
      ),
    );
  }
  .
  .
}