我正在尝试在 React Native 中重新创建 html 表功能,但我无法弄清楚这一点。
我有 1 列用于项目名称(短),另一列用于项目描述(可能很长)。
我希望第一列只占用所需的空间,第二列可以弯曲,然后在空间不足时自动换行。这部分很简单,但是第一列中的项目都有不同的宽度。如果我首先制作列来解决这个问题,那么让第一列中的相应项目垂直弯曲以保持对齐就会让我绊倒。 HTML 表格可以毫不费力地做到这一点。为什么 Native 这么难?
真的没有办法用这种语言做一个真正灵活的表格吗?
我已经尝试了不同的 Flex 变体,但是 我不希望它成为任一列的固定宽度或比例,因为我想稍后保留字体大小的选项,这会破坏它。
react-native-paper
失败,因为 DataTable.Cell
不允许多行,并且添加功能会扰乱对齐,让我回到开始的地方。
编辑:在html中,我会这样做:
<html>
<head>
<style>
td:first-child {white-space: nowrap; }
</style>
</head>
<body>
<table>
<tr>
<td>
I am some data!
</td>
<td>
Two households, both alike in dignity, in fair Verona, where we lay our scene, from ancient grudge break to new mutiny, where civil blood makes civil hands unclean.
</td>
</tr>
<tr>
<td>
I'm data too!
</td>
<td>
From forth the fatal loins of these two foes, a pair of star-cross'd lovers take their life; whose misadventured piteous overthrows do with their death bury their parents' strife.
</td>
</tr>
<tr>
<td>
I am also some data!
</td>
<td>
The fearful passage of their death-mark'd love, and the continuance of their parents' rage, which, but their children's end, nought could remove, is now the two hours' traffic of our stage; the which if you with patient ears attend, what here shall miss, our toil shall strive to mend.
</td>
</tr>
</table>
</body>
</html>
结果:
您可以创建一个名为
Table
的组件(代表表格本身)和一个名为 TableRow
的组件(代表表格的一行)。
import React from 'react';
import { View } from 'react-native';
import TableRow from './TableRow';
const Table = () => (
<View style={{ flexDirection: 'column' }}>
<TableRow itemName="Item 1" itemDescription="Description for item 1" />
<TableRow itemName="Item 2" itemDescription="Description for item 2" />
<TableRow itemName="Item 3" itemDescription="Description for item 3" />
</View>
);
export default Table;
和
import React from 'react';
import { View, Text } from 'react-native';
const TableRow = ({ itemName, itemDescription }) => (
<View style={{ flexDirection: 'row' }}>
<View style={{ width: 'auto', alignItems: 'flex-start' }}>
<Text>{itemName}</Text>
</View>
<View style={{ flex: 3, alignItems: 'flex-start' }}>
<Text>{itemDescription}</Text>
</View>
</View>
);
export default TableRow;
在我看来,使用
flex: 1
而不是 width: 'auto'
看起来更好,但我当然不知道你的先决条件是什么。
要使用数据填充表格,您需要向表格组件传递一个项目数组。为此,请修改 Table 组件
import React from 'react';
import { View } from 'react-native';
import TableRow from './TableRow';
const Table = ({ items }) => (
<View style={{ flexDirection: 'column' }}>
{items.map(item => (
<TableRow
key={item.name}
itemName={item.name}
itemDescription={item.description}
/>
))}
</View>
);
export default Table;
现在您可以执行以下操作:
import React from 'react';
import Table from './Table';
const items = [
{ name: 'Item 1', description: 'Description for item 1' },
{ name: 'Item 2', description: 'Description for item 2' },
{ name: 'Item 3', description: 'Description for item 3' },
];
const App = () => (
<Table items={items} />
);
export default App;
这将用数据填充您的表格。
好吧,我想我已经得到了我想要的功能。可能有一种更可扩展的方法来做到这一点,这可能效率极低,但它似乎有效。
要点是我可以使用状态变量来存储每个单元格所需的宽度,然后在
onLayout
中,我可以在布局更改时调用 setColWidth
来更新该变量。然后,我可以使用 style 将最小宽度设置为最大单元格的宽度。
然后有一个数组,用于确定给定列是否缩小以为其他列留出空间。
最后,我可以在父级
alignItems
中调用 View
将表收缩到适合数据的最小大小
import React, {useState} from 'react';
import {LayoutChangeEvent, useWindowDimensions, View} from 'react-native';
const Table = ({
data,
rowStyle = undefined,
priviledge = new Array(data.length).fill(false),
}: {
data: any[];
rowStyle: Object | undefined;
priviledge: boolean[];
}) => {
// Initialize list of widths
const [colWidth, setColWidth] = useState<number[][]>(
data.map(row => new Array(Object.keys(row).length).fill(0)),
);
// Get widows size
const maxSize = useWindowDimensions();
if (!colWidth || !maxSize) {
return <></>;
}
// Fix issues of going off screen
const onLayout = (event: LayoutChangeEvent, row: number, col: number) => {
// Get current width
var {width, __} = event.nativeEvent.layout;
// Find total row width
const sum =
colWidth[row].reduce((partialSum, a) => partialSum + a, 0) -
colWidth[row][col] +
width;
// Shrink unpriviledged components
if (!priviledge[col] && sum > maxSize.width) {
width = width - (sum - maxSize.width);
if (width < 0) {
width = 0;
}
}
// Store width in colWidth array
colWidth[row][col] = width;
setColWidth([...colWidth]);
};
return (
<View>
{/* Map along rows */}
{data.map((item, rowIndex) => (
<View
key={rowIndex}
style={{
flexDirection: 'row',
maxWidth: maxSize.width,
}}>
{/* Map along columns */}
{Object.keys(item).map((key, colIndex) => (
<View
key={key}
onLayout={event => {
onLayout(event, rowIndex, colIndex);
}}
style={{
minWidth: Math.max(...colWidth.map(row => row[colIndex])),
flexShrink: 1,
...rowStyle,
}}>
{item[key]}
</View>
))}
</View>
))}
</View>
);
};
export default Table;
这是我的项目中的一些示例数据的外观(黄色框是使用此代码的表格):
现在,我看到的唯一问题是从横向旋转到纵向时它不会更新(但纵向到横向效果很好???)。