Flutter Web:当Row组件将溢出时显示"+X"按钮
检测Row组件溢出并实现"+X"折叠效果
核心思路
通过对比Row容器的可视宽度和内部所有子元素的总宽度,判断是否溢出;若溢出则逐步隐藏子元素,同时统计隐藏数量并显示"+X"按钮。
具体实现步骤(以React为例)
- 获取DOM元素引用
给Row容器和子元素都添加ref,方便后续获取尺寸信息:
import { useRef, useEffect, useState } from 'react'; function CollapsibleRow({ items }) { const rowRef = useRef(null); const itemRefs = useRef([]); const [hiddenCount, setHiddenCount] = useState(0); // 后续逻辑写在这里 }
- 计算溢出状态
在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]);
- 渲染"+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
相关产品推荐
相关产品推荐

