记录一些开发中遇到的问题以及解决办法。
1、ScrollView的onScroll只调用一次
其实日志中已经提示了我们
You specified
onScroll
on a <ScrollView> but not
scrollEventThrottle
. You will only receive one event. Using
16
you get all the events but be aware that it may cause frame drops, use a bigger number if you don't need as much precision.
所以解决办法就是增加scrollEventThrottle属性。
建议简单判断一下系统和机型,在低端手机上设置的值大一点,高端手机上值设置小一点,这样可以一定程度上保证流畅度。
2、Tried to register two views with the same name xxxx
原因:是多次使用requireNativeComponent同一个组件。
解决办法:检查代码,找出多次使用的代码,使用RN包装一次这个原生组件,其他地方使用这个包装后的RN组件。
3、组件库demo目录引用外层组件源码目录代码
使用以下方式依赖:
"react-navigation": "link:../.."
4、Android端崩溃,报
java.lang.NullPointerException: Attempt to read from field 'int android.view.View.mViewFlags' on a null object reference
日志如下:
java.lang.NullPointerException: Attempt to read from field 'int android.view.View.mViewFlags' on a null object reference
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3408)
at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:663)
at android.view.View.updateDisplayListIfDirty(View.java:15341)
at android.view.View.draw(View.java:16143)
at android.view.ViewGroup.drawChild(ViewGroup.java:3622)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3409)
at com.facebook.react.views.view.ReactViewGroup.dispatchDraw(ReactViewGroup.java:663)
可能原因:
Image组件中属性resizeMode设置为了stretch,stretch只支持iOS,所以在Android系统上可能会造成崩溃。可以考虑用contain或cover来代替。
// 这样写,在Android系统上可能会崩溃
<Image ... resizeMode={'stretch'} />
5、React Native 0.55.4(其他版本可能也有类似问题),Text中包含中英文时,如果设置了lineHeight,在iOS上中英文是底部对齐,而不是垂直对齐。
这个版本的Text绘制时是使用的NSMutableAttributedString,居然是按字符来设置baseline,这样中英文这种高度不一样的字符就不会垂直对齐了。
解决办法一:更新到最新版本
解决办法二:直接改源码
将RCTTextShadowView.m文件中postprocessAttributedText方法替换为如下代码:
- (void)postprocessAttributedText:(NSMutableAttributedString *)attributedText
__block CGFloat maximumLineHeight = 0;
[attributedText enumerateAttribute:NSParagraphStyleAttributeName
inRange:NSMakeRange(0, attributedText.length)
options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
usingBlock:
^(NSParagraphStyle *paragraphStyle, __unused NSRange range, __unused BOOL *stop) {
if (!paragraphStyle) {
return;
maximumLineHeight = MAX(paragraphStyle.maximumLineHeight, maximumLineHeight);
if (maximumLineHeight == 0) {
// `lineHeight` was not specified, nothing to do.
return;
__block CGFloat maximumFontLineHeight = 0;
[attributedText enumerateAttribute:NSFontAttributeName
inRange:NSMakeRange(0, attributedText.length)
options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
usingBlock:
^(UIFont *font, NSRange range, __unused BOOL *stop) {
if (!font) {
return;
if (maximumFontLineHeight <= font.lineHeight) {
maximumFontLineHeight = font.lineHeight;
if (maximumLineHeight < maximumFontLineHeight) {
return;
CGFloat baseLineOffset = maximumLineHeight / 2.0 - maximumFontLineHeight / 2.0;
[attributedText addAttribute:NSBaselineOffsetAttributeName
value:@(baseLineOffset)
range:NSMakeRange(0, attributedText.length)];
解决办法三:使用runtime方式替换postprocessAttributedText为解决办法二的实现
6、iOS的TextInput组件如果设置的value值字符串长度大于设置maxLength,则maxLength长度控制无效,可以无限输入
除了设置value字符串长度大于maxLength这种情况外,多个手指同时按键盘快速输入,也可能出现这种无限输入的情况。
// RCTBaseTextInputView.m
if (_maxLength) {
NSUInteger allowedLength = _maxLength.integerValue - backedTextInputView.attributedText.string.length + range.length;
if (text.length > allowedLength) {
这里的allowedLength
可能是一个负数,但定义的类型却是NSUInteger
,这时allowedLength
就会被转化成一个很大的数字,导致text.length > allowedLength
一直是NO
。
解决办法一:更新到最新版本,我已经提交了PR
解决办法二:直接改源码
// RCTBaseTextInputView.m
if (_maxLength) {
NSInteger allowedLength = _maxLength.integerValue - backedTextInputView.attributedText.string.length + range.length;
if (allowedLength < 0 || text.length > allowedLength) {
7、React Native开发的App中的字体会随着系统字体的设置而放大缩小,有时会引起界面显示混乱
解决办法:禁止字体缩放
RN中用于显示的控件就是TextInput和Text,所以只要全局设置它们不可缩放字体就可以了,代码如下:
TextInput.defaultProps = Object.assign({}, TextInput.defaultProps, {
allowFontScaling: false
Text.defaultProps = Object.assign({}, Text.defaultProps, {