我正在寻找一种方法,当按下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),
),
);
}
}
而不是重绘支架中的所有小部件?
答案 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();
},
),
);
}
.
.
}