Flutter UI 组件应用一:布局、交互、动画与弹窗

以下是 Flutter UI 组件高级应用的详细教学,包含代码示例和关键概念说明:


一、高级布局技巧

1. 复杂布局组合

dart 复制代码
Scaffold(
  body: Column(
    children: [
      // 顶部导航栏
      Container(height: 50, color: Colors.blue),
      // 主内容区域
      Expanded(
        child: Row(
          children: [
            // 侧边栏
            Container(width: 100, color: Colors.grey[200]),
            // 内容区
            Expanded(
              child: Stack(
                children: [
                  ListView.builder(
                    itemCount: 20,
                    itemBuilder: (ctx, i) => ListTile(title: Text('Item $i')),
                  ),
                  Positioned(
                    bottom: 20,
                    right: 20,
                    child: FloatingActionButton(onPressed: () {}),
                  )
                ],
              ),
            ),
          ],
        ),
      ),
    ],
  ),
  bottomNavigationBar: BottomNavigationBar(
    items: [/*...*/],
  ),
)

2. 响应式布局

dart 复制代码
LayoutBuilder(
  builder: (context, constraints) {
    if (constraints.maxWidth > 600) {
      return _buildWideLayout();
    } else {
      return _buildMobileLayout();
    }
  },
)

二、事件处理进阶

1. 手势识别

dart 复制代码
GestureDetector(
  onTap: () => print('Tapped'),
  onDoubleTap: () => print('Double tapped'),
  onLongPress: () => showDialog(/*...*/),
  onVerticalDragUpdate: (details) {
    // 处理垂直滑动
  },
  child: Container(color: Colors.amber),
)

2. 自定义手势冲突处理

dart 复制代码
RawGestureDetector(
  gestures: {
    AllowMultipleGestureRecognizer: 
      GestureRecognizerFactoryWithHandlers<AllowMultipleGestureRecognizer>(
        () => AllowMultipleGestureRecognizer(),
        (instance) {
          instance.onTap = () => print('允许同时识别多个手势');
        },
      ),
  },
  child: Text('多手势支持'),
)

三、动画实现

1. 隐式动画

dart 复制代码
AnimatedContainer(
  duration: Duration(seconds: 1),
  width: _selected ? 200 : 100,
  height: _selected ? 100 : 200,
  decoration: BoxDecoration(
    color: _selected ? Colors.red : Colors.blue,
    borderRadius: BorderRadius.circular(_selected ? 20 : 0),
  ),
)

2. 显式动画

dart 复制代码
class _AnimatedLogoState extends State<AnimatedLogo> 
    with SingleTickerProviderStateMixin {
    
  late AnimationController _controller;
  late Animation<Offset> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: Duration(seconds: 2),
    )..repeat(reverse: true);
    
    _animation = Tween<Offset>(
      begin: Offset.zero,
      end: Offset(0, 0.5),
    ).animate(CurvedAnimation(
      parent: _controller,
      curve: Curves.easeInOut,
    ));
  }

  @override
  Widget build(BuildContext context) {
    return SlideTransition(
      position: _animation,
      child: FlutterLogo(size: 100),
    );
  }
}

四、弹窗实现

1. 标准弹窗

dart 复制代码
showDialog(
  context: context,
  builder: (context) => AlertDialog(
    title: Text('提示'),
    content: Text('确定要删除吗?'),
    actions: [
      TextButton(
        onPressed: () => Navigator.pop(context),
        child: Text('取消'),
      ),
      TextButton(
        onPressed: () {
          // 执行删除操作
          Navigator.pop(context);
        },
        child: Text('确定'),
      ),
    ],
  ),
);

2. 自定义弹窗

dart 复制代码
void showCustomDialog(BuildContext context) {
  showGeneralDialog(
    context: context,
    pageBuilder: (_, __, ___) => Center(
      child: Material(
        child: Container(
          width: 300,
          height: 400,
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(20),
          child: Column(
            children: [
              // 自定义内容
              Expanded(child: ListView(...)),
              ElevatedButton(
                onPressed: () => Navigator.pop(context),
                child: Text('关闭'),
              )
            ],
          ),
        ),
      ),
    ),
    transitionBuilder: (_, anim, __, child) {
      return ScaleTransition(
        scale: anim,
        child: child,
      );
    },
  );
}

五、综合示例:带动画的交互界面

dart 复制代码
class InteractiveList extends StatefulWidget {
  @override
  _InteractiveListState createState() => _InteractiveListState();
}

class _InteractiveListState extends State<InteractiveList> {
  final List<String> _items = [];
  bool _showAddButton = true;

  void _addItem() {
    setState(() {
      _items.insert(0, 'Item ${_items.length + 1}');
    });
  }

  void _showAddDialog() {
    showDialog(
      context: context,
      builder: (ctx) => AlertDialog(
        content: TextField(
          autofocus: true,
          decoration: InputDecoration(hintText: '输入新项目'),
          onSubmitted: (text) {
            _addItem();
            Navigator.pop(ctx);
          },
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: AnimatedOpacity(
        duration: Duration(milliseconds: 300),
        opacity: _showAddButton ? 1 : 0,
        child: FloatingActionButton(
          onPressed: _showAddDialog,
          child: Icon(Icons.add),
        ),
      ),
      body: NotificationListener<ScrollNotification>(
        onNotification: (notification) {
          if (notification is ScrollUpdateNotification) {
            setState(() {
              _showAddButton = notification.metrics.pixels < 100;
            });
          }
          return true;
        },
        child: AnimatedList(
          initialItemCount: _items.length,
          itemBuilder: (context, index, animation) {
            return SizeTransition(
              sizeFactor: animation,
              child: ListTile(
                title: Text(_items[index]),
                trailing: IconButton(
                  icon: Icon(Icons.delete),
                  onPressed: () => setState(() => _items.removeAt(index)),
                ),
              ),
            );
          },
        ),
      ),
    );
  }
}

关键点说明:

  1. 布局嵌套:通过合理组合Row/Column/Stack/Expanded实现复杂布局
  2. 响应式设计:使用LayoutBuilder和MediaQuery适配不同屏幕
  3. 手势控制:区分不同手势类型并处理冲突
  4. 动画优化
    • 使用AnimatedWidget分离动画逻辑
    • 注意控制器dispose
    • 优先使用隐式动画简化代码
  5. 弹窗最佳实践
    • 通过Context正确管理弹窗层级
    • 使用Hero动画实现跨页面过渡
    • 自定义弹窗时注意圆角和阴影效果
相关推荐
于慨2 小时前
flutter基础组件用法
开发语言·javascript·flutter
恋猫de小郭4 小时前
Android CLI ,谷歌为 Android 开发者专研的 AI Agent,提速三倍
android·前端·flutter
火柴就是我5 小时前
flutter pushAndRemoveUntil 的一次小疑惑
flutter
于慨6 小时前
flutter doctor问题解决
flutter
唔666 小时前
flutter 图片加载类 图片的安全使用
安全·flutter
Nathan202406167 小时前
Flutter - InheritedWidget
flutter·dart
恋猫de小郭7 小时前
JetBrains Amper 0.10 ,期待它未来替代 Gradle
android·前端·flutter
Lanren的编程日记8 小时前
Flutter鸿蒙应用开发:实时聊天功能集成实战
flutter·华为·harmonyos
Utopia^18 小时前
鸿蒙flutter第三方库适配 - 联系人备份工具
flutter·华为·harmonyos
念格1 天前
Flutter 仿微信输入框最佳实践:自适应高度 + 超行数智能切换全屏
前端·flutter