Flutter 组件之 按钮、Wrap、StatefulWidg

2023-10-12  本文已影响0人  Abner_XuanYuan

1、按钮

1、属性
onPressed:必填参数,按下按钮时触发的回调,接收一个方法,传 null 表示按钮禁用,会显示禁用相关样式。
child:子组件。
style:ButtonStyle 类型的样式。

ButtonStyle 属性

ButtonStyle ButtonStyle({
  MaterialStateProperty<TextStyle?>? textStyle,  //文本样式
  MaterialStateProperty<Color?>? backgroundColor,  //背景色
  MaterialStateProperty<Color?>? foregroundColor,  //前景色(文本颜色)
  MaterialStateProperty<Color?>? overlayColor,  //高亮色,按钮按下之后的颜色
  MaterialStateProperty<Color?>? shadowColor,  //阴影色
  MaterialStateProperty<Color?>? surfaceTintColor,  //表面色调颜色
  MaterialStateProperty<double?>? elevation,  //阴影度
  MaterialStateProperty<EdgeInsetsGeometry?>? padding,  //内容边距
  MaterialStateProperty<Size?>? minimumSize,  //最小尺寸
  MaterialStateProperty<Size?>? fixedSize,  //按钮尺寸
  MaterialStateProperty<Size?>? maximumSize,  //最大尺寸
  MaterialStateProperty<Color?>? iconColor,  //图标颜色
  MaterialStateProperty<double?>? iconSize,  //图标大小
  MaterialStateProperty<BorderSide?>? side,  //设置边框
  MaterialStateProperty<OutlinedBorder?>? shape,  //设置按钮的形状
  MaterialStateProperty<MouseCursor?>? mouseCursor,  //桌面端鼠标样式
  VisualDensity? visualDensity,  //视觉密度
  MaterialTapTargetSize? tapTargetSize,  //响应触摸区域
  Duration? animationDuration,  //动画持续时间
  bool? enableFeedback,  //是否启用反馈,如长按震动
  AlignmentGeometry? alignment,  //子组件对齐样式
  InteractiveInkFeatureFactory? splashFactory,  //没有水波纹效果
})
2、按钮分类

ElevatedButton:即"凸起"按钮,它默认带有阴影和灰色背景。按下后,阴影会变大。

ElevatedButton ElevatedButton({
  Key? key,
  required void Function()? onPressed,  //点击事件
  void Function()? onLongPress,  //长按事件
  void Function(bool)? onHover,  //鼠标悬停时回调
  void Function(bool)? onFocusChange,  //焦点
  ButtonStyle? style,
  FocusNode? focusNode,  //用于焦点管理和监听
  //如果当前未将其范围内的其他节点作为焦点,则将此小部件选择为初始焦点时为 True
  bool autofocus = false,
  Clip clipBehavior = Clip.none,  //裁剪
  MaterialStatesController? statesController,
  required Widget? child,
})

示例

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () {
        print("ElevatedButton -- Click");
      },
      onLongPress: () {
        print("ElevatedButton -- LongClick");
      },
      style: ButtonStyle(
        backgroundColor: MaterialStateProperty.all(Colors.green),
        foregroundColor: MaterialStateProperty.all(Colors.white),
        shadowColor: const MaterialStatePropertyAll(Colors.greenAccent),
        overlayColor: const MaterialStatePropertyAll(Colors.transparent),//按钮点击时的高亮色
      ),
      child: const Text("ElevatedButton"),
    );
  }
}

TextButton:文本按钮,默认背景透明并不带阴影。按下后,会有背景色。

//TextButton
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return TextButton(
      child: const Text("TextButton"),
      onPressed: () {
        print("TextButton -- Click");
      },
      onLongPress: () {
        print("TextButton -- Long Click");
      },
      autofocus: true,
      style: TextButton.styleFrom(
        backgroundColor: Colors.grey,
        foregroundColor: Colors.red,
        shadowColor: Colors.green,
      ),
    );
  }
}

OutlinedButton:默认有一个边框,不带阴影且背景透明。按下后,边框颜色会变亮、同时出现背景和阴影。

//OutlinedButton
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return OutlinedButton(
      onPressed: () {
        print("OutlinedButton -- Click");
      },
      onLongPress: () {
        print("OutlinedButton -- Long Click");
      },
      style: const ButtonStyle(
        backgroundColor: MaterialStatePropertyAll(Colors.green),
        foregroundColor: MaterialStatePropertyAll(Colors.black),
        overlayColor: MaterialStatePropertyAll(Colors.transparent),
      ),
      child: const Text("OutlinedButton"),
    );
  }
}

IconButton:是一个可点击的 Icon,不包括文字,默认没有背景,点击后会出现背景。

//IconButton
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return IconButton(
      icon: const Icon(Icons.thumb_up),
      onPressed: () {
        print("IconButton -- Click");
      },
      iconSize: 40, //图标大小
      padding: const EdgeInsets.all(30),
      alignment: Alignment.topLeft,

      //以下两行可以取消按钮的默认点击效果
      splashColor: Colors.transparent,
      highlightColor: Colors.transparent,
    );
  }
}

浮动按钮:是一个圆形图标按钮,它触发应用程序中的主要操作。
FloatingActionButton:它创建一个简单的圆形浮动按钮,其中包含一个子部件。T 必须有一个子参数来显示 widget 。

//FloatingActionButton
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return FloatingActionButton(onPressed: () { 
      print("FloatingActionButton -- Click");
     },
     backgroundColor: Colors.green,
     foregroundColor: Colors.white,
     child: const Icon(Icons.add),
     );
  }
}

FloatingActionButton.extended:它创建了一个宽的浮动按钮,其中包含一个图标和一个标签。它使用标签和图标参数,而不是子参数。

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return FloatingActionButton.extended(
        onPressed: () {
          print("FloatingActionButton.extended -- Click");
        },
        icon: const Icon(Icons.add),
        backgroundColor: Colors.green,
        foregroundColor: Colors.black,
        label: const Text("Add"));
  }
}

自适应按钮

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Expanded(
          child: Container(
            height: 60,
            margin: const EdgeInsets.all(10),
            child: ElevatedButton(
              child: const Text('自适应按钮'),
              onPressed: () {
                print("自适应按钮");
              },
            ),
          ),
        )
      ],
    );
  }
}

修改按钮宽高

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      height: 50,
      child: ElevatedButton(
          onPressed: () {
            print("自定义宽高");
          },
          style: ElevatedButton.styleFrom(
            foregroundColor: Colors.red,
            backgroundColor: Colors.green,
          ),
          child: const Text("自定义宽高")),
    );
  }
}

2、Wrap

Wrap 可以实现流布局,单行的 Wrap 跟 Row 表现几乎一致,单列的 Wrap 则跟 Column 表现几乎一致。但 Row 与 Column 都是单行单列的,Wrap 则不是,mainAxis 上空间不足时,则向 crossAxis 上去扩展显示。

1、属性
Wrap Wrap({
  Key? key,
  Axis direction = Axis.horizontal,    //主轴的方向,默认水平
  WrapAlignment alignment = WrapAlignment.start,    //主轴的对其方式
  double spacing = 0.0,    //主轴方向上的间距
 //run 的对齐方式。run 可以理解为新的行或者列,如果是水平方向布局的话,run 可以理解为新的一行。
  WrapAlignment runAlignment = WrapAlignment.start,   
  double runSpacing = 0.0,  //run的间距
  WrapCrossAlignment crossAxisAlignment = WrapCrossAlignment.start,    //次轴对齐方式
  TextDirection? textDirection,    //文本方向
  VerticalDirection verticalDirection = VerticalDirection.down,    // children 摆放顺序,默认是down。
  Clip clipBehavior = Clip.none,
  List<Widget> children = const <Widget>[],
})
2、使用
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  List<Widget> _customButton() {
    List<Widget> list = [];
    for (var e in listData) {
      list.add(XSHButton(e["title"], onPressed: () {
        print("标题: " + e["title"]);
      }));
    }
    return list;
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(3),
      child: Wrap(
        spacing: 5,
        runSpacing: 5,
        // direction: Axis.vertical,
        // alignment: WrapAlignment.start,
        // runAlignment: WrapAlignment.center,
        children: _customButton(),
      ),
    );
  }
}

//自定义按钮
// ignore: must_be_immutable
class XSHButton extends StatelessWidget {
  String text;
  void Function() onPressed;

  XSHButton(this.text, {super.key, required this.onPressed});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      style: const ButtonStyle(
        backgroundColor:
            MaterialStatePropertyAll(Color.fromARGB(255, 236, 233, 233)),
        foregroundColor: MaterialStatePropertyAll(Colors.black45),
      ),
      onPressed: onPressed,
      child: Text(text),
    );
  }
}

3、在 Flutter 中自定义组件其实就是一个类,这个类需要继承 StatelessWidget 或者 StatefulWidget。

StatelessWidget是无状态组件,状态不可变的 widget。
StatefulWidget是有状态组件,持有的状态可能在 widget 生命周期改变。如果想改变页面中数据的话这个时候就需要用到 StatefulWidget。

使用示例

//计数器
class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int countNum = 0;
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: [
          const SizedBox(
            height: 100,
          ),
          Text(
            "数字是: $countNum",
            style: const TextStyle(color: Colors.red, fontSize: 20),
          ),
          const SizedBox(
            height: 100,
          ),
          ElevatedButton(
              onPressed: () {
                setState(() {
                  countNum++;
                });
              },
              child: const Text("增加")),
        ],
      ),
    );
  }
}
//动态列表
class HomePage1 extends StatefulWidget {
  const HomePage1({super.key});

  @override
  State<HomePage1> createState() => _HomePage1State();
}

class _HomePage1State extends State<HomePage1> {

  List<String> list = [];
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        Column(
          children: list.map((e) {
            return ListTile(
              title: Text(e),
            );
          }).toList(),
        ),
        const SizedBox(
          height: 10,
        ),
        Padding(
          padding: const EdgeInsets.all(10),
          child: ElevatedButton(
              onPressed: () {
                setState(() {
                  list.add("第 ${list.length + 1} 条数据");
                });
              },
              child: const Text("增加一条数据")),
        ),
      ],
    );
  }
}

刷新页面:setState 方法。

上一篇 下一篇

猜你喜欢

热点阅读