[Flutter]flutter基础之组件基础(四)

一、Button Widget

按钮是开发中常用的可与用户交互的组件,在 Flutter 中,提供了很多跟按钮相关的 Widget 。

1. MaterialButton

MaterialButton 是用来构建一个依赖于 ButtomThemeTheme 的实用工具类。其实现了按钮的基本需求功能,但是官方不建议直接使用此类来创建按钮,此类多用于定时和按钮 Widget 的基类。 应该尽量使用其提供的三个子类来创建,三个子类分别为:RaisedButtonFlatButtonOutlineButton 。这三个子类实现了 Material Design 设计风格的默认参数设置。MaterialButton 继承自 StatelessWidget ,为无状态 Widget, 其构造方法如下:

const MaterialButton({
  Key key,
  //Function类型必传参数,为当按钮点击时的回调方法,如果为null,按钮将处于禁用状态
  @required this.onPressed,
  //Function类型可选命名参数,为当长按按钮时的回调方法
  this.onLongPress,
  //Function类型可选命名参数,为当按钮突出(高亮)显示或停止突出显示时调用的回调方法,参数bool类型
  this.onHighlightChanged,
  //ButtonTextTheme类型可选命名参数,用来定义按钮的基本颜色,最小尺寸,内部填充和形状的默认值
  this.textTheme,
  //Color类型可选命名参数,为按钮文本的颜色
  this.textColor,
  //Color类型可选命名参数,为按钮禁用时的按钮文本的颜色
  this.disabledTextColor,
  //Color类型可选命名参数,按钮状态为可用时且未被点击时的填充色
  this.color,
  //Color类型可选命名参数,为按钮禁用时的按钮填充颜色
  this.disabledColor,
  //Color类型可选命名参数,当按钮具有输入焦点时的填充颜色
  this.focusColor,
  //Color类型可选命名参数,指针悬停在按钮上时的填充颜色
  this.hoverColor,
  //Color类型可选命名参数,用于设置按钮的高亮颜色
  this.highlightColor,
  //Color类型可选命名参数,按钮点击时水波纹效果的颜色
  this.splashColor,
  //Brightness类型可选命名参数,用于设置按钮的主题亮度
  this.colorBrightness,
  //double类型可选命名参数,相对于其父级放置此按钮的z坐标,可用于控制凸起按钮下方的
  //阴影大小,默认值为2,不能为负数
  this.elevation,
  //double类型可选命名参数,当按钮启用并具有焦点时,按钮的elevation
  this.focusElevation,
  //double类型可选命名参数,当按钮启用且指针悬停在按钮上方时,按钮的按钮的elevation
  this.hoverElevation,
  //double类型可选命名参数,按钮为启用状态并被按下时其相对于父级的高程
  this.highlightElevation,
  //double类型可选命名参数,当按钮为不可用状态时其相对于父级的高程
  this.disabledElevation,
  //EdgeInsetsGeometry类型可选命名参数,设置按钮的内边距
  this.padding,
  //ShapeBorder类型可选命名参数,设置按钮形状
  this.shape,
  //Clip类型可选命名参数,用于设置内容将被如何裁剪
  this.clipBehavior = Clip.none,
    //FocusNode类型可选命名参数,按钮的焦点节点  
  this.focusNode,
  //bool类型可选命名命名参数,用于设置是否按钮为当前焦点
  this.autofocus = false,
  //MaterialTapTargetSize类型可选命名参数,设置按钮的最小点击尺寸
  this.materialTapTargetSize,
  //Duration类型可选命名参数,用于定义按钮形状或高亮变化的动画的持续时间
  this.animationDuration
  //double类型可选命名参数,按钮的最小宽度
  this.minWidth,
  //double类型可选命名参数,按钮的高度
  this.height,
  //bool类型可选命名参数,当检测到手势时,是否提供听觉视觉的反馈
  this.enableFeedback = true,
  //Widget类型可选命名参数,是为按钮设置的显示标签,可以为任意Widget,通常使用Text
  this.child,
})

基本使用如下:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Widget基础"),
        ),
        body: studyWidget(context),
      ),
    );
  }
}
//示例代码值修改此函数
Widget studyWidget(BuildContext context) {
  return MaterialButton(
    child: Text("MaterialButton"),
    onPressed: ()=> print("按钮被点击"),
    color: Colors.red,    //不设置填充色默认为无色
  );
}
2. RaisedButton Widget

RaisedButton 是一种外观凸起的按钮,其最小尺寸为 88.0 * 36.0 。构造函数如下:

const RaisedButton({
  Key key,
  @required VoidCallback onPressed,
  VoidCallback onLongPress,
  ValueChanged<bool> onHighlightChanged,
  ButtonTextTheme textTheme,
  Color textColor,
  Color disabledTextColor,
  Color color,
  Color disabledColor,
  Color focusColor,
  Color hoverColor,
  Color highlightColor,
  Color splashColor,
  Brightness colorBrightness,
  double elevation,
  double focusElevation,
  double hoverElevation,
  double highlightElevation,
  double disabledElevation,
  EdgeInsetsGeometry padding,
  ShapeBorder shape,
  Clip clipBehavior = Clip.none,
  FocusNode focusNode,
  bool autofocus = false,
  MaterialTapTargetSize materialTapTargetSize,
  Duration animationDuration,
  Widget child,
})

参数与 MaterialButton 相同部分不再介绍。使用方式如下:

//示例代码值修改此函数
Widget studyWidget(BuildContext context) {
  return RaisedButton(
    child: Text("RaisedButton"),
    onPressed: ()=> print("按钮被点击"),
  );
}

也可写做如下形式:

//示例代码值修改此函数
Widget studyWidget(BuildContext context) {
  return RaisedButton(
    child: Text("RaisedButton"),
    onPressed: buttonPressed,
  );
}

void buttonPressed() {
  print("按钮被点击");
}

其默认效果如下:

202038212.jpg

其他属性如下,使用纵向布局 Widget Column 来展示,如下:

Widget studyWidget(BuildContext context) {
  return Column(
    children: <Widget>[
      RaisedButton(
        child: Text("RaisedButton1"),
        color: Colors.red,   //按钮填充色
        textColor: Colors.amber,  //文字颜色
        onPressed: ()=> print("按钮被点击"),
      ),

      RaisedButton(
        child: Text("RaisedButton2"),
        onPressed: ()=> print("按钮被点击"),
        textTheme: ButtonTextTheme.primary,  //按钮主题
      ),

      RaisedButton(
        child: Text("RaisedButton3"),
        disabledColor: Colors.blue,  //按钮禁用时的填充色
      ),

      RaisedButton(
        child: Text("RaisedButton4"),
        disabledTextColor: Colors.tealAccent,  //按钮禁用时的文字颜色
      ),

      RaisedButton(
        child: Text("RaisedButton5"),
        onPressed: ()=> print("按钮被点击"),
        padding: EdgeInsets.all(20.0),  //设备按钮内边距
      ),

      RaisedButton(
        child: Text("RaisedButton6"),
        onPressed: ()=> print("按钮被点击"),
        shape: BeveledRectangleBorder(    //设置按钮形状
          borderRadius: BorderRadius.circular(8),
        ),
      ),
    ],
  );
}

效果如下图:

202038245.jpg

ButtonTextTheme 是一个枚举类型,如下:

enum ButtonTextTheme {
  //按钮文本的颜色是黑还是白取决于主题 [ThemeData.brightness]
  normal,
    
  //按钮文本的颜色与[ThemeData.accentColor]相同 
  accent,
  
  //按钮文本的颜色依赖于[ThemeData.accentColor]
  primary,
}

在设置内边距 padding 使用的是 EdgeInsetsGeometryEdgeInsetsGeometry 是一个抽象类,其有两个子类 EdgeInsetsEdgeInsetsDirectional ,这里使用 EdgeInsets ,其构造函数如下:

//通过左、上、右、底来创建边距
EdgeInsets.fromLTRB(this.left, this.top, this.right, this.bottom);

//四周创建同样距离的边距
EdgeInsets.all(double value) : left = value, top = value, right = value, bottom = value;

//可以单独为某个方向创建边距
EdgeInsets.only({
    this.left = 0.0,
    this.top = 0.0,
    this.right = 0.0,
    this.bottom = 0.0,
  });

//纵向和横向边距
EdgeInsets.symmetric({
  double vertical = 0.0,
  double horizontal = 0.0,
}) : left = horizontal,
     top = vertical,
     right = horizontal,
     bottom = vertical;

//创建于指定窗口边距相同的边距
EdgeInsets.fromWindowPadding(ui.WindowPadding padding, double devicePixelRatio)
  : left = padding.left / devicePixelRatio,
    top = padding.top / devicePixelRatio,
    right = padding.right / devicePixelRatio,
    bottom = padding.bottom / devicePixelRatio;

shape 设置形状使用的是 ShapeBorder ,其也是一个抽象类,这里使用的是其子类,如下:

BeveledRectangleBorder 用于创建带有平角或斜角的矩形边框。构造函数如下:

const BeveledRectangleBorder({
  //BorderSide类型参数,为边框样式
  this.side = BorderSide.none,
  //BorderRadiusGeometry类型命名可选参数,为每个角的半径
  this.borderRadius = BorderRadius.zero,
}) 

除此之外还有很多其他的形状类可以使用。

3. FlatButton Widget

FlatButton 是平面按钮,没有凸起与阴影等效果,如果不设置颜色等只能看见文字(设置文字的情况下)。使用方式与上述相同。

4. OutlineButton Widget

OutlineButton 为带边框的按钮,其构造函数如下:

const OutlineButton({
  Key key,
  @required VoidCallback onPressed,
    //BorderSide类型可选命名参数,为在按钮可用且未点击状态的边框样式
  this.borderSide,
  //Color类型可选命名参数,为按钮不可用状态时的边框颜色
  this.disabledBorderColor,
  //Color类型可选命名参数,为按钮可用状态并按下时边框的颜色
  this.highlightedBorderColor,
    //.... 省略相同属性部分
  Widget child,
}) 

使用方式与上述相同。

上面介绍的是 MaterialButton 与其子类按钮,下面介绍其他的功能按钮。

5. FloatingActionButton Widget

FloatingActionButton 为 Material Design 设计风格的浮动按钮,可悬停在内容之上,以提升应用程序的主要操作。每个屏幕最多使用一个浮动按钮。其继承自 StatelessWidget 为无状态按钮,有两个构造函数如下:

FloatingActionButton() 构造函数,用于创建圆形浮动操作按钮。

const FloatingActionButton({
  Key key,
  //Widget类型可选命名参数,是为按钮设置的显示的Widget
  this.child,
  //String类型可选命名参数,按钮按下时弹出的提示文本
  this.tooltip,
  //Color类型可选命名参数,默认图标和文本颜色
  this.foregroundColor,
  //Color类型可选命名参数,按钮的背景填充色
  this.backgroundColor,
  //Color类型可选命名参数,当按钮具有输入焦点时用于填充按钮的颜色
  this.focusColor,
  //Color类型可选命名参数,指针悬停在按钮上时的填充颜色
  this.hoverColor,
  //Color类型可选命名参数,按钮点击时水波纹效果的颜色
  this.splashColor,
  //Object类型可选命名参数,应用于按钮的“英雄”小部件的标签
  this.heroTag = const _DefaultHeroTag(),
  //double类型可选命名参数,相对于其父按钮放置此按钮的z坐标
  this.elevation,
  //double类型可选命名参数,当按钮具有输入焦点时,相对于其父按钮放置该按钮的z坐标
  this.focusElevation,
  //double类型可选命名参数,当按钮启用且指针悬停在按钮上方时,按钮的按钮的elevation
  this.hoverElevation,
  //double类型可选命名参数,按钮为启用状态并被按下时其相对于父级的高程
  this.highlightElevation,
  //double类型可选命名参数,按钮禁用时放置该按钮的z坐标
  this.disabledElevation,
  //Function类型必传参数,为当按钮点击时的回调方法,如果为null,按钮将处于禁用状态
  @required this.onPressed,
  //bool类型可选命名参数,控制此按钮的大小
  this.mini = false,
  //ShapeBorder类型可选命名参数,设置按钮形状
  this.shape,
  //Clip类型可选命名参数,用于设置内容将被如何裁剪
  this.clipBehavior = Clip.none,
  //FocusNode类型可选命名参数,此小部件的焦点节点
  this.focusNode,
  //bool类型可选命名参数,如果在当前范围内没有其他节点被聚焦时,此小部件将被选为初始焦点,则为True
  this.autofocus = false,
  //MaterialTapTargetSize类型可选命名参数,设置按钮的最小点击尺寸
  this.materialTapTargetSize,
  //bool类型可选命名参数,如果这是“扩展”浮动操作按钮,则为True
  this.isExtended = false,
})

使用如下:

Widget studyWidget(BuildContext context) {
  return FloatingActionButton(
    child: Icon(Icons.print),
    foregroundColor: Colors.red,
    backgroundColor: Colors.yellow,
    onPressed: ()=> print("按钮被点击"),
  );
}

效果如下图:

202038437.jpg

FloatingActionButton.extended() 构造函数,用于创建一个更宽的带有可选图标和标签的边框形状的浮动操作按钮。

FloatingActionButton.extended({
  Key key,
  //Widget类型可选命名参数,为要实现的图标
  Widget icon,
  //Widget类型必传参数,为按钮要显示的标签
  @required Widget label,
  //...省略相同功能的属性
})

使用如下:

Widget studyWidget(BuildContext context) {
  return FloatingActionButton.extended(
    icon: Icon(Icons.memory),
    label: Text("按钮"),
    foregroundColor: Colors.red,
    backgroundColor: Colors.yellow,
    onPressed: ()=> print("按钮被点击"),
  );
}

效果如下:

202038440.jpg
6. IconButton Widget

Material Design 设计风格图标按钮,其继承自 StatelessWidget 为无状态按钮,构造方法如下:

const IconButton({
  Key key,
  //double类型可选命名参数,用来定义按钮内图标的大小
  this.iconSize = 24.0,
  //EdgeInsetsGeometry类型可选命名参数,用于定义图标按钮的内边距
  this.padding = const EdgeInsets.all(8.0),
  //AlignmentGeometry类型可选命名参数,用于设置图标显示的位置
  this.alignment = Alignment.center,
  //Widget类型必传参数,按钮内部使用的图标
  @required this.icon,
  //Color类型可选命名参数,按钮处于启动状态时,内部图标使用的颜色
  this.color,
  //Color类型可选命名参数,当按钮具有输入焦点时,按钮图标的颜色
  this.focusColor,
    //Color类型可选命名参数,指针悬停在按钮上时的填充颜色
  this.hoverColor,
  //Color类型可选命名参数,用于设置按钮的高亮颜色
  this.highlightColor,
  //Color类型可选命名参数,按钮点击时水波纹效果的颜色
  this.splashColor,
  //Color类型可选类型参数,按钮禁用状态下,内部图标使用的颜色
  this.disabledColor,
    //Function类型必传参数,为当按钮点击时的回调方法,如果为null,按钮将处于禁用状态
  @required this.onPressed,
  //FocusNode类型可选命名参数,此小部件的焦点节点
  this.focusNode,
  //bool类型可选命名参数,如果当其范围内没有其他节点当前被聚焦时,此小部件将被选为初始焦点,则为True
  this.autofocus = false,
  //String类型可选命名参数,按钮按下时弹出的提示文本
  this.tooltip,
  //bool类型可选命名参数,检测到的手势是否提供听觉视觉的反馈
  this.enableFeedback = true,
})

使用方式如下:

Widget studyWidget(BuildContext context) {
  return IconButton(
    icon: Icon(Icons.add),
    color: Colors.yellow,
    onPressed: (){},
  );
}
7. DropdownButton Widget

DropdownButton 用于定义一个下拉菜单按钮,每一个菜单项使用 DropdownMenuItem 定义。一个菜单中的菜单项需要为同一类型。DropdownButton 继承自 StatefulWidget 为一个有状态的 Widget ,其构造函数如下:

DropdownButton({
  Key key,
  // List<DropdownMenuItem<T>>类型必传参数,设置的菜单项列表
  @required this.items,
  //DropdownButtonBuilder类型可选命名参数,用于定制与项目中的下拉菜单
  //项(DropdownMenuItem)相对应的按钮
  this.selectedItemBuilder,
  //泛型T类型可选命名参数,为当前选择的是哪个下拉菜单项
  this.value,
  //Widget类型可选命名参数,下拉按钮显示的占位符Widget
  this.hint,
  //Widget类型可选命名参数,当下拉菜单被禁用时显示的内容
  this.disabledHint,
  //Function类型必传参数,选择一个菜单项时调用
  @required this.onChanged,
  //int类型可选命名参数,打开时放置菜单的z坐标
  this.elevation = 8,
  //TextStyle类型可选命名参数,用于设置下拉菜单中文本的文本的样式,以及点击按钮时出现的下拉菜单
  this.style,
  //Widget类型可选命名参数,用于绘制下拉按钮下划线的Widget
  this.underline,
  //Widget类型可选命名参数,下拉按钮图标的Widget
  this.icon,
  //Color类型可选命名参数,按钮禁用状态的内部图标的颜色
  this.iconDisabledColor,
  //Color类型可选命名参数,按钮启用状态的内部图标的颜色
  this.iconEnabledColor,
  //double类型可选命名参数,下拉按钮的向下箭头图标按钮的大小
  this.iconSize = 24.0,
  //bool类型可选命名参数,是否降低按钮的高度
  this.isDense = false,
  //bool类型可选命名参数,是否将下拉列表的内部内容设置为水平填充其父项
  this.isExpanded = false,
  //double类型可选命名参数,如果为null,则菜单项高度将根据每个菜单项的固有高度而变化
  this.itemHeight = kMinInteractiveDimension,
  //Color类型可选命名参数,当按钮具有输入焦点时,按钮材质的颜色
  this.focusColor,
  //FocusNode类型可选命名参数,此小部件的焦点节点
  this.focusNode,
  //bool类型可选命名参数,如果当其范围内没有其他节点当前被聚焦时,此小部件将被选为初始焦点,则为True
  this.autofocus = false,
}) 

DropdownMenuItem 菜单项的构造函数如下:

const DropdownMenuItem({
  Key key,
  //泛型T类型可选参数,为当用户选择此菜单项时返回的值
  this.value,
  //Widget类型必传参数,菜单项要显示的Widget
  @required Widget child,
})

基本使用方式如下:

Widget studyWidget(BuildContext context) {
  return DropdownButton(
    items: <DropdownMenuItem<int>>[
      DropdownMenuItem(
        child: Text("Item 1"),
        value: 1,
      ),
      DropdownMenuItem(
        child: Text("Item 2"),
        value: 2,
      ),
      DropdownMenuItem(
        child: Text("Item 3"),
        value: 3,
      ),
    ],

    onChanged: (value)=> print(value),
  );
}
2020381102.jpg

但是现在存在一个问题,虽然可以选择菜单项并且输出对应的 value ,但是操作后界面是无变化的。上面说过 DropdownButton 继承自 StatefulWidget ,是一个有状态的 Widget,对于有状态的 Widget ,前面文章曾经介绍过,都会与状态类一起使用,在状态类中对数据界面做操作才能实现界面的更新操作,更改代码如下:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Widget基础"),
        ),
        body: MyDropdownMenu(),
      ),
    );
  }
}

class MyDropdownMenu extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MyDropdownMenuState();
  }
}

class _MyDropdownMenuState extends State<MyDropdownMenu> {

  int currentSelectIndex = 1;

  @override
  Widget build(BuildContext context) {
    return DropdownButton(
      items: <DropdownMenuItem<int>>[
        DropdownMenuItem(
          child: Text("Item 1"),
          value: 1,
        ),
        DropdownMenuItem(
          child: Text("Item 2"),
          value: 2,
        ),
        DropdownMenuItem(
          child: Text("Item 3"),
          value: 3,
        ),
      ],

      value: currentSelectIndex,

      onChanged: (value) {
        print(value);
        setState(() {
          currentSelectIndex = value;
        });
      },
    );
  }
}

将更新数据项放在 setState() 方法内进行操作即可。

其他属性设置如下:

class _MyDropdownMenuState extends State<MyDropdownMenu> {

  int currentSelectIndex = 1;

  @override
  Widget build(BuildContext context) {
    return DropdownButton(
      items: <DropdownMenuItem<int>>[
        DropdownMenuItem(
          child: Text("Item 1"),
          value: 1,
        ),
        DropdownMenuItem(
          child: Text("Item 2"),
          value: 2,
        ),
        DropdownMenuItem(
          child: Text("Item 3"),
          value: 3,
        ),
      ],

      value: currentSelectIndex,
      selectedItemBuilder: (BuildContext context){
        return <Widget>[
          Icon(Icons.add),
          Icon(Icons.print),
          Icon(Icons.ac_unit),
        ];
      },
      hint: Text("hint"),
      disabledHint: Text("按钮被禁用"),
      style: TextStyle(
        fontSize: 24.0,
        color: Colors.red,
      ),
      underline: Container(
        height: 1,
        color: Colors.yellow,
      ),
      icon: Icon(Icons.arrow_downward),

      onChanged: (value) {
        print(value);
        setState(() {
          currentSelectIndex = value;
        });
      },
    );
  }
}

效果如下:

202039228.jpg

selectedItemBuilder 使用 DropdownButtonBuilder 构造器,其是一个返回 List<Widget>Function ,圆形为:List<Widget> Function(BuildContext context) ,作用是定义与下拉列表中选项相对应的每一个 Widget ,这个 Widget 用来显示在菜单未点开的情况下显示。

hint 用来定义按钮在 value 属性为 null 或此按钮被禁用且 disabledHint 属性也为 null 时显示。

disabledHint 如果不为 null ,在按钮被禁用时显示。

icon 属性用来定义下拉按钮靠右侧显示的图标。

8. PopupMenuButton Widget

PopupMenuButton 是弹出菜单

const PopupMenuButton({
  Key key,
  //PopupMenuItemBuilder<T>类型必传参数,当按下按钮创建要在菜单中显示的项目时调用
  @required this.itemBuilder,
  //泛型T类型可选命名参数,菜单打开时应突出显示的菜单项的值(如果有),也就是打开时选择哪一项
  this.initialValue,
  //PopupMenuItemSelected<T>类型可选命名参数,当用户从该按钮创建的弹出菜单中选择一个值时调用
  this.onSelected,
  //PopupMenuCanceled类型可选命名参数,当用户在不选择项目的情况下关闭弹出菜单时调用
  this.onCanceled,
  //String类型可选命名参数,按钮按下时弹出的提示文本
  this.tooltip,
  //double类型可选命名参数,打开时放置菜单的z坐标。这控制了菜单下阴影的大小
  this.elevation,
  //EdgeInsetsGeometry类型可选命名参数,默认情况下匹配图标按钮的8 dps填充。在某些情况下,特别是当该按钮作为列表项的尾部元素出现时,能够将填充设置为零是很有用的
  this.padding = const EdgeInsets.all(8.0),
  //Widget类型可选命名参数,如果提供,child是用于该按钮的小部件,该按钮将利用InkWell进行点击
  this.child,
  //Widget类型可选命名参数,如果图标用于此按钮,该按钮的行为类似IconButton
  this.icon,
  //Offset类型可选命名参数,应用于弹出菜单按钮的偏移量
  this.offset = Offset.zero,
  //bool类型可选命名参数,该弹出菜单按钮是否是交互式的
  this.enabled = true,
  //ShapeBorder类型可选命名参数,用于菜单的形状
  this.shape,
  //Color类型可选命名参数,菜单背景颜色
  this.color,
  //bool类型可选命名参数,如果为真(缺省值),那么菜单将被包装成继承主题的副本,如主题和弹出主题,它们被定义在显示菜单的构建上下文之上
  this.captureInheritedThemes = true,
})

itemBuilder 的类型是 PopupMenuItemBuilder<T> ,其是一个 Function ,原型为:List<PopupMenuEntry<T>> Function(BuildContext context)PopupMenuButton 的使用如下:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Widget基础"),
        ),
        body: MyPopupMenuButton(),
      ),
    );
  }
}

class MyPopupMenuButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return PopupMenuButton(
      itemBuilder: (context) {
        return <PopupMenuEntry<String>> [
          const PopupMenuItem(
            child: Text("选项1"),
            value: "1",
          ),

          const PopupMenuItem(
            child: Text("选项2"),
            value: "2",
          ),

          const PopupMenuItem(
            child: Text("选项3"),
            value: "3",
          ),
        ];
      },
      onSelected: (value){
        print(value);
      },

      onCanceled: (){
        print("未选择任何选项,菜单关闭");
      },
      icon: Icon(Icons.add),
      initialValue: "2",
      offset: Offset(50, 110),
      color: Colors.yellow,
    );;
  }
}

其中,childicon 只能选择一个使用,都是图标在界面上未展开时显示的 Widget 。这里使用的是无状态的形式,如果需要对界面做数据更新处理,则需要使用 StatefulWidget

效果如下:

2020310448.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容