You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter实现点击拖拽时在两盒子间扩展元素且不超边界

Flutter实现受限的中间元素扩展功能

需求效果参考:
拖动扩展效果

核心实现思路

  • 用StatefulWidget维护中间元素的高度状态
  • 通过GestureDetector监听长按触发扩展,拖动手势调整高度
  • 限制中间元素的高度范围,确保始终在上下两个盒子的边界内

完整代码示例

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('受限扩展示例')),
        body: const LimitedExpandableArea(),
      ),
    );
  }
}

class LimitedExpandableArea extends StatefulWidget {
  const LimitedExpandableArea({super.key});

  @override
  State<LimitedExpandableArea> createState() => _LimitedExpandableAreaState();
}

class _LimitedExpandableAreaState extends State<LimitedExpandableArea> {
  // 上下盒子的固定高度
  final double _topBoxHeight = 100;
  // 中间元素的当前高度,初始为最小高度
  double _middleHeight = 50;
  // 中间元素的最小/最大高度(基于屏幕高度计算)
  late double _minMiddleHeight;
  late double _maxMiddleHeight;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // 计算屏幕可用高度,减去顶部盒子高度后,剩余空间为中间+底部盒子的总高度
    final screenHeight = MediaQuery.of(context).size.height -
        AppBar().preferredSize.height -
        MediaQuery.of(context).padding.top -
        MediaQuery.of(context).padding.bottom;
    _minMiddleHeight = 50;
    _maxMiddleHeight = screenHeight - _topBoxHeight;
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // 顶部固定盒子
        Container(
          height: _topBoxHeight,
          color: Colors.blue,
          alignment: Alignment.center,
          child: const Text('顶部盒子'),
        ),
        // 可扩展的中间元素,用GestureDetector监听手势
        GestureDetector(
          // 长按开始触发初始扩展
          onLongPressDown: (_) {
            setState(() {
              // 长按后先扩展到一个初始高度(也可直接进入拖动调整)
              _middleHeight = _minMiddleHeight + 50;
            });
          },
          // 拖动时调整高度
          onVerticalDragUpdate: (details) {
            setState(() {
              // 根据拖动方向调整高度,同时限制在最小/最大范围内
              _middleHeight = (_middleHeight + details.delta.dy).clamp(
                _minMiddleHeight,
                _maxMiddleHeight,
              );
            });
          },
          child: Container(
            height: _middleHeight,
            color: Colors.orange,
            alignment: Alignment.center,
            child: const Text('拖动调整高度'),
          ),
        ),
        // 底部固定盒子(自动占据剩余空间)
        Expanded(
          child: Container(
            color: Colors.green,
            alignment: Alignment.center,
            child: const Text('底部盒子'),
          ),
        ),
      ],
    );
  }
}

关键细节说明

  • 高度限制:通过clamp()方法强制中间元素高度在_minMiddleHeight和_maxMiddleHeight之间,彻底避免超出上下盒子的边界
  • 手势逻辑:onLongPressDown触发初始扩展动作,onVerticalDragUpdate响应拖动实时调整高度,完全匹配“按住点击后扩展+拖动调整”的需求
  • 自适应适配:在didChangeDependencies中动态计算屏幕可用高度,确保在不同尺寸的设备上都能正确限制扩展范围

内容的提问来源于stack exchange,提问作者Doublon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 05:25:16