我想出了一个有点做作的方法来做到这一点。我们先来看问题。
我们可以使用 flexbox 将“徽章”放在左侧,将文本放在右侧,然后让“消息行”水平向下。这很简单,但我们希望消息行根据其内容改变宽度,而 flexbox 不会让您这样做,因为它会贪婪地扩展以填满所有空间。
我们需要一种方法来检查消息文本的宽度,然后相应地调整视图的大小,将其强制为指定的宽度。我们不能使用measure 来获取文本宽度,因为它实际上只给了我们底层节点的宽度,而不是实际的文本本身。
为此,我偷了一个想法from here 并创建了一个到 Obj-C 的桥梁,它创建了一个带有文本的 UILabel 并以这种方式获取它的宽度。
// TextMeasurer.h
#import "RCTBridgeModule.h"
#import <UIKit/UIKit.h>
@interface TextMeasurer : NSObject<RCTBridgeModule>
@end
// TextMeasurer.m
#import "TextMeasurer.h"
@implementation TextMeasurer
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(get:(NSString *)text cb:(RCTResponseSenderBlock)callback)
{
UILabel *label = [[UILabel alloc]init];
label.font = [UIFont fontWithName:@"Helvetica" size:14.0];
label.text = text;
callback(@[[NSNumber numberWithDouble: label.intrinsicContentSize.width]]);
}
@end
然后我将 this 的用法包装到一个组件中:
var AutosizingText = React.createClass({
getInitialState: function() {
return {
width: null
}
},
componentDidMount() {
setTimeout(() => {
this.refs.view.measure((x, y, width, height) => {
TextMeasurer.get(this.props.children, len => {
if(len < width) {
this.setState({
width: len
});
}
})
});
});
},
render() {
return <View ref="view" style={{backgroundColor: 'red', width: this.state.width}}><Text ref="text">{this.props.children}</Text></View>
}
});
如果文本的宽度小于视图的原始宽度 - 这将由 flexbox 设置,所有这些都会调整包含视图的大小。应用程序的其余部分如下所示:
var messages = React.createClass({
render: function() {
var rows = [
'Message Text',
'Message Text with lots of content ',
'Message Text with lots of content put in here ok yeah? Keep on talking bla bla bla whatever is needed to stretch this message body out.',
'Keep on talking bla bla bla whatever is needed to stretch this message body out.'
].map((text, idx) => {
return <View style={styles.messageRow}>
<View style={styles.badge}><Text>Me</Text></View>
<View style={styles.messageOuter}><AutosizingText>{text}</AutosizingText></View>
</View>
});
return (
<View style={styles.container}>
{rows}
</View>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'flex-start',
alignItems: 'stretch',
flexDirection: 'column',
backgroundColor: '#F5FCFF',
},
messageRow: {
flexDirection: 'row',
margin: 10
},
badge: {
backgroundColor: '#eee',
width: 80, height: 50
},
messageOuter: {
flex: 1,
marginLeft: 10
},
messageText: {
backgroundColor: '#E0F6FF'
}
});
AppRegistry.registerComponent('messages', () => messages);
它给了你这个:
我会密切关注Github issue,因为这个解决方案肯定有点笨拙,至少我希望在某个时候看到一种更好的方法来测量 RN 中的文本。