React Native height auto样式失效,连接线组件显示异常求助
问题描述
预期效果

实际效果

颜色显示正常,核心问题出在LineConnector连接线组件上。问题表现为:每次展开子项时,父组件的主连接线会断开,需要让它持续延伸至最后一个子项而不中断。要求在不安装第三方库的前提下解决。
可复用LineConnector组件代码
import React from "react"; import { StyleSheet, View } from "react-native"; type props ={ color:any; type:string; getParentDimensions?: any; } const LineConnector = ({color, type, getParentDimensions}:props) =>{ return (<> <View style= {{ borderWidth:0.5, backgroundColor: color, borderColor:color , zIndex:-2 , opacity:0.6, bottom:16.5, marginLeft: type === 'area' ? 45 : type == 'asset' ? 82 : 7, }} > </View> <View style={{ borderBottomColor: color, borderBottomWidth: 0.5, width:'5%', opacity:0.6, position:'relative', alignSelf:'center', marginRight:10, top:5 }}> <View style={{ height:4, width:4, backgroundColor:color, position:'absolute', right:0, borderRadius:100, top:-2 }}> </View> </View> </> ) }; export {LineConnector}
BoxLocations组件代码
import React, { useState } from 'react'; import { Pressable, StyleSheet, Text, View } from 'react-native'; import ChevronDown from '@assets/images/chevron_down.svg'; import CounterAssets from './CounterAssets'; import BoxGradientLayout,{stylesCommon} from './BoxGradientLayout'; import BoxAreas from './BoxAreas'; import { LineConnector } from './LineConnector'; type propsLocations = { colors: any; locations?: []; } const BoxLocations = ({colors,locations}:propsLocations) => { const [showAreas, setShowAreas] = useState<number>(-1); const styles = StyleSheet.create({ chevronDown:{ transform:[{rotate: showAreas ? '180deg' : '0deg'}] }, }); const showViewAreas = (index:number) =>{ if(index == showAreas){ setShowAreas(-1); }else{ setShowAreas(index) } } return ( <> {locations?.map((loc:any, index:number)=>( <React.Fragment key={loc.id}> <View style={{flexDirection:'row',display:'flex'}}> <LineConnector color={colors?.site} type='location' /> <BoxGradientLayout layoutType='location' colors={ colors?.location}> <Text style={stylesCommon.name}> {loc?.name} </Text> <CounterAssets count={loc?.assets_counter} /> </BoxGradientLayout> <View style={stylesCommon.containerChevron}> <Pressable onPress={() => showViewAreas(index)} style={({ pressed }) => [pressed ? stylesCommon.chevronDownPress : styles.chevronDown]}> <ChevronDown fill={ colors?.location} fillOpacity={'0.03'} stroke={ colors?.location} /> </Pressable> </View> </View> {showAreas == index ? ( <View style={stylesCommon.childrenBox}> <BoxAreas areas={loc.areas} colors={colors}/> </View> ) : null} </React.Fragment> ))} </> ); }
BoxLocations通用样式
export const stylesCommon = StyleSheet.create({ name:{ paddingLeft:20, right:5 }, containerChevron:{ top:5 , left:4, alignItems:'center', flexDirection:'row', elevation:5 }, chevronDownPress:{ opacity:0.4, }, childrenBox:{ flexDirection:'column', position:'relative', } })
渐变盒子样式
const styles = StyleSheet.create({ container:{ flexDirection:'row', }, containerGradient:{ height:33, width:'auto', marginTop:10, alignSelf:'flex-start', alignItems:'center', flexDirection:'row', backgroundColor: colors, borderRadius:10, borderWidth:1, borderColor: colors, elevation:5 }, icons:{ height:20, width:20, backgroundColor: colors, justifyContent:'center', alignItems:'center', borderRadius:100, left:4 } });
解决方案
问题根源在于当前LineConnector是独立挂载在每个父项的行内,高度固定无法跟随子项展开动态延伸。调整布局结构和连接线实现方式即可解决:
1. 重构布局结构
将每个Location项及其子项包裹在相对定位容器中,把主垂直连接线改为容器内的绝对定位元素,让它根据容器高度(含展开的子项)自动延伸。
修改BoxLocations的渲染逻辑:
{locations?.map((loc:any, index:number)=>( <View key={loc.id} style={{position: 'relative', marginBottom: 10}}> {/* 主垂直连接线 */} <View style={{ position: 'absolute', left: 7, // 和原type='location'的marginLeft一致 top: 0, bottom: 0, width: 0.5, backgroundColor: colors?.site, opacity: 0.6, zIndex: -2 }} /> {/* 父项行 */} <View style={{flexDirection:'row', display:'flex'}}> {/* 仅保留横向连接线和圆点 */} <View style={{ borderBottomColor: colors?.site, borderBottomWidth: 0.5, width:'5%', opacity:0.6, position:'relative', alignSelf:'center', marginRight:10, top:5 }}> <View style={{ height:4, width:4, backgroundColor: colors?.site, position:'absolute', right:0, borderRadius:100, top:-2 }}> </View> </View> <BoxGradientLayout layoutType='location' colors={ colors?.location}> <Text style={stylesCommon.name}> {loc?.name} </Text> <CounterAssets count={loc?.assets_counter} /> </BoxGradientLayout> <View style={stylesCommon.containerChevron}> <Pressable onPress={() => showViewAreas(index)} style={({ pressed }) => [pressed ? stylesCommon.chevronDownPress : styles.chevronDown]}> <ChevronDown fill={ colors?.location} fillOpacity={'0.03'} stroke={ colors?.location} /> </Pressable> </View> </View> {/* 子项区域 */} {showAreas == index ? ( <View style={stylesCommon.childrenBox}> <BoxAreas areas={loc.areas} colors={colors}/> </View> ) : null} </View> ))}
2. 优化LineConnector复用性(可选)
如果要保留组件复用性,修改LineConnector逻辑,根据需求渲染垂直/水平连接线:
import React from "react"; import { View } from "react-native"; type props ={ color:any; type:string; isVerticalLine?: boolean; } const LineConnector = ({color, type, isVerticalLine}:props) =>{ const horizontalLine = ( <View style={{ borderBottomColor: color, borderBottomWidth: 0.5, width:'5%', opacity:0.6, position:'relative', alignSelf:'center', marginRight:10, top:5 }}> <View style={{ height:4, width:4, backgroundColor:color, position:'absolute', right:0, borderRadius:100, top:-2 }}> </View> </View> ); const verticalLine = ( <View style={{ position: 'absolute', left: type === 'area' ? 45 : type == 'asset' ? 82 : 7, top: 0, bottom: 0, width: 0.5, backgroundColor: color, opacity: 0.6, zIndex: -2 }} /> ); return ( <> {isVerticalLine ? verticalLine : horizontalLine} </> ) }; export {LineConnector}
在BoxLocations中使用优化后的组件:
<View key={loc.id} style={{position: 'relative', marginBottom: 10}}> <LineConnector color={colors?.site} type='location' isVerticalLine={true} /> <View style={{flexDirection:'row', display:'flex'}}> <LineConnector color={colors?.site} type='location' /> {/* 其余父项内容不变 */} </View> {/* 子项区域不变 */} </View>
3. 子项连接线适配
确保子项(BoxAreas)中的LineConnector也采用绝对定位逻辑,让子项连接线与父项垂直长线对齐,保持视觉连贯性。
调整后,父项垂直连接线会随容器高度自动延伸,不会再出现断开问题,完全匹配预期效果。
内容的提问来源于stack exchange,提问作者Guido Gagliardini
相关产品推荐
相关产品推荐

