Simulate display: inline in React Native

前端 未结 4 1989
孤街浪徒
孤街浪徒 2020-12-13 08:37

React Native doesn\'t support the CSS display property, and by default all elements use the behavior of display: flex (no inline-flex

4条回答
  •  一向
    一向 (楼主)
    2020-12-13 08:56

    I had the following use case:

    I needed a text that can wrap with different sizes, and throughout that text, I wanted to underscore some of the words (to indicate that they are clickable).

    It's quite simple expect for the case that you can't control the underline in any way (how close is it, what color is it, so on) - this led me through the rabbit hole, and eventually coming up with the solution of splitting every word, and wrapping it in separate Text component, wrapped with View.

    I'll paste the code here:

    
    
    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 (
          
            {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 (
                  
                     onPressHandler()}>
                      {val}{isLast ? '' : ' '}
                    
                  
                );
              }
    
              return (
                
                  {part}{isLast ? '' : ' '}
                
              );
            })}
          
        );
      }
    }
    

    and usage:

      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 (
           onUrlClick(index)}>
            By tapping Create an account or Continue, I agree to SALT\'s [Terms of Service] and [Privacy Policy]
          
        );
      }
    
    

    this is the end result:

提交回复
热议问题