如何在 ListView 和 FlatList 中渲染绝对元素?
How to render absoulute element inside ListView or FlatList?
这是我研究了一段时间的有趣的:
我有一个 FlatList(与 ListView 有同样的问题),我想在具有以下特征的内部滚动容器中呈现一个元素:
- 绝对定位(因此对列表元素的位置没有影响)
- 位置距顶部 XX 距离(
translateY
或 top
)
- zIndex(列表元素上方)
用例是我正在渲染一个日视图日历网格,在当前时间位置有一个水平条固定在距离内部滚动视图开始的 X 处,因此当用户滚动通过该位置时它会出现。
到目前为止,我已经尝试用另一个 ScrollView 包装 FlatList/ListView...还尝试将此元素渲染为 header 元素,它仅在 header/footer 可见时有效(在看不见的时候被丢弃)。
欢迎任何想法。 :)
谢谢
下面的屏幕截图(红色条是我要渲染的):
这是一个工作演示,它听起来像是您要实现的目标:https://sketch.expo.io/BkreW1che。您可以点击"preview"在浏览器中查看。
下面是测量 ListView 高度并将指示器放在其顶部所需的主要代码(访问上面的 link 以查看完整源代码):
handleLayout(event) {
const { y, height } = event.nativeEvent.layout;
// Now we know how tall the ListView is; let's put the indicator in the middle.
this.setState({ indicatorOffset: y + (height / 2) });
}
renderIndicator() {
const { indicatorOffset } = this.state;
// Once we know how tall the ListView is, put the indicator on top.
return indicatorOffset ? (
<View style={[{ position: 'absolute', left: 0, right: 0, top: indicatorOffset }]} />
) : null;
}
render() {
return (
<View style={styles.container}>
<ListView
onLayout={(event) => this.handleLayout(event)}
dataSource={this.state.dataSource}
renderRow={this.renderRow}
/>
{this.renderIndicator()}
</View>
);
}
编辑:我现在了解到您希望指示器与列表一起滚动。这是上面的一个简单更改,只需向 ListView 添加一个 onScroll
侦听器:https://sketch.expo.io/HkEjDy92e
handleScroll(event) {
const { y } = event.nativeEvent.contentOffset;
// Keep the indicator at the same position in the list using this offset.
this.setState({ scrollOffset: y });
},
进行此更改后,由于 onScroll
回调的延迟,指标实际上似乎有点滞后。
如果您想要更好的性能,您可以考虑将指标呈现为 renderRow
方法的一部分。例如,如果您知道指示器应该出现在 10:30 am,那么您可以在 10am 行的中间呈现它。
这是我研究了一段时间的有趣的:
我有一个 FlatList(与 ListView 有同样的问题),我想在具有以下特征的内部滚动容器中呈现一个元素:
- 绝对定位(因此对列表元素的位置没有影响)
- 位置距顶部 XX 距离(
translateY
或top
) - zIndex(列表元素上方)
用例是我正在渲染一个日视图日历网格,在当前时间位置有一个水平条固定在距离内部滚动视图开始的 X 处,因此当用户滚动通过该位置时它会出现。
到目前为止,我已经尝试用另一个 ScrollView 包装 FlatList/ListView...还尝试将此元素渲染为 header 元素,它仅在 header/footer 可见时有效(在看不见的时候被丢弃)。
欢迎任何想法。 :)
谢谢
下面的屏幕截图(红色条是我要渲染的):
这是一个工作演示,它听起来像是您要实现的目标:https://sketch.expo.io/BkreW1che。您可以点击"preview"在浏览器中查看。
下面是测量 ListView 高度并将指示器放在其顶部所需的主要代码(访问上面的 link 以查看完整源代码):
handleLayout(event) {
const { y, height } = event.nativeEvent.layout;
// Now we know how tall the ListView is; let's put the indicator in the middle.
this.setState({ indicatorOffset: y + (height / 2) });
}
renderIndicator() {
const { indicatorOffset } = this.state;
// Once we know how tall the ListView is, put the indicator on top.
return indicatorOffset ? (
<View style={[{ position: 'absolute', left: 0, right: 0, top: indicatorOffset }]} />
) : null;
}
render() {
return (
<View style={styles.container}>
<ListView
onLayout={(event) => this.handleLayout(event)}
dataSource={this.state.dataSource}
renderRow={this.renderRow}
/>
{this.renderIndicator()}
</View>
);
}
编辑:我现在了解到您希望指示器与列表一起滚动。这是上面的一个简单更改,只需向 ListView 添加一个 onScroll
侦听器:https://sketch.expo.io/HkEjDy92e
handleScroll(event) {
const { y } = event.nativeEvent.contentOffset;
// Keep the indicator at the same position in the list using this offset.
this.setState({ scrollOffset: y });
},
进行此更改后,由于 onScroll
回调的延迟,指标实际上似乎有点滞后。
如果您想要更好的性能,您可以考虑将指标呈现为 renderRow
方法的一部分。例如,如果您知道指示器应该出现在 10:30 am,那么您可以在 10am 行的中间呈现它。