对于我当前的项目,我创建了一个日记/日历类型组件,显示当用户点击查看该视图时居中的当前日期(日记视图)或当前月份(日历视图)。
我使用ScrollView来保存我的内容:
_getInitialOffset(h) {
const FIX = 75; //TODO: Make it less arbitrary
let percentToScroll = (this.props.viewedDate.month()+1)/12; //12 = number of months per year
let { height } = this.props;
let centerFix = height/2;
let contentHeight = h;
let yPos = contentHeight*percentToScroll - centerFix - FIX;
return (yPos > 0) ? yPos : 0;
}
render() {
var year = this.props.viewedDate.year();
var cal = Calendar.get(year);
var contentHeight = this.contentHeight;
return (
<View>
<View style={styles.daysOfWeek}>
{
Calendar.days().map(function(day, i) {
return <Text key={i} style={styles.dayHeader}>{day}</Text>;
})
}
</View>
<ScrollView
ref={ref => {this._scrollView = ref}}
style={{
height: this.props.height,
paddingTop: 15
}}
onContentSizeChange={(w, h) => {
this._scrollView.scrollTo({y: this._getInitialOffset(h), animated: false});
}}>
<Year year={year} calendar={cal}/>
</ScrollView>
</View>
);
}
我试图让它在当前月份的渲染中居中,但因为我的当前方法(使用OnContentSizeChange)在渲染之后发生,所以有一个框架,用户看到它未被渲染,这是不好的用户经验。
有没有办法在渲染之前/期间获取ScrollView组件的内容高度,或者在onContentSizeChange方法触发之后延迟组件可见性?
答案 0 :(得分:3)
onContentSizeChange
在内部使用onLayout
,一旦计算出布局就会触发。
计算布局后会立即触发此事件,但在收到事件时,新布局可能尚未反映在屏幕上,尤其是在布局动画正在进行中时。
在此之前无法获得尺寸。
因此,您可以执行的操作是将滚动视图的opacity
设置为0,直到触发第一个onContentSizeChange
。
我建议您使用Animated.Value
进行不透明度更改,以便它不会重新渲染整个组件。
答案 1 :(得分:0)
我的解决方法如下:
以下内容摘自我的代码。它是不完整且未经测试的,但应该足以使它开始使用。
class CustomScrollView extends React.Component {
constructor(props) {
super(props);
this.state = {
scrollOffsetAnim: new Animated.Value(0)
};
}
renderScrollBar() {
const {
scrollOffsetAnim,
contentHeight,
containerHeight,
} = this.state;
//...
}
render() {
return (
<View>
<ScrollView
scrollEventThrottle={16}
onScroll={(evt) => {
const {contentOffset} = evt.nativeEvent;
const {y} = contentOffset;
this.state.scrollOffsetAnim.setValue(y);
}}
onLayout={(evt) => {
const {height} = evt.nativeEvent.layout;
const {containerHeight} = this.state;
if(!containerHeight || containerHeight !== height) {
this.setState({containerHeight: height})
}
}}
>
<View
onLayout={(evt) => {
const {height} = evt.nativeEvent.layout;
const {contentHeight} = this.state;
if(!contentHeight || contentHeight !== height) {
this.setState({contentHeight: height})
}
}}
>
{this.props.children}
</View>
</ScrollView>
{this.renderScrollBar()}
</View>
);
}
}