1. 程式人生 > 其它 >Flutter常用元件總結-頁面導航跳轉時資料的傳遞和返回

Flutter常用元件總結-頁面導航跳轉時資料的傳遞和返回

技術標籤:Flutter

一、頁面導航跳轉時資料的傳遞

通過構造方法傳遞頁面跳轉需要的資料:

import 'package:flutter/material.dart';

//傳遞的資料結構,也可以理解為對商品資料的抽象
class Product{
  final String title;  //商品標題
  final String description;  //商品描述
  Product(this.title,this.description);
}

void main(){
  runApp(MaterialApp(
      title:'資料傳遞案例',
      home:ProductList(products:List.generate(20, (i)=>Product('商品 $i','這是一個商品詳情,編號為:$i')),
      )
  ));
}

class ProductList extends StatelessWidget{
  final List<Product> products;
  ProductList({Key key,@required this.products}):super(key:key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title:Text('商品列表')),
        body:ListView.builder(
          itemCount:products.length,
          itemBuilder: (context,index){
            return ListTile(
                title:Text(products[index].title),
                onTap:(){
                  Navigator.push(context, 
                      //push跳轉頁面時,通過構造方法傳遞資料
                      MaterialPageRoute(builder:(context)=>new ProductDetail(product:products[index]))
                  );
                }
            );
          },
        )
    );
  }
}

class ProductDetail extends StatelessWidget {
  final Product product;
  ProductDetail({Key key ,@required this.product}):super(key:key);


  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: AppBar(
          title:Text('${product.title}'),
        ),
        body:Center(child: Text('${product.description}'),)
    );
  }
}

執行效果圖,點選第6個商品item項:

二、頁面資料的返回

這裡先熟悉下Flutter的Toast元件SnackBar,它和Android的Toast元件很像,下面原始碼:

/// A lightweight message with an optional action which briefly displays at the
/// bottom of the screen.
/// 帶有可選操作的輕量級訊息,可在螢幕底部短暫顯示。 
///
/// To display a snack bar, call `Scaffold.of(context).showSnackBar()`, passing
/// an instance of [SnackBar] that describes the message.
/// 通過描述訊息的[SnackBar]例項(Scaffold.of(context)獲取到的)。呼叫Scaffold.of(context).showSnackBar()顯示snack bar
/// To control how long the [SnackBar] remains visible, specify a [duration].
/// 控制snack bar的顯示時間
/// A SnackBar with an action will not time out when TalkBack or VoiceOver are
/// enabled. This is controlled by [AccessibilityFeatures.accessibleNavigation].
///
/// See also:
///
///  * [Scaffold.of], to obtain the current [ScaffoldState], which manages the
///    display and animation of snack bars.
///    [Scaffold.of] 獲取當前的[ScaffoldState],管理snack bars的顯示和動畫.
///  * [ScaffoldState.showSnackBar], which displays a [SnackBar].
///  * [ScaffoldState.removeCurrentSnackBar], which abruptly hides the currently
///    displayed snack bar, if any, and allows the next to be displayed.
///  * [SnackBarAction], which is used to specify an [action] button to show
///    on the snack bar.
///  * [SnackBarThemeData], to configure the default property values for
///    [SnackBar] widgets.
///  * <https://material.io/design/components/snackbars.html>
class SnackBar extends StatefulWidget {
  /// Creates a snack bar.
  ///
  /// The [content] argument must be non-null. The [elevation] must be null or
  /// non-negative.
  const SnackBar({
    Key key,
    @required this.content,
    this.backgroundColor,
    this.elevation,
    this.shape,
    this.behavior,
    this.action,
    this.duration = _snackBarDisplayDuration,
    this.animation,
    this.onVisible,
  }) : assert(elevation == null || elevation >= 0.0),
       assert(content != null),
       assert(duration != null),
       super(key: key);

  /// The primary content of the snack bar.
  ///
  /// Typically a [Text] widget.
  final Widget content;

  /// The Snackbar's background color. If not specified it will use
  /// [ThemeData.snackBarTheme.backgroundColor]. If that is not specified
  /// it will default to a dark variation of [ColorScheme.surface] for light
  /// themes, or [ColorScheme.onSurface] for dark themes.
  final Color backgroundColor;

  /// The z-coordinate at which to place the snack bar. This controls the size
  /// of the shadow below the snack bar.
  ///
  /// Defines the card's [Material.elevation].
  ///
  /// If this property is null, then [ThemeData.snackBarTheme.elevation] is
  /// used, if that is also null, the default value is 6.0.
  final double elevation;

  /// The shape of the snack bar's [Material].
  ///
  /// Defines the snack bar's [Material.shape].
  ///
  /// If this property is null then [ThemeData.snackBarTheme.shape] is used.
  /// If that's null then the shape will depend on the [SnackBarBehavior]. For
  /// [SnackBarBehavior.fixed], no overriding shape is specified, so the
  /// [SnackBar] is rectangular. For [SnackBarBehavior.floating], it uses a
  /// [RoundedRectangleBorder] with a circular corner radius of 4.0.
  final ShapeBorder shape;

  /// This defines the behavior and location of the snack bar.
  ///
  /// Defines where a [SnackBar] should appear within a [Scaffold] and how its
  /// location should be adjusted when the scaffold also includes a
  /// [FloatingActionButton] or a [BottomNavigationBar]
  ///
  /// If this property is null, then [ThemeData.snackBarTheme.behavior]
  /// is used. If that is null, then the default is [SnackBarBehavior.fixed].
  final SnackBarBehavior behavior;

  /// (optional) An action that the user can take based on the snack bar.
  ///
  /// For example, the snack bar might let the user undo the operation that
  /// prompted the snackbar. Snack bars can have at most one action.
  ///
  /// The action should not be "dismiss" or "cancel".
  final SnackBarAction action;

  /// The amount of time the snack bar should be displayed.
  ///
  /// Defaults to 4.0s.
  ///
  /// See also:
  ///
  ///  * [ScaffoldState.removeCurrentSnackBar], which abruptly hides the
  ///    currently displayed snack bar, if any, and allows the next to be
  ///    displayed.
  ///  * <https://material.io/design/components/snackbars.html>
  final Duration duration;

  /// The animation driving the entrance and exit of the snack bar.
  final Animation<double> animation;

  /// Called the first time that the snackbar is visible within a [Scaffold].
  final VoidCallback onVisible;

  // API for Scaffold.showSnackBar():

  /// Creates an animation controller useful for driving a snack bar's entrance and exit animation.
  static AnimationController createAnimationController({ @required TickerProvider vsync }) {
    return AnimationController(
      duration: _snackBarTransitionDuration,
      debugLabel: 'SnackBar',
      vsync: vsync,
    );
  }

  /// Creates a copy of this snack bar but with the animation replaced with the given animation.
  ///
  /// If the original snack bar lacks a key, the newly created snack bar will
  /// use the given fallback key.
  SnackBar withAnimation(Animation<double> newAnimation, { Key fallbackKey }) {
    return SnackBar(
      key: key ?? fallbackKey,
      content: content,
      backgroundColor: backgroundColor,
      elevation: elevation,
      shape: shape,
      behavior: behavior,
      action: action,
      duration: duration,
      animation: newAnimation,
      onVisible: onVisible,
    );
  }

  @override
  State<SnackBar> createState() => _SnackBarState();
}

知識點1:SnackBar是使用者操作後,顯示提示資訊的一個控制元件,類似Android中的Toast,會自動隱藏。SnackBar是以ScaffoldshowSnackBar方法來進行顯示的。

Scaffold.of(context).showSnackBar(SnackBar(content:Text('$result')));

返回資料的方式

知識點2:返回資料其實是特別容易的,通過路由導航方法Navigator.pop()的第二個引數進行傳遞即可,只要在返回時帶第二個引數就可以了。

 Navigator.pop(context,'xxxx');  //xxx就是返回的引數

示例:

import 'package:flutter/material.dart';

void main(){
  runApp(MaterialApp(
      title:'頁面跳轉返回資料',
      home:FirstPage()
  ));
}

class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar:AppBar(title:Text("足沐春風")),
        body:Center(
          child: RouteButton(),
        )
    );
  }
}

//跳轉的Button
class RouteButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      onPressed:(){
        _navigateToServiceMaster(context);
      },
      child: Text('請選擇技師'),
    );
  }
  //知識點3:使用非同步等待關鍵詞async、await
  _navigateToServiceMaster(BuildContext context) async{ //async是啟用非同步方法

    final result = await Navigator.push(//等待
        context,
        MaterialPageRoute(builder: (context)=> ServiceMaster())
    );
    //知識點1:在首頁Toast彈訊息,獲取上一頁面返回來的訊息
    Scaffold.of(context).showSnackBar(SnackBar(content:Text('$result')));
  }
}

class ServiceMaster extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar:AppBar(
          title:Text('技師榮譽榜')
      ),
      body:Center(
          child:Column(
            children: <Widget>[
              RaisedButton(
                child: Text('1號 國家級技師'),
                onPressed: (){
                  //知識點2:pop返回到首頁,並攜帶字元引數資料 "服務於世界各國領導人,譽滿全球。" 返回到首頁
                  Navigator.pop(context,'服務於世界各國領導人,譽滿全球。');
                },
              ) ,RaisedButton(
                child: Text('2號 宗師級技師'),
                onPressed: (){
                  //知識點2:pop返回到首頁,並攜帶字元引數資料 "服務於江湖各界英雄人物。" 返回到首頁
                  Navigator.pop(context,'服務於江湖各界英雄人物。');
                },
              ) ,
              RaisedButton(
                child: Text('3號 業界知名技師'),
                onPressed: (){
                  //知識點2:pop返回到首頁,並攜帶字元引數資料 "服務於藝術界、商界風雲人物。" 返回到首頁
                  Navigator.pop(context,'服務於藝術界、商界風雲人物。');
                },
              ) ,
            ],
          )
      ) ,
    );
  }
}

當進入技師列表點選3號技師按鈕時,會從當前所處的第二個頁面pop返回主介面,並彈出一個Toast訊息:SnackBar訊息,圖如下: