programing

디스플레이 시뮬레이션: React Native 인라인

magicmemo 2023. 2. 25. 20:51
반응형

디스플레이 시뮬레이션: React Native 인라인

React Native는 CSS를 지원하지 않습니다.display디폴트로는 모든 요소가 다음 동작을 사용합니다.display: flex(없음)inline-flex둘 중 하나).대부분의 비플렉스 레이아웃은 플렉스 속성을 사용하여 시뮬레이션할 수 있지만 인라인 텍스트로 인해 당황스럽습니다.

내 앱에는 텍스트로 된 여러 단어가 들어 있는 컨테이너가 있으며, 그 중 일부는 포맷이 필요합니다.즉, 포맷을 수행하려면 스팬을 사용해야 합니다.스팬을 포장하기 위해 사용할 용기를 설정할 수 있습니다.flex-wrap: wrap단, 단어 구분 시 래핑하는 기존의 인라인 동작이 아닌 스팬 끝에서만 래핑할 수 있습니다.

문제가 표시됨(노란색으로 표시됨):

여기에 이미지 설명 입력

(http://codepen.io/anon/pen/GoWmdm?editors=110) 경유)

플렉스 속성을 사용하여 올바른 래핑과 진정한 인라인 시뮬레이션을 얻을 수 있는 방법이 있습니까?

div 또는 다른 요소에서 스팬을 줄바꿈하는 방법으로 텍스트 요소를 다른 텍스트 요소로 줄바꿈으로써 이 효과를 얻을 수 있습니다.

<View>
  <Text><Text>This writing should fill most of the container </Text><Text>This writing should fill most of the container</Text></Text>       
</View>

또한 flexWrap: 'rap'과 함께 부모에서 flexDirection:'row' 속성을 선언하여 이 효과를 얻을 수 있습니다.그러면 자녀가 인라인으로 표시됩니다.

<View style={{flexDirection:'row', flexWrap:'wrap'}}>
  <Text>one</Text><Text>two</Text><Text>Three</Text><Text>Four</Text><Text>Five</Text>
</View>

예를 확인해 주세요.

https://rnplay.org/apps/-rzWGg

원하는 효과를 얻기 위해 플렉스를 사용하지 않고 텍스트 노드만 중첩할 수 있습니다.다음과 같습니다.https://facebook.github.io/react-native/docs/text

<Text style={{fontWeight: 'bold'}}>
  I am bold
  <Text style={{color: 'red'}}>
    and red
  </Text>
</Text>

다른 콘텐츠와 함께 텍스트 블록을 인라인화하는 적절한 방법을 찾지 못했습니다.현재의 "해키한" 회피책은 텍스트 문자열 내의 모든 단어를 자체 블록으로 분할하여 각 단어에 대해 flexWrap이 적절하게 랩핑되도록 하는 것입니다.

다음과 같은 사용 사례가 있습니다.

다른 크기로 줄바꿈할 수 있는 텍스트가 필요했고, 텍스트 전체에 걸쳐 일부 단어에 밑줄을 그어 클릭할 수 있는 것을 표시했습니다.

밑줄을 제어할 수 없는 경우(얼마나 가까운지, 어떤 색상인지 등)는 매우 간단합니다.이것에 의해, 저는 토끼구멍을 통과해, 최종적으로 모든 단어를 분할해, 다른 텍스트 컴포넌트로 둘러싸는 솔루션을 생각해 냈습니다.

여기에 코드를 붙여넣습니다.



import React from 'react';
import { StyleSheet, View, TouchableOpacity, Text } from 'react-native';
import Colors from '../../styles/Colors';
import Fonts from '../../styles/Fonts';

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});

export default class SaltText extends React.Component {

  getTheme (type) {

    if (type === 'robomonoregular10gray') {
      return {
          fontSize: Fonts.SIZES.TEN,
          fontFamily: Fonts.ROBOTOMONO_REGULAR,
          color: Colors.getColorOpacity(Colors.GRAY, 70),
          lineHeight: Fonts.SIZES.TEN + 10
      };
    }

    throw new Error('not supported');
  }

  splitText (text) {
    const parts = [];
    const maps = [];

    let currentPart = '';
    let matchIndex = 0;

    for (const letter of text) {

      const isOpening = letter === '[';
      const isClosing = letter === ']';

      if (!isOpening && !isClosing) {
        currentPart += letter;
        continue;
      }

      if (isOpening) {
        parts.push(currentPart);
        currentPart = '';
      }

      if (isClosing) {
        parts.push(`[${matchIndex}]`);
        maps.push(currentPart);
        currentPart = '';
        matchIndex++;
      }
    }

    const partsModified = [];
    for (const part of parts) {
      const splitted = part
        .split(' ')
        .filter(f => f.length);

      partsModified.push(...splitted);
    }

    return { parts: partsModified, maps };
  }

  render () {

    const textProps = this.getTheme(this.props.type);
    const children = this.props.children;

    const getTextStyle = () => {
      return {
        ...textProps,
      };
    };

    const getTextUnderlineStyle = () => {
      return {
        ...textProps,
        borderBottomWidth: 1,
        borderColor: textProps.color
      };
    };

    const getViewStyle = () => {
      return {
        flexDirection: 'row',
        flexWrap: 'wrap',
      };
    };

    const { parts, maps } = this.splitText(children);

    return (
      <View style={getViewStyle()}>
        {parts.map((part, index) => {

          const key = `${part}_${index}`;
          const isLast = parts.length === index + 1;

          if (part[0] === '[') {
            const mapIndex = part.substring(1, part.length - 1);
            const val = maps[mapIndex];
            const onPressHandler = () => {
              this.props.onPress(parseInt(mapIndex, 10));
            };
            return (
              <View key={key} style={getTextUnderlineStyle()}>
                <Text style={getTextStyle()} onPress={() => onPressHandler()}>
                  {val}{isLast ? '' : ' '}
                </Text>
              </View>
            );
          }

          return (
            <Text key={key} style={getTextStyle()}>
              {part}{isLast ? '' : ' '}
            </Text>
          );
        })}
      </View>
    );
  }
}

및 사용방법:

  renderPrivacy () {

    const openTermsOfService = () => {
      Linking.openURL('https://reactnativecode.com');
    };

    const openPrivacyPolicy = () => {
      Linking.openURL('https://reactnativecode.com');
    };

    const onUrlClick = (index) => {
      if (index === 0) {
        openTermsOfService();
      }

      if (index === 1) {
        openPrivacyPolicy();
      }
    };

    return (
      <SaltText type="robomonoregular10gray" onPress={(index) => onUrlClick(index)}>
        By tapping Create an account or Continue, I agree to SALT\'s [Terms of Service] and [Privacy Policy]
      </SaltText>
    );
  }

최종 결과는 다음과 같습니다.

예

이것을 사용해 보세요, 심플하고 깔끔하게.

<Text style={{ fontFamily: 'CUSTOM_FONT', ... }}>
   <Text>Lorem ipsum</Text>
   <Text style={{ color: "red" }}>&nbsp;dolor sit amet.</Text>
</Text>

결과:

Lorem ipsum dolor sit amet.

언급URL : https://stackoverflow.com/questions/34624100/simulate-display-inline-in-react-native

반응형