Flutter系列文章-Flutter UI进阶

news2025/4/25 2:58:57

在本篇文章中,我们将深入学习 Flutter UI 的进阶技巧,涵盖了布局原理、动画实现、自定义绘图和效果、以及 Material 和 Cupertino 组件库的使用。通过实例演示,你将更加了解如何创建复杂、令人印象深刻的用户界面。

第一部分:深入理解布局原理

1. 灵活运用 Row 和 Column

Row 和 Column 是常用的布局组件,但灵活地使用它们可以带来不同的布局效果。例如,使用 mainAxisAlignment 和 crossAxisAlignment 可以控制子组件在主轴和交叉轴上的对齐方式。

Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: [
    Container(width: 50, height: 50, color: Colors.red),
    Container(width: 50, height: 50, color: Colors.green),
    Container(width: 50, height: 50, color: Colors.blue),
  ],
)

2. 弹性布局 Flex 和 Expanded

Flex 和 Expanded 可以用于实现弹性布局,让组件占据可用空间的比例。例如,下面的代码将一个蓝色容器占据两倍宽度的空间。

Row(
  children: [
    Container(width: 50, height: 50, color: Colors.red),
    Expanded(
      flex: 2,
      child: Container(height: 50, color: Colors.blue),
    ),
  ],
)

第二部分:动画和动效实现

1. 使用 AnimatedContainer

AnimatedContainer 可以实现在属性变化时自动产生过渡动画效果。例如,以下代码在点击时改变容器的宽度和颜色。

class AnimatedContainerExample extends StatefulWidget {
  @override
  _AnimatedContainerExampleState createState() => _AnimatedContainerExampleState();
}

class _AnimatedContainerExampleState extends State<AnimatedContainerExample> {
  double _width = 100;
  Color _color = Colors.blue;

  void _animateContainer() {
    setState(() {
      _width = _width == 100 ? 200 : 100;
      _color = _color == Colors.blue ? Colors.red : Colors.blue;
    });
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _animateContainer,
      child: AnimatedContainer(
        width: _width,
        height: 100,
        color: _color,
        duration: Duration(seconds: 1),
        curve: Curves.easeInOut,
      ),
    );
  }
}

2. 使用 Hero 动画

Hero 动画可以在页面切换时产生平滑的过渡效果。在不同页面中使用相同的 tag,可以让两个页面之间的共享元素过渡更加自然。

class PageA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        Navigator.of(context).push(MaterialPageRoute(
          builder: (context) => PageB(),
        ));
      },
      child: Hero(
        tag: 'avatar',
        child: CircleAvatar(
          radius: 50,
          backgroundImage: AssetImage('assets/avatar.jpg'),
        ),
      ),
    );
  }
}

class PageB extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Hero(
          tag: 'avatar',
          child: CircleAvatar(
            radius: 150,
            backgroundImage: AssetImage('assets/avatar.jpg'),
          ),
        ),
      ),
    );
  }
}

第三部分:自定义绘图和效果

1. 使用 CustomPaint 绘制图形

CustomPaint 允许你自定义绘制各种图形和效果。以下是一个简单的例子,绘制一个带边框的矩形。

class CustomPaintExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: RectanglePainter(),
      child: Container(),
    );
  }
}

class RectanglePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.blue
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2;

    canvas.drawRect(Rect.fromLTWH(50, 50, 200, 100), paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}

第四部分:Material 和 Cupertino 组件库

1. 使用 Material 组件

Material 组件库提供了一系列符合 Material Design 规范的 UI 组件。例如,AppBar、Button、Card 等。以下是一个使用 Card 的例子。

Card(
  elevation: 4,
  child: ListTile(
    leading: Icon(Icons.account_circle),
    title: Text('John Doe'),
    subtitle: Text('Software Engineer'),
    trailing: Icon(Icons.more_vert),
  ),
)

2. 使用 Cupertino 组件

Cupertino 组件库提供了 iOS 风格的 UI 组件,适用于 Flutter 应用在 iOS 平台上的开发。例如,CupertinoNavigationBar、CupertinoButton 等。

dart
Copy code
CupertinoNavigationBar(
middle: Text(‘Cupertino Example’),
trailing: CupertinoButton(
child: Text(‘Done’),
onPressed: () {},
),
)

第五部分:综合实例

以下是一个更加综合的例子,涵盖了之前提到的布局、动画、自定义绘图和 Material/Cupertino 组件库的知识点。

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ExampleScreen(),
    );
  }
}

class ExampleScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Advanced UI Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            AnimatedRotateExample(),
            SizedBox(height: 20),
            CustomPaintExample(),
            SizedBox(height: 20),
            PlatformWidgetsExample(),
          ],
        ),
      ),
    );
  }
}

class AnimatedRotateExample extends StatefulWidget {
  @override
  _AnimatedRotateExampleState createState() => _AnimatedRotateExampleState();
}

class _AnimatedRotateExampleState extends State<AnimatedRotateExample> {
  double _rotation = 0;

  void _startRotation() {
    Future.delayed(Duration(seconds: 1), () {
      setState(() {
        _rotation = 45;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        GestureDetector(
          onTap: () {
            _startRotation();
          },
          child: AnimatedBuilder(
            animation: Tween<double>(begin: 0, end: _rotation).animate(
              CurvedAnimation(
                parent: ModalRoute.of(context)!.animation!,
                curve: Curves.easeInOut,
              ),
            ),
            builder: (context, child) {
              return Transform.rotate(
                angle: _rotation * 3.1416 / 180,
                child: child,
              );
            },
            child: Container(
              width: 100,
              height: 100,
              color: Colors.blue,
              child: Icon(
                Icons.star,
                color: Colors.white,
              ),
            ),
          ),
        ),
        Text('Tap to rotate'),
      ],
    );
  }
}

class CustomPaintExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: CirclePainter(),
      child: Container(
        width: 200,
        height: 200,
        alignment: Alignment.center,
        child: Text(
          'Custom Paint',
          style: TextStyle(color: Colors.white, fontSize: 18),
        ),
      ),
    );
  }
}

class CirclePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final center = Offset(size.width / 2, size.height / 2);
    final radius = size.width / 2;
    final paint = Paint()
      ..color = Colors.orange
      ..style = PaintingStyle.fill;

    canvas.drawCircle(center, radius, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return false;
  }
}

class PlatformWidgetsExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Material(
          elevation: 4,
          child: ListTile(
            leading: Icon(Icons.account_circle),
            title: Text('John Doe'),
            subtitle: Text('Software Engineer'),
            trailing: Icon(Icons.more_vert),
          ),
        ),
        SizedBox(height: 20),
        CupertinoButton.filled(
          child: Text('Explore'),
          onPressed: () {},
        ),
      ],
    );
  }
}

这个示例演示了一个综合性的界面,包括点击旋转动画、自定义绘图和 Material/Cupertino 组件。你可以在此基础上进一步扩展和修改,以满足更复杂的 UI 设计需求。

总结

在本篇文章中,我们深入学习了 Flutter UI 的进阶技巧。我们了解了布局原理、动画实现、自定义绘图和效果,以及 Material 和 Cupertino 组件库的使用。通过实例演示,你将能够更加自信地构建复杂、令人印象深刻的用户界面。

希望这篇文章能够帮助你在 Flutter UI 进阶方面取得更大的进展。如果你有任何问题或需要进一步的指导,请随时向我询问。祝你在 Flutter 开发的道路上取得成功!

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

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

相关文章

三维模型OSGB格式轻量化压缩必要性分析

三维模型OSGB格式轻量化压缩必要性分析 三维模型是计算机图形学和视觉效果等领域的重要应用之一。然而&#xff0c;由于三维模型通常包含大量的几何信息、纹理信息和其他元素&#xff0c;导致其占用的存储空间和计算资源非常巨大。为了提高三维模型的处理效率和性能&#xff0…

C#实现邮箱验证码

开发环境&#xff1a;C#&#xff0c;VS2019&#xff0c;.NET Core 3.1&#xff0c;ASP.NET Core Web API&#xff0c;163邮箱 1、在163邮箱的设置中开通IMAP/SMTP的服务&#xff0c;授权成功后会弹出一个窗体&#xff08;如下图所示&#xff09;&#xff0c;上面显示了授权密码…

go重制版的海盗王gateserver网关服务端

海盗王原有的gateserver网关经常出现无故报错和掉地图的问题&#xff0c;经过反复修改都无法解决相关问题。 加上&#xff0c;原有的程序已经趋于古董级别&#xff0c;存在很大的兼容性问题。 以上&#xff0c;萌发了用go语言进行重新开发一个gateserver网关程序的想法&#xf…

科技巨头纷纷押注,Web3钱包能否成为撬动行业的支点?

出品&#xff5c;欧科云链研究院 作者&#xff5c;Hedy Bi 在PayPal推出稳定币并引发行业热议之际&#xff0c;公链Aptos昨日宣布与微软合作&#xff0c;共同探索与资产代币化、数字支付和中央银行数字货币相关的创新解决方案。尽管比尔盖茨对加密货币持摇摆态度&#xff0c;…

[小尘送书-第二期]《Power BI数据分析与可视化实战》数据清洗、数据建模、数据可视化设计与高级技法

大家好&#xff0c;我是小尘&#xff0c;欢迎你的关注&#xff01;大家可以一起交流学习&#xff01;欢迎大家在CSDN后台私信我&#xff01;一起讨论学习&#xff0c;讨论如何找到满意的工作&#xff01; &#x1f468;‍&#x1f4bb;博主主页&#xff1a;小尘要自信 &#x1…

F7--DDR4的读写测试-2023-08-11

1.场景 7系列的FPGA芯片不支持DDR4&#xff0c;使用DDR4需要更高性能的FPGA芯片&#xff0c;这里用到Kintex ultrascale是支持DDR4的&#xff0c;具体FPGA芯片是XCKU3P-2FFVA676I&#xff0c;DDR4的颗粒为MT40A512M16LY- 075E时钟频率为750MHz-1333MHz&#xff0c;单颗容量为1G…

JVM运行时五大数据区域详解

前言&#xff1a; java虚拟机再执行Java程序的时候把它所拥有的内存区域划分了若干个数据区域。这些区域有着不同的功能&#xff0c;各司其职。这些区域不但功能不同&#xff0c;创建、销毁时间也不同。有些区域为线程私有&#xff0c;如&#xff1a;每个线程都有自己的程序计数…

腾讯云CVM服务器端口在安全组中打开!

腾讯云服务器CVM端口怎么开通&#xff1f;腾讯云服务器端口是通过配置安全组规则来开通的&#xff0c;腾讯云服务器网以开通80端口为例来详细说下腾讯云轻量应用服务器开启端口的方法&#xff0c;其他的端口的开通如8080、1433、443、3306、8888等端口也适用于此方法&#xff0…

5v升9v升压电路

5v升9v升压电路 现在市场上有许多电子设备需要提供不同电压的供电能力。其中&#xff0c;升压电路是一种常见的电路类型&#xff0c;可以将低电压升高到所需要的电压水平。在本文中&#xff0c;我们将介绍一种5V升9V的升压电路方案&#xff0c;该方案具有以下特点&#xff1a;…

新知识:Monkey 改进版之 App Crawler

原生Monkey 大家知道Monkey是Android平台上进行压力稳定性测试的工具&#xff0c;通过Monkey可以模拟用户触摸屏幕、滑动、按键等伪随机用户事件来对设备上的程序进行压力测试。而原生的Android Monkey存在一些缺陷&#xff1a; 事件太过于随机&#xff0c;测试有效性大打折扣…

深入理解 python 虚拟机:字节码教程——深入剖析循环实现原理

在本篇文章当中主要给大家介绍 cpython 当中跟循环相关的字节码&#xff0c;这部分字节码相比起其他字节码来说相对复杂一点&#xff0c;通过分析这部分字节码我们对程序的执行过程将会有更加深刻的理解。 循环 普通 for 循环实现原理 我们使用各种例子来理解和循环相关的字…

flutter 初识(开发体验,优缺点)

前言 最近有个跨平台桌面应用的需求&#xff0c;需要支持 windows/linux/mac 系统&#xff0c;要做个更新应用的小界面&#xff0c;主要功能就是下载更新文件并在本地进行替换&#xff0c;很简单的小功能。 花了几分钟构建没做 UI 优化的示例界面&#xff1a; 由于我们的客…

数据分析两件套ClickHouse+Metabase(二)

Metabase篇 Metabase安装部署 任何问题请查看 -> 官方文档 jar包从GitHub下载 -> 地址 同样有个问题, 默认数据源里没有ClickHouse, 不过ClickHouse官方提供了插件包 -> 插件包 在安装metabase目录下新建一个plugins文件夹, 把下载的clickhouse.metabase-driver.ja…

JavaSpring加载properties文件

手动加载 #properties文件 jdbc.driver1 <?xml version"1.0" encoding"UTF-8"?> <!-- 开启context命名空间--> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XM…

glove安装中的问题

万恶之源&#xff1a; >>> from glove import Glove Traceback (most recent call last):File "<stdin>", line 1, in <module>File "D:\code_related_software\Anaconda\lib\site-packages\glove\__init__.py", line 1, in <mod…

详解C语言函数:深入了解函数的使用和特性

目录 引言 一、函数的概念 1.1 函数关键特点 1.2 函数的组成部分 1.3 函数声明和定义格式 二、函数分类 2.1 库函数 使用库函数的步骤 2.2 自定义函数 创建自定义函数的步骤 三、函数的参数类型 3.1 形式参数&#xff08;形参&#xff09;&#xff1a; 格式&#x…

【碎碎念随笔】1、回顾我的电脑和编程经历

✏️ 闲着无事&#xff0c;讲述一下我的计算机和代码故事 一、初识计算机 &#x1f5a5;️ 余家贫&#xff0c;耕植无钱买电脑。大约六年级暑假&#xff0c;我在姐姐哪儿第一次接触到了计算机&#xff08;姐姐也是买的二手&#xff09;。 &#x1f5a5;️ 计算机真有趣&#x…

如何投诉删除360搜索下拉词?

有的企业发现自己品牌在360搜索下拉框里会展现出来一些负面词&#xff0c;如骗子、跑路、倒闭等&#xff0c;有企业咨询能不能删除360搜索下拉里的负面词&#xff1f;小马识途营销顾问分析要看具体情况&#xff0c;按经验如果是涉及诋毁诽谤的词&#xff0c;投诉到平台能够删除…

检测新突破 | AlignDet:支持各类检测器自监督新框架(ICCV2023)

引言 论文链接&#xff1a;https://arxiv.org/abs/2307.11077 项目地址&#xff1a;https://github.com/liming-ai/AlignDet 这篇论文主要研究目标检测领域的自监督预训练方法。作者首先指出&#xff0c;当前主流的预训练-微调框架在预训练和微调阶段存在数据、模型和任务上的…

Kafka的下载和安装

一、Kafka下载和安装 下载地址&#xff1a;https://kafka.apache.org/downloads 下载完毕解压即可 linux解压命令tar -zxvf kafka_2.13-3.5.1.tgz&#xff0c;linux环境下指令是在\kafka_2.13-3.5.1\bin目录。 windows直接解压即可&#xff0c;windows环境下指令是在kafka_2.…