【Flutter】AspectRatio组件Card组件按钮组件Wrap组件

news2024/11/19 9:39:25

🔥 本文由 程序喵正在路上 原创,CSDN首发!
💖 系列专栏:Flutter学习
🌠 首发时间:2024年5月25日
🦋 欢迎关注🖱点赞👍收藏🌟留言🐾

目录

  • AspectRatio组件
  • Card组件
    • Card实现一个通讯录的卡片
    • Card实现一个图文列表
  • 按钮组件
    • 按钮组件的属性
    • ElevatedButton、TextButton、OutlinedButton、IconButton
    • 带图标的按钮
    • 修改按钮的宽度高度
    • 自适应按钮
    • 配置圆角圆形按钮
    • 修改OutlinedButton边框
  • Wrap组件
    • 自定义一个按钮组件
    • Wrap组件的简单使用
    • Wrap组件搜索页面布局

AspectRatio组件

AspectRatio 的作用是根据设置调整子元素 child 的宽高比。

AspectRatio 首先会在布局限制条件允许的范围内尽可能的扩展,widget 的高度是由宽度和比率决定的,类似于 BoxFit 中的 contain,按照固定比率去尽量占满区域。

如果在满足所有限制条件过后无法找到一个可行的尺寸,AspectRatio 最终将会去优先适应布局限制条件,而忽略所设置的比率。

属性说明
aspectRatio宽高比,最终可能不会根据这个值去布局,具体要看综合因素,外层是否允许按照这种比率进行布局,这只是一个参考值
chlid子组件
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return AspectRatio(
        aspectRatio: 3 / 1, //宽度为屏幕的宽度,高度为宽度的三分之一
        child: Container(
          color: Colors.blue,
        ));
  }
}

在这里插入图片描述

Card组件

Card 是卡片组件块,内容可以由大多数类型的 Widget 构成,Card 具有圆角和阴影,这让它看起来有立体感。

属性说明
margin外边距
child子组件
elevation阴影值的深度
color背景颜色
shadowColor阴影颜色
clipBehavior内容溢出的剪切方式,Clip.none:不剪切;Clip.hardEdge:剪切但不应用抗锯齿;Clip.antiAlias:剪切而且抗锯齿;Clip.antiAliasWithSaveLayer:带有抗锯齿的剪辑,并在剪辑之后立即保存 saveLayer
ShapeCard 的阴影效果,默认的阴影效果为圆角的长方形边

Card实现一个通讯录的卡片

实现如下效果:

在这里插入图片描述

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

  
  Widget build(BuildContext context) {
    return ListView(
      children: [
        Card(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(10),
          ),
          elevation: 20, //阴影深度
          color: Colors.blue.shade100,
          margin: const EdgeInsets.all(10),
          child: const Column(
            children: [
              ListTile(
                title: Text(
                  "张三",
                  style: TextStyle(fontSize: 28),
                ),
                subtitle: Text("高级软件工程师"),
              ),
              Divider(),
              ListTile(title: Text("电话:12345678910")),
              ListTile(title: Text("地址:北京市海淀区"))
            ],
          ),
        ),
        Card(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(10),
          ),
          elevation: 20, //阴影深度
          color: Colors.green.shade100,
          margin: const EdgeInsets.all(10),
          child: const Column(
            children: [
              ListTile(
                title: Text(
                  "张三",
                  style: TextStyle(fontSize: 28),
                ),
                subtitle: Text("高级软件工程师"),
              ),
              Divider(),
              ListTile(title: Text("电话:12345678910")),
              ListTile(title: Text("地址:北京市海淀区"))
            ],
          ),
        ),
        Card(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(10),
          ),
          elevation: 20, //阴影深度
          color: Colors.red.shade100,
          margin: const EdgeInsets.all(10),
          child: const Column(
            children: [
              ListTile(
                title: Text(
                  "张三",
                  style: TextStyle(fontSize: 28),
                ),
                subtitle: Text("高级软件工程师"),
              ),
              Divider(),
              ListTile(title: Text("电话:12345678910")),
              ListTile(title: Text("地址:北京市海淀区"))
            ],
          ),
        ),
      ],
    );
  }
}

Card实现一个图文列表

实现如下效果:

在这里插入图片描述

import 'package:flutter/material.dart';
import './res/listData.dart';

void main() {
  runApp(MaterialApp(
    debugShowCheckedModeBanner: false,
    home: Scaffold(
      appBar: AppBar(title: const Text("Card实现图文列表")),
      body: const MyApp(),
    ),
  ));
}

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

  List<Widget> _initCardData() {
    var tempList = listData.map((value) {
      return Card(
        elevation: 20,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
        margin: const EdgeInsets.all(10),
        child: Column(
          children: [
            AspectRatio(
                aspectRatio: 16 / 9,
                child: Image.network(
                  value["imageUrl"],
                  fit: BoxFit.cover,
                )),
            ListTile(
              leading: CircleAvatar(
                backgroundImage: NetworkImage(value["imageUrl"]),
              ),
              title: Text(value["title"]),
              subtitle: Text(value["author"]),
            ),
          ],
        ),
      );
    });

    return tempList.toList();
  }

  
  Widget build(BuildContext context) {
    return ListView(
      children: _initCardData(),
    );
  }
}

按钮组件

按钮组件的属性

属性说明
onPressed必填参数,按下按钮时触发的回调,接收一个方法,传 null 表示按钮禁用,会显示禁用相关样式
child子组件
style通过 ButtonStyle 装饰

ButtonStylee里面的常用的参数

属性名称值类型属性值
foregroundColorColor文本颜色
backgroundColorColor按钮颜色
shadowColorColor阴影颜色
elevationdouble阴影的范围,值越大阴影范围越大
padding内边距
shape设置按钮的形状
side设置按钮边框

ElevatedButton、TextButton、OutlinedButton、IconButton

  • ElevatedButton 即 “凸起” 按钮,它默认带有阴影和灰色背景。按下后,阴影会变大
  • TextButton 即文本按钮,默认背景透明并不带阴影。按下后,会有背景色
  • OutlineButton 默认有一个边框,不带阴影且背景透明。按下后,边框颜色会变亮、同时出现背景和阴影
  • IconButton 是一个可点击的 Icon,不包括文字,默认没有背景,点击后会出现背景
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return ListView(children: [
      Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          ElevatedButton(
              onPressed: () {
                print("ElevatedButton");
              },
              child: const Text("普通按钮")),
          TextButton(onPressed: () {}, child: const Text("文本按钮")),
          OutlinedButton(onPressed: () {}, child: const Text("边框按钮")),
          IconButton(onPressed: () {}, icon: const Icon(Icons.thumb_up))
        ],
      ),
    ]);
  }
}

在这里插入图片描述

带图标的按钮

ElevatedButtonTextButtonOutlineButton 都有一个 icon 构造函数,通过它可以轻松创建带图标的按钮。

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

  
  Widget build(BuildContext context) {
    return ListView(children: [
      Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
        ElevatedButton.icon(
            onPressed: () {},
            icon: const Icon(Icons.send),
            label: const Text("发送")),
        TextButton.icon(
            onPressed: () {},
            icon: const Icon(Icons.info),
            label: const Text("消息")),
        OutlinedButton.icon(
            onPressed: () {},
            icon: const Icon(Icons.add),
            label: const Text("增加"))
      ]),
    ]);
  }
}

在这里插入图片描述

修改按钮的宽度高度

按钮组件中没有属性可以让我们直接修改宽度和高度,但是我们可以将按钮写在一个 Container 或者 SizeBox 里面,以此来控制按钮的宽高。

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

  
  Widget build(BuildContext context) {
    return ListView(children: [
      Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          SizedBox(
            height: 80,
            width: 200,
            child: ElevatedButton(
              style: ButtonStyle(
                  backgroundColor: MaterialStateProperty.all(Colors.red),
                  foregroundColor: MaterialStateProperty.all(Colors.black)),
              onPressed: () {},
              child: const Text('宽度高度'),
            ),
          ),
        ],
      ),
    ]);
  }
}

在这里插入图片描述

自适应按钮

将按钮写在 Expanded 组件中,可以让按钮自适应,当还有其它组件时,按钮会根据屏幕自动调节大小

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

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

在这里插入图片描述

配置圆角圆形按钮

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

  
  Widget build(BuildContext context) {
    return ListView(children: [
      Row(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: [
          ElevatedButton(
              style: ButtonStyle(
                  shape: MaterialStateProperty.all(//圆角
                      RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(12)))),
              onPressed: () {},
              child: const Text("圆角")),
          SizedBox(
            height: 80,
            width: 80,
            child: ElevatedButton(
                style: ButtonStyle(
                    shape: MaterialStateProperty.all(//圆形
                        const CircleBorder(
                            side: BorderSide(width: 2, color: Colors.yellow)))),
                onPressed: () {},
                child: const Text("圆形")),
          ),
        ],
      ),
    ]);
  }
}

在这里插入图片描述

修改OutlinedButton边框

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

  
  Widget build(BuildContext context) {
    return ListView(children: [
      Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Expanded(
            child: Container(
              margin: const EdgeInsets.all(20),
              height: 50,
              child: OutlinedButton(
                  style: ButtonStyle(
                      foregroundColor: MaterialStateProperty.all(Colors.black),
                      side: MaterialStateProperty.all(
                          const BorderSide(width: 1, color: Colors.blue))),
                  onPressed: () {},
                  child: const Text("修改边框")),
            ),
          )
        ],
      )
    ]);
  }
}

在这里插入图片描述

Wrap组件

自定义一个按钮组件

Wrap 可以实现流布局,单行的 WrapRow 表现几乎一致,单列的 Wrap 则跟 Column 表现几乎一致。但 RowColumn 都是单行单列的,Wrap 则突破了这个限制,mainAxis 上空间不足时,则向 crossAxis
去扩展显示。

属性说明
direction主轴的方向,默认水平
alignment主轴的对齐方式
spacing主轴方向上的间距
textDirection文本方向
verticalDirection定义了 children 的摆放顺序,默认是 down,见 Flex 相关属性介绍
runAlignmentrun 的对齐方式,run 可以理解为新的行或者列,如果是水平方向布局的话,run 可以理解为新的一行
runSpacingrun 的间距

下面我们通过实现一个案例来介绍 Wrap 组件的使用:

//自定义按钮
class MyButton extends StatelessWidget {
  String text; //按钮上的文本
  void Function()? onPressed;
  MyButton(this.text, {super.key, required this.onPressed});

  
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: onPressed,
      style: ButtonStyle(
        backgroundColor:
            MaterialStateProperty.all(const Color.fromARGB(255, 239, 237, 237)),
        foregroundColor: MaterialStateProperty.all(Colors.black45),
      ),
      child: Text(text),
    );
  }
}

Wrap组件的简单使用

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

  
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(10),
      child: Wrap(
        spacing: 5,		//水平方向间隔
        runSpacing: 5,	//垂直方向间隔
        children: [
          MyButton("第1集", onPressed: () {}),
          MyButton("第2集", onPressed: () {}),
          MyButton("第3集", onPressed: () {}),
          MyButton("第4集", onPressed: () {}),
          MyButton("第5集", onPressed: () {}),
          MyButton("第6集", onPressed: () {}),
          MyButton("第7集", onPressed: () {}),
          MyButton("第8集", onPressed: () {}),
          MyButton("第9集", onPressed: () {}),
          MyButton("第10集", onPressed: () {}),
        ],
      ),
    );
  }
}

在这里插入图片描述

Wrap组件搜索页面布局

实现如下效果:

在这里插入图片描述

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

  
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(10),
      child: ListView(
        children: [
          Row(
            children: [
              Text("热搜", style: Theme.of(context).textTheme.headlineSmall)
            ],
          ),
          const Divider(),
          Wrap(
            spacing: 10,
            runSpacing: 12,
            children: [
              MyButton("T恤", onPressed: () {}),
              MyButton("笔记本", onPressed: () {}),
              MyButton("时尚", onPressed: () {}),
              MyButton("游戏", onPressed: () {}),
              MyButton("弹射风筝", onPressed: () {}),
              MyButton("斗篷伞", onPressed: () {}),
              MyButton("猫窝鱼缸", onPressed: () {}),
              MyButton("鸡腿帽", onPressed: () {}),
            ],
          ),
          const SizedBox(height: 10),
          Row(
            children: [
              Text("历史搜索", style: Theme.of(context).textTheme.headlineSmall)
            ],
          ),
          const Divider(),
          const Column(
            children: [
              ListTile(title: Text("时尚")),
              Divider(),
              ListTile(title: Text("潮流")),
              Divider(),
            ],
          ),
          const SizedBox(height: 40),
          Padding(
            padding: const EdgeInsets.all(40),
            child: OutlinedButton.icon(
              onPressed: () {},
              icon: const Icon(Icons.delete),
              label: const Text("清空历史记录"),
              style: ButtonStyle(
                  foregroundColor: MaterialStateProperty.all(Colors.black38)),
            ),
          )
        ],
      ),
    );
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1692182.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开源内网穿透神器:中微子代理(neutrino-proxy)实现内网穿刺

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

go select 原理

编译器会使用如下的流程处理 select 语句&#xff1a; 将所有的 case 转换成包含 channel 以及类型等信息的 runtime.scase 结构体。调用运行时函数 runtime.selectgo 从多个准备就绪的 channel 中选择一个可执行的 runtime.scase 结构体。通过 for 循环生成一组 if 语句&…

计算机网络——TCP 协议的三次握手 / 四次挥手

简述 TCP / UDP 协议都是传输层的协议。 UDP 是面向无连接的协议&#xff0c;就是说发送端不在乎消息数据是否传输到接收端了&#xff0c;所以会出现数据丢失的情况&#xff0c;所以可靠性也不高。 TCP 是面向连接的、可靠的、基于字节流的传输层协议。所谓面向连接的&#…

win11 wsl ubuntu24.04

win11 wsl ubuntu24.04 一&#xff1a;开启Hyper-V二&#xff1a;安装wsl三&#xff1a;安装ubuntu24.04三&#xff1a;桥接模式&#xff0c;固定IP四&#xff1a;U盘使用五&#xff1a;wsl 从c盘迁移到其它盘参考资料 一&#xff1a;开启Hyper-V win11家庭版开启hyper-v 桌面…

【Crypto】RSA

文章目录 题目步骤1.计算 &#x1d45b;2.计算欧拉函数 &#x1d719;(&#x1d45b;)3. 扩展欧几里得算法求逆元 &#x1d451; 解题感悟 题目 p473398607161 q4511491 e17 求d 步骤 1.计算 &#x1d45b; 公式&#xff1a;npq n47339860716145114912135733555619387051 …

微信小程序知识点1

一. 页面样式和结构 1.1 小程序组件(html) (1) 区域布局组件 view 定义块级区域&#xff0c;相当于网页中的 div 标签text 定义行内区域&#xff0c;相当于网页中的 span标签 (2) 链接跳转组件 navigator 组件相当于网页中的 a 标签&#xff0c;用来实现页面之间的跳转。 …

基于大数据的支付风险智能防控技术规范

随着大数据、移动互联、人工智能、生物特征识别等技术的快速发展&#xff0c;支付方式正在发生着巨大而深刻的变革&#xff0c;新技术在丰富支付手段、提高支付效率的同时&#xff0c;带来了新的隐患&#xff0c;也对从业机构的风险防控能力提出了更高的要求。 传统的风控技术…

机器学习--数学部分笔记

前言 因为周三要考试,所以数学部分写一下笔记 正文 随机事件和随机实验 条件概率 • 在已知事件 &#x1d435; 发生的条件下&#xff0c;事件&#x1d434;发生的概率称为事件 &#x1d434; 的条件概率&#xff0c;记为&#x1d443;(&#x1d434;|&#x1d435;) 全概率…

Java 解决 古典问题

1 问题 编写一个Java程序&#xff0c;解决以下问题&#xff1a; 2 方法 再导入java.util包下的Scanner类&#xff0c;构建Scanner对象&#xff0c;以便输入。通过对问题的分析&#xff0c;我们可以得到&#xff0c;当位数为1时&#xff0c;其返回值为1&#xff1b;当位数为2时&…

部署LAMP平台

目录 一、LAMP简介与概述 1.1 各组件作用 1.2 LAMP平台搭建时各组件安装顺序 1.3 httpd服务的目录结构 1.4 httpd.conf配置文件 二、编译安装Apache httpd服务 2.1 关闭防火墙&#xff0c;将安装Apache所需软件包传到/opt目录下 2.2 安装环境依赖包 ​2.3 配置软件模块…

浅论未来 IT 和财务结合的趋势

前言 会计核算企业各类业务单据&#xff0c;所有业务部门的数据都会汇流到财务部来&#xff0c;所以会计其实是企业的数据中心&#xff1b;而 IT 技术正是处理数据的利器&#xff0c;可以将重复的流程自动化&#xff0c;还能将财务数据可视化&#xff1b;因此&#xff0c;两者…

路由_传递params参数和query参数

传递params参数 传递params参数可以直接在路径后面加上参数&#xff1a; 上述就是在路径变化的时候传过去三个值分别为哈哈、嘿嘿、呵呵的参数 但是这样的话会被认为三个参数是路径的一部分&#xff0c;计算机没有办法区分哪些是路径哪些是参数&#xff0c;所以首先要在这条路…

练习题(2024/5/23)

1单词接龙 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk&#xff1a; 每一对相邻的单词只差一个字母。 对于 1 < i < k 时&#xff0c;每个 si 都在 wordList 中。注意&#…

继“三级淋巴结”之后,再看看“单细胞”如何与AI结合【医学AI|顶刊速递|05-25】

小罗碎碎念 24-05-25文献速递 今天想和大家分享的是肿瘤治疗领域的另一个热点——单细胞技术&#xff0c;我们一起来看看&#xff0c;最新出炉的顶刊&#xff0c;是如何把AI与单细胞结合起来的。 另外&#xff0c;今天是周末&#xff0c;所以会有两篇文章——一篇文献速递&…

CATO原理中的数学与魔术(十)——Parity Principle及其应用一:集合的基本性质...

在前面的文章中&#xff0c;我们介绍了CATO原理的数学模型以及两个经典的魔术应用系列&#xff1a;Baby Hummer和Royal Hummer&#xff0c;以及它们的拓展&#xff0c;详情请戳&#xff1a; 传送门 CATO原理中的数学与魔术&#xff08;九&#xff09;——Royal Hummer 及其进阶…

Vue.js - Vue 的安装 以及 常用的 Vue 指令 【0基础向 Vue 基础学习】

文章目录 Vue 快速上手1、Vue.js 官网 & Vue.js 的获取2、创建 Vue 实例&#xff0c;初始化渲染3、插值表达式 安装 Vue 开发者工具&#xff1a;装插件调试 Vue 应用Vue 指令1、v-show 指令2、v-if3、v-else & v-else-if4、v-onv-on 调用传参 5、v-bindv-bind 对于样式…

[数据结构] -- 单链表

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;C打怪之路&#xff0c;python从入门到精通&#xff0c;数据结构&#xff0c;C语言&#xff0c;C语言题集&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文(平均质量分82)&#…

订单id的设计问题探讨

如何设计一个订单id 设计一个订单ID系统需要考虑多个因素&#xff0c;包括唯一性、排序性&#xff08;时间顺序&#xff09;、可读性&#xff08;可选&#xff09;以及系统的扩展性和性能。结合这些因素&#xff0c;可以选择不同的方案来生成订单ID。以下是几种常见的订单ID设…

【Nodejs-多进程之Cluster】

cluster 模块是 Node.js 提供的一个用于多进程的模块&#xff0c;它可以轻松地创建一组共享同一个服务器端口的子进程&#xff08;worker进程&#xff09;。通过使用 cluster 模块&#xff0c;可以充分利用多核系统&#xff0c;提高应用程序的性能和可靠性。 基本原理 cluste…

文心智能体,零代码构建情感表达大师智能体

前言 随着智能体技术的突飞猛进&#xff0c;各行各业正迎来前所未有的变革与机遇。智能体&#xff0c;作为人工智能领域的重要分支&#xff0c;以其自主性、智能性和适应性&#xff0c;正逐步渗透到我们生活的每一个角落&#xff0c;成为推动社会进步和科技发展的新动力。 为了…