flutter 如何通过编程方式更改main.dart AppBar子控件的标题?

6vl6ewon  于 2022-12-14  发布在  Flutter
关注(0)|答案(5)|浏览(172)

我在main.dart中有一个AppBar,我想在它的子页面上将它定义为主要的,但是我想在子页面上更改AppBar本身的标题,我如何正确地做到这一点?

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

class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter App",
      theme: ThemeData(
        primaryColor: Colors.cyan,
        brightness: Brightness.dark
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text("Main Dart"),
        ),
        body: HomeScreen(),
      ),
      routes: <String, WidgetBuilder>{
        '/homeScreen': (buildContext)=>HomeScreen(),
        '/second': (buildContext)=>Second() 
      },
    );
  }
}

//HomeScreen or Second Widget on different dart file

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //here I want to change the title of Main Dart to HomeScreen
    return Container(
      child: Center(
        child: FlatButton(
          child: new Text("Home screen"),
          onPressed: (){
            Route route = MaterialPageRoute(builder: (context) => Second());
            Navigator.push(context, route);
          },
        ),
      ),
    );
  }
}

或者我需要在每个屏幕中放置Scaffold(appBar:AppBar(...), ...)?这是最好的方法?

qzwqbdag

qzwqbdag1#

app_properties_bloc.dart中具有应用程序属性的BLoC

final appBloc = AppPropertiesBloc();

class AppPropertiesBloc{
  StreamController<String> _title = StreamController<String>();

  Stream<String> get titleStream => _title.stream;

  updateTitle(String newTitle){
    _title.sink.add(newTitle);
  }

  dispose() {
    _title.close();
  }
}

在AppBar中使用流构建器,如下所示:

AppBar(
   title: StreamBuilder<Object>(
       stream: appBloc.titleStream,
       initialData: "Main Dart",
       builder: (context, snapshot) {
           return Text(snapshot.data);
       }
   ),
),

使用此项更新按钮onPressed()的标题

onPressed: () {
    appBloc.updateTitle('new title');
},
nmpmafwu

nmpmafwu2#

如果你只是改变了支架的标题,那么这将是工作。
我正在创建一个DefaultScaffold,每个屏幕都提供了标题。这里的代码将显示MainPage和另外两个页面,它们具有相同的AppBar,但标题发生了变化。

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(initialRoute: 'home', routes: <String, WidgetBuilder>{
      'home': (context) => SOMain(),
      '/secondPage': (context) => DefaultScaffold("Second Screen", SOSecond()),
      '/thirdPage': (context) => DefaultScaffold("Third Screen", SOThird()),
    });
  }
}

class DefaultScaffold extends StatelessWidget {
  String title;
  Widget body;

  DefaultScaffold(this.title, this.body);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: body,
    );
  }
}

class SOMain extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultScaffold(
      "Main Screen",
      Center(
        child: RaisedButton(
            child: Text("Go to second screen"),
            onPressed: () {
              Navigator.pushNamed(context, '/secondPage');
            }),
      ),
    );
  }
}

class SOSecond extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: RaisedButton(
        child: Text("Go the 3rd screen"),
        onPressed: () => Navigator.pushNamed(context, "/thirdPage"),
      ),
    );
  }
}

class SOThird extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(child: Text("You are on last screen"));
  }
}

注意:这是一个简单的解决方法,可能不是最好的方法。

eivgtgni

eivgtgni3#

您可以使用回呼函式,从child更新parent的状态。
父类:

import 'package:flutter/material.dart';

class Parent extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return ParentState();
  }
}

class ParentState extends State<Parent> {

  String title = "Old Title";

  @override
  Widget build(BuildContext context) {

    return new Scaffold(
        appBar: new AppBar(
        title: new Text(title),
      ),
      body: DaysFragmentView(onTitleSelect: (String value) {
            setTitle(value);
        }
      ),
    );

  }

  void setTitle(String value) {
    setState(() {
      title = value;
    });
  }
}

子类别

typedef TitleCallback = void Function(Title color);

class DaysFragmentView extends StatelessWidget {
  const DaysFragmentView({this.onTitleSelect});

  final TitleCallback onTitleSelect;

  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        RaisedButton(
          child: Text('One'),
          onPressed: () {
            onTitleSelect("TITLE ONE");
          },
        ),
        RaisedButton(
          child: Text('Two'),
          onPressed: () {
            onTitleSelect("TITLE TWO");
          },
        )
      ],
    );
  }
}

参考编号:

mrwjdhj3

mrwjdhj34#

可以选择使用ValueListenableBuilder。
使用示例变量

String appTitle;

然后按以下块中所示设置应用栏:

appBar: AppBar(
          ValueListenableBuilder<String>(
          valueListenable: appTitle,
          builder: (context, value, child) {
            return Text(appTitle.value);
          },
        ),

之后,你可以简单地在另一个类中设置appTitle.value。标题也会被改变,因为它会监听那个值。

appTitle.value = "Home Screen";
iyfamqjs

iyfamqjs5#

这里的一些答案太复杂了。这里是一个完整的工作示例使用应用程序栏更新从儿童与scafold小部件。
你可以在 dart 垫run the example

import 'package:flutter/material.dart';

void main() {
  runApp(const MyHomePage(title: 'init title'));
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final ValueNotifier<String?> _appBarTitleNotifier = ValueNotifier<String?>(null);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: ValueListenableBuilder<String?>(
            builder: (BuildContext context, String? value, Widget? child) {
              return Text(value ?? widget.title);
            },
            valueListenable: _appBarTitleNotifier,
          ),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              ChildDemoTitleBar(titleNotifier: _appBarTitleNotifier)
            ],
          ),
        ),
      ),
    );
  }
}

class ChildDemoTitleBar extends StatefulWidget {
  final ValueNotifier<String?> titleNotifier;

  const ChildDemoTitleBar({Key? key, required this.titleNotifier})
      : super(key: key);

  @override
  State<ChildDemoTitleBar> createState() => _ChildDemoTitleBarState();
}

class _ChildDemoTitleBarState extends State<ChildDemoTitleBar> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return Padding(
        padding: const EdgeInsets.fromLTRB(20, 0, 20, 20),
        child: InkWell(
            onTap: () {
              _counter++;
              widget.titleNotifier.value = "title updated $_counter";
            },
            child: const Text("tap to update title")));
  }
}

相关问题