Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Text wrap with chevron on right in React Native ListView item renderer

Tags:

react-native

I am trying to have a list view show up that looks similar to this. The problem I am trying to solve is regarding word wrapping of the label. I do have it working with the code below, but it feels like a hack and doesn't work with device rotation. There has to be a way to do it without using Dimensions and styling.

enter image description here

Here is what I have.

import React, { Component } from 'react';

import {
  StyleSheet,
  Dimensions,
  TouchableOpacity,
  Text,
  View
} from 'react-native';

import Moment from 'moment'
import Icon from 'react-native-vector-icons/FontAwesome';

class ProjectListItemRenderer extends Component {

  componentDidMount() {
    //alert(Dimensions.get('window').height)

  }

  render() {

    return (
      <View style={styles.projectRow}>
        <View style={{width: Dimensions.get('window').width - 50}}>
          <Text style={styles.itemName}>{this.props.name}</Text>
          <Text style={styles.itemDetails}>{`${Moment(this.props.lastUpdated).fromNow()}`}</Text>
        </View>
        <View style={styles.moreContainer}>
          <Icon name="chevron-right" size={15} style={styles.moreIcon} />
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({

  projectRow: {
    flexDirection: 'row',
    justifyContent: 'flex-start',
    padding: 15,
   },

   itemName: {
     fontSize: 18,
     color: '#4A90E2',
   },

   itemDetails: {
     fontSize: 12,
     color: '#BBBBBB',
   },

   moreContainer: {
    justifyContent: 'center',
    alignItems: 'center'
  },

   moreIcon: {
     color: "#d6d7da"
   }

});

module.exports = ProjectListItemRenderer;

The other option I tried was absolute positioning, with the label being 20px from the right, and then absolute positioning the chevron on the right. The problem I ran into there was trying to figure out the height of the individual listItem renderer after it is rendered (and word wrapped).

like image 340
abritez Avatar asked Jul 06 '16 02:07

abritez


1 Answers

The problem comes from having flexDirection: 'row' in the View containing your text. This makes the text overflow to the right instead of wrapping. If you want your text to wrap, the containing View must have flexDirection: 'column' in the style.

I've modified your code accordingly:

import React, { Component } from 'react';

import {
  StyleSheet,
  Dimensions,
  TouchableOpacity,
  Text,
  View
} from 'react-native';

import Moment from 'moment'
import Icon from 'react-native-vector-icons/FontAwesome';

class ProjectListItemRenderer extends Component {

  componentDidMount() {
    //alert(Dimensions.get('window').height)
  }

  render() {

    return (
      <View style={styles.projectRow}>
        <View style={styles.projectText}>
          <Text style={styles.itemName}>{this.props.name}</Text>
          <Text style={styles.itemDetails>
            {`${Moment(this.props.lastUpdated).fromNow()}`}
          </Text>
        </View>
        <View style={styles.moreContainer}>
          <Icon name="chevron-right" size={15} style={styles.moreIcon} />
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({

  projectText: {
    flex: 1,
    flexDirection: 'column'
  },

  projectRow: {
    flexDirection: 'row',
    justifyContent: 'flex-start',
    padding: 15,
  },

   itemName: {
     fontSize: 18,
     color: '#4A90E2',
   },

   itemDetails: {
     fontSize: 12,
     color: '#BBBBBB',
   },

   moreContainer: {
    justifyContent: 'center',
    alignItems: 'center'
  },

   moreIcon: {
     color: "#d6d7da"
   }

});

module.exports = ProjectListItemRenderer;

The only difference is I replaced {width: Dimensions.get('window').width - 50} with {flex: 1, flexDirection: 'column'}.

like image 175
Mika Kuitunen Avatar answered Nov 15 '22 12:11

Mika Kuitunen