React Native - 收到道具时测量组件
React Native - measure component when props recieved
我有一个 ScrollView 作为我视图的根。我在其中展示了一堆文本组件。每个组件都有自己的 'ref',因此它们是可访问的。
现在,我正在传递一个带有数字的道具,该数字告诉我应该滚动到哪个文本。所以我需要先测量它。我尝试了这四种方法,但每种方法都只给我未定义的值。
有人有什么想法吗?
componentWillReceiveProps(nextProps) {
//this is a reference to my 'Text' component
const chapterNo = nextProps.navigation.state.params.chapter;
const chapterRef = this.refs["chapter" + chapterNo];
//method 1:
var RCTUIManager = require('NativeModules').UIManager;
var handle = ReactNative.findNodeHandle(chapterRef);
RCTUIManager.measure(handle, (x, y, width, height, pageX, pageY) => {
console.log(x, y, width, height);
});
//method 2:
NativeMethodsMixin.measure.call(chapterRef, (x, y, width, height) => {
console.log(x, y, width, height);
});
//method 3:
chapterRef.measure((ox, oy, width, height, px, py) => {
console.log(ox, oy, width, height);
});
//method 4 (same as 3 but with setTimout):
setTimeout(() => {
chapterRef.measure((ox, oy, width, height, px, py) => {
console.log(ox, oy, width, height);
});
}, 0);
}
看下面的例子
假设您的 scrollView 的每个项目都有不同的大小(否则会更容易):
- 创建一个数组来接收每个项目的高度。例如在你的组件的构造函数中。默认为空。
- 使用 onLayout 属性 获取 scrollView 的每个项目的高度(您还可以获得屏幕上的宽度和精确的 x,y 位置)。 onLayout 在装载和布局更改时调用:https://facebook.github.io/react-native/docs/view.html#onlayout
- 在您的回调函数(您称为 onLayout 的函数)中将此高度与项目的索引一起存储。你会得到例如这样的东西:this.widthsTab[0] = 312
- 然后,您只需浏览 widthsTab 即可准确找到元素所在的位置,然后滚动到该确切位置。
- 您还可以移除一半的屏幕高度,以确保您的元素位于屏幕中间。
很抱歉,如果不是很清楚,但我相信您会明白的。我会尽快添加示例。
编辑:
class HorizontalNavCustomerFlow extends Component {
state = {
heights: [],
totalHeight: 0,
heightsChecked: 0,
};
componentDidUpdate() {
const { currentParagraph } = this.props; // Id of the paragraph you want to scroll to
// Compute current item position and scroll when all item heights are computed
if (this.state.widthsChecked === HOW_MANY_ITEMS_YOU_HAVE) { // use for example .lenght if you have an array
let yposition = 0;
const screenHeight = Dimensions.get('window').height;
for (let i = 0; i <= currentParagraph; i++) {
yposition += this.state.heights[i];
}
// Removing half of current element
yposition -= this.state.heights[currentParagraph] / 2;
// And half of screen's height
yposition -= screenHeight / 2;
// Last elements
if (yposition > (this.state.totalWidth - screenWidth)) {
yposition = this.state.totalHeight - screenHeight;
}
// Scroll
if (yposition > 0) this.refs.MainScrollView.scrollTo({ y: yposition, animated: false });
}
}
// Render
render() {
return (
<View>
<ScrollView
ref='MainScrollView'
showsVerticalScrollIndicator={false}
>
// ... Your items
<View
onLayout={(object) => {
const { height } = object.nativeEvent.layout;
const newState = this.state;
newState.heights[index] = width;
newState.heightsChecked = this.state.heightsChecked + 1;
newState.totalHeight = this.state.totalHeight + height;
this.setState(newState);
}}
>
<Text>...</Text>
</View>
</ScrollView>
</View>
);
}
}
数组的索引可能会减一,这取决于您是从 0 还是 1 开始计数。请随意使用 +/-1 进行调整。
此外,我删除了当前项目宽度的一半,因为我想在它的中间向右滚动,但是如果你想滚动到开头或这个项目或其他东西,请随意更改。
我有一个 ScrollView 作为我视图的根。我在其中展示了一堆文本组件。每个组件都有自己的 'ref',因此它们是可访问的。 现在,我正在传递一个带有数字的道具,该数字告诉我应该滚动到哪个文本。所以我需要先测量它。我尝试了这四种方法,但每种方法都只给我未定义的值。 有人有什么想法吗?
componentWillReceiveProps(nextProps) {
//this is a reference to my 'Text' component
const chapterNo = nextProps.navigation.state.params.chapter;
const chapterRef = this.refs["chapter" + chapterNo];
//method 1:
var RCTUIManager = require('NativeModules').UIManager;
var handle = ReactNative.findNodeHandle(chapterRef);
RCTUIManager.measure(handle, (x, y, width, height, pageX, pageY) => {
console.log(x, y, width, height);
});
//method 2:
NativeMethodsMixin.measure.call(chapterRef, (x, y, width, height) => {
console.log(x, y, width, height);
});
//method 3:
chapterRef.measure((ox, oy, width, height, px, py) => {
console.log(ox, oy, width, height);
});
//method 4 (same as 3 but with setTimout):
setTimeout(() => {
chapterRef.measure((ox, oy, width, height, px, py) => {
console.log(ox, oy, width, height);
});
}, 0);
}
看下面的例子
假设您的 scrollView 的每个项目都有不同的大小(否则会更容易):
- 创建一个数组来接收每个项目的高度。例如在你的组件的构造函数中。默认为空。
- 使用 onLayout 属性 获取 scrollView 的每个项目的高度(您还可以获得屏幕上的宽度和精确的 x,y 位置)。 onLayout 在装载和布局更改时调用:https://facebook.github.io/react-native/docs/view.html#onlayout
- 在您的回调函数(您称为 onLayout 的函数)中将此高度与项目的索引一起存储。你会得到例如这样的东西:this.widthsTab[0] = 312
- 然后,您只需浏览 widthsTab 即可准确找到元素所在的位置,然后滚动到该确切位置。
- 您还可以移除一半的屏幕高度,以确保您的元素位于屏幕中间。
很抱歉,如果不是很清楚,但我相信您会明白的。我会尽快添加示例。
编辑:
class HorizontalNavCustomerFlow extends Component {
state = {
heights: [],
totalHeight: 0,
heightsChecked: 0,
};
componentDidUpdate() {
const { currentParagraph } = this.props; // Id of the paragraph you want to scroll to
// Compute current item position and scroll when all item heights are computed
if (this.state.widthsChecked === HOW_MANY_ITEMS_YOU_HAVE) { // use for example .lenght if you have an array
let yposition = 0;
const screenHeight = Dimensions.get('window').height;
for (let i = 0; i <= currentParagraph; i++) {
yposition += this.state.heights[i];
}
// Removing half of current element
yposition -= this.state.heights[currentParagraph] / 2;
// And half of screen's height
yposition -= screenHeight / 2;
// Last elements
if (yposition > (this.state.totalWidth - screenWidth)) {
yposition = this.state.totalHeight - screenHeight;
}
// Scroll
if (yposition > 0) this.refs.MainScrollView.scrollTo({ y: yposition, animated: false });
}
}
// Render
render() {
return (
<View>
<ScrollView
ref='MainScrollView'
showsVerticalScrollIndicator={false}
>
// ... Your items
<View
onLayout={(object) => {
const { height } = object.nativeEvent.layout;
const newState = this.state;
newState.heights[index] = width;
newState.heightsChecked = this.state.heightsChecked + 1;
newState.totalHeight = this.state.totalHeight + height;
this.setState(newState);
}}
>
<Text>...</Text>
</View>
</ScrollView>
</View>
);
}
}
数组的索引可能会减一,这取决于您是从 0 还是 1 开始计数。请随意使用 +/-1 进行调整。 此外,我删除了当前项目宽度的一半,因为我想在它的中间向右滚动,但是如果你想滚动到开头或这个项目或其他东西,请随意更改。