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

Flutter Web:当Row组件将溢出时显示"+X"按钮

检测Row组件溢出并实现"+X"折叠效果

核心思路

通过对比Row容器的可视宽度和内部所有子元素的总宽度,判断是否溢出;若溢出则逐步隐藏子元素,同时统计隐藏数量并显示"+X"按钮。

具体实现步骤(以React为例)

  1. 获取DOM元素引用
    给Row容器和子元素都添加ref,方便后续获取尺寸信息:
import { useRef, useEffect, useState } from 'react';

function CollapsibleRow({ items }) {
  const rowRef = useRef(null);
  const itemRefs = useRef([]);
  const [hiddenCount, setHiddenCount] = useState(0);

  // 后续逻辑写在这里
}
  1. 计算溢出状态
    在useEffect中监听容器尺寸变化(比如窗口 resize、子元素动态更新),计算总宽度:
useEffect(() => {
  const checkOverflow = () => {
    if (!rowRef.current) return;
    const rowWidth = rowRef.current.clientWidth;
    let totalItemWidth = 0;
    const visibleItemIndexes = [];
    let hiddenNum = 0;

    // 遍历子元素,累加宽度直到超过容器(预留"+X"按钮宽度,约40px)
    itemRefs.current.forEach((item, index) => {
      if (!item) return;
      if (totalItemWidth + item.offsetWidth <= rowWidth - 40) {
        totalItemWidth += item.offsetWidth;
        visibleItemIndexes.push(index);
      } else {
        hiddenNum++;
      }
    });

    // 更新隐藏数量,控制元素显示/隐藏
    setHiddenCount(hiddenNum);
    itemRefs.current.forEach((item, index) => {
      if (item) {
        item.style.display = visibleItemIndexes.includes(index) ? 'inline-block' : 'none';
      }
    });
  };

  // 防抖优化,避免resize时频繁计算
  const debounce = (func, delay) => {
    let timer;
    return (...args) => {
      clearTimeout(timer);
      timer = setTimeout(() => func.apply(this, args), 100);
    };
  };
  const debouncedCheck = debounce(checkOverflow, 100);

  checkOverflow();
  window.addEventListener('resize', debouncedCheck);
  return () => window.removeEventListener('resize', debouncedCheck);
}, [items]);
  1. 渲染"+X"按钮
    根据hiddenCount的值决定是否显示按钮,点击按钮可按需展开所有元素:
return (
  <div 
    ref={rowRef} 
    style={{ 
      display: 'flex', 
      flexWrap: 'nowrap', 
      overflow: 'hidden',
      gap: '8px',
      padding: '4px 8px'
    }}
  >
    {items.map((item, index) => (
      <div
        key={index}
        ref={(el) => (itemRefs.current[index] = el)}
        style={{ 
          whiteSpace: 'nowrap',
          padding: '4px 12px',
          border: '1px solid #eee',
          borderRadius: '4px'
        }}
      >
        {item}
      </div>
    ))}
    {hiddenCount > 0 && (
      <button 
        style={{ 
          whiteSpace: 'nowrap',
          padding: '4px 12px',
          border: '1px solid #eee',
          borderRadius: '4px',
          cursor: 'pointer'
        }}
        onClick={() => {
          // 点击展开逻辑:显示所有元素,隐藏按钮
          itemRefs.current.forEach(item => {
            if (item) item.style.display = 'inline-block';
          });
          setHiddenCount(0);
        }}
      >
        +{hiddenCount}
      </button>
    )}
  </div>
);

注意事项

  • 若使用UI框架的Row组件(如Ant Design的Row),需确保容器的overflow设为hidden,且子元素不自动换行
  • 动态加载子元素时,要将子元素列表加入useEffect的依赖项,确保数据更新后重新检测溢出
  • 不同场景下"+X"按钮的宽度可能不同,需根据实际样式调整预留宽度值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 19:30:43