rn-relates icon indicating copy to clipboard operation
rn-relates copied to clipboard

大屏手机 Text 出现空行问题

Open ljunb opened this issue 5 years ago • 0 comments
trafficstars

背景

最近参与了鹏友圈 2.16 社区视觉改版的功能开发,其中遇到一个奇怪的问题:

在个别机型下,Text 组件设置了 lineHeihgt 后,发现 numberOfLines 有显示问题,尾随出现了一行空行。复现机型有 iPhone 8 Plus、iPhone 11 Pro Max

一开始以为是 RN 中文网提及Text 嵌套导致的问题,查看后发现并不是同个问题。尝试搜了下 issue 列表,发现类似反馈和相关讨论:

#29298 - Text's numberOfLines doesn't work in iphone8P #21410 - [0.57] Text component rendering last line truncated

方案

基本确定是相同问题,既然是因为 lineHeightheight 导致的,可以简单做个处理:当组件渲染之后,如发现高度不超过所有行高总高度的话,手动更改下组件高度。

实践

自定义组件:

import React, { useState } from "react";
import { PixelRatio, StyleSheet, Text, TextProps } from 'react-native';

const AdaptableHeightText: React.FC<TextProps> = (props) => {
  const {
    children,
    numberOfLines = 0,
    style,
  } = props;
  const lineHeight = StyleSheet.flatten(style || {}).lineHeight || 0;
  const [contentHeight, setContentHeight] = useState(0);

  const handleLayout = (evt) => {
    const { height } = evt.nativeEvent.layout;
    if (height !== contentHeight && contentHeight === 0) {
      // 向上取整
      const ceilH = Math.ceil(height);
      const targetH = numberOfLines * lineHeight;

      // 设置了 lineHeight & numberOfLines 时处理;
      // 有时 layout 的 height 还多了一行高度,这里取 min
      targetH > 0 && setContentHeight(Math.min(ceilH, targetH + 2 * PixelRatio.get()));
    }
  };

  return (
    <Text
      {...props}
      style={[style, contentHeight > 0 && { height: contentHeight } ]}
      onLayout={handleLayout}
    >
      {children}
    </Text>
  )
};

export default AdaptableHeightText;

ljunb avatar Aug 06 '20 06:08 ljunb