0

I am new in react native and I really get stuck in aligning a two toolbar buttons for two days! I need to put them in the right part of my tool bar using flex. However, I couldn't do that. Here is the code:

export default class ToolbarHorizontal extends Component {

  // component prop types
  static propTypes = {
    items: React.PropTypes.arrayOf(React.PropTypes.shape({
      active: React.PropTypes.bool,
      name: React.PropTypes.string.isRequired,
      imageSourceActive: React.PropTypes.number.isRequired,
      imageSourceInactive: React.PropTypes.number.isRequired,
      onOpen: PropTypes.func,
    })).isRequired,
    toolbarActiveItem: React.PropTypes.string.isRequired,
    forcedPath: React.PropTypes.bool,
    forcedPathImageSource: React.PropTypes.number,
    tintColor: React.PropTypes.string,
  };

  constructor(props) {
    super();
    this.toolbarActiveIndex = props.items.map((el) => el.name).indexOf(props.toolbarActiveItem);
  }

  render() {
    const { items } = this.props;
    let { toolbarActiveItem } = this.props;
    let { forcedPath } = this.props;
    let { forcedPathImageSource } = this.props;
    let { tintColor } = this.props;
    tintColor = (tintColor) ? tintColor : '#000'; // default value is black
    return (
      <View style={styles.container} >
        <ScrollView
          horizontal={true}
          collapsable={true}
          showsHorizontalScrollIndicator={false}
          showsVerticalScrollIndicator={false}
          style={styles.scroller}
        >
   <View style={styles.componentContainer}>
        { items.map((item, index) => {
            let active = (item.active !== undefined) ? item.active : true; // default value is true
            if (active) {
              return(
                <View key={item.id} style={styles.imageContianer}>
                  {(toolbarActiveItem == item.name) &&
                    <View style={styles.insideImageContainer}>
                      <Image
                        source={item.imageSourceSection}
                        style={styles.item}
                      />
                      <Text size={20} style={{color:tintColor, paddingRight:10}}>{!forcedPath ? item.description : null}</Text>
                    </View>
                  }
                </View>
              );
            }
          }
        )}


<View style={styles.buttomContainer}>
        { items.map((item, index) => {
            //console.log('toolbarActiveItem == item.name:', toolbarActiveItem, '==', item.name);
            let active = (item.active !== undefined) ? item.active : true; // default value is true
            if (active && (!forcedPath || item.isVisibleWhenForcedPath)) {
              return(
                <View key={item.id} >
                  {item.isTouchable && forcedPath && index > 0 &&
                    <Image
                      source={forcedPathImageSource}
                      style={styles.forcedPathImage}
                    />
                  }
                  {item.isTouchable &&
                    <TouchableOpacity onPress={() => {
                      if (!forcedPath) { // when forcedPath, buttons are never touchable
                        if (toolbarActiveItem != item.name) {
                          item.onOpen(item.name);
                          toolbarActiveItem = item.name;
                        }
                        else
                        { // already on opened page, go back if button is pressed again
                          this.props.navigation.goBack();
                        }
                      }
                    }}>
                      {forcedPath &&
                        <Image
                          source={(toolbarActiveItem == item.name) ? item.imageSourceForcedPathActive : index > this.toolbarActiveIndex ? item.imageSourceForcedPathTobevisited : item.imageSourceForcedPathVisited}
                          style={styles.item}
                        />
                      }
                      {!forcedPath &&
                        <Image
                          source={(toolbarActiveItem == item.name) ? item.imageSourceActive : item.imageSourceInactive}
                          style={styles.item}
                        />
                      }
                    </TouchableOpacity>
                  }
                </View>
              );
            }
          }
        )}
          </View>
        </View>

        </ScrollView>
      </View>
    );
  }

}

const styles = StyleSheet.create({
  container: {
    flex:0.16,
    flexDirection:'row' ,

    //backgroundColor: 'transparent',
  },
  componentContainer: {
    flex:1,
    flexDirection:'row',
    alignContent:'center',
    alignItems: 'center',

  },
  imageContianer: {
    flex:1,
    flexDirection:'row',
    alignContent:'center',
    alignItems:'center',

  },
  buttomContainer: {
    flex:1,
    flexDirection:'row',
  //  backgroundColor: '#9b59b6' ,
  },
insideImageContainer: {
  flex:1,
  alignItems:'center',
  flexDirection:'row',
},

  scroller: {
    marginHorizontal: 0,
    marginVertical: 10,
  },
  item: {
    width: 60,
    height: 60,
    //marginRight: 5,
    margin: 2,
  },
  forcedPathImage: {
    flex: 1,
    width: 24,
    height: 36,
    resizeMode: 'contain',
  },
});

In fact the problem is that, any changing in flex value doesn't work in insideImageContainer or imageContianer. Can you help me to fix this issue. Thanks in advance.

Queen
  • 571
  • 3
  • 10
  • 28
  • 1
    Try setting `marginRight: 'auto'` on the element that is to the left of your buttons. – Jon Koops Nov 03 '17 at 14:10
  • @JonKoops: Thanks for your answer and sorry for my question that was long. Unfortunately, nothing happen and it keeps as before. – Queen Nov 03 '17 at 14:16
  • @JonKoops: Do you have any other idea? – Queen Nov 03 '17 at 14:25
  • Perhaps if you could provide a more succinct version of your component structure. It's hard to reproduce this since it has a lot unrelated logic. Maybe a simplified version in plain HTML and CSS to play around with? – Jon Koops Nov 03 '17 at 14:29
  • @JonKoops: Thanks a lot. Unfortunately, the components are so huge and complex. However, I try to see if I can do that. – Queen Nov 03 '17 at 14:32
  • 1
    Try removing `flex:1` from `buttomContainer`. Then `componentContainer` should grow to fill the space and `buttomContainer` should be pushed to the right. At the moment, they're each trying to fill half of the row. – Rob Hogan Nov 03 '17 at 14:37
  • @RobHogan: Thanks a lot for your answer, as I remove it, all the buttons become vertical. – Queen Nov 03 '17 at 14:44
  • @RobHogan: I should mention that, I also deleted 'flexDirection' there. However, in both cases by changing the flex in 'componentContainer' nothing changes. – Queen Nov 03 '17 at 14:47

1 Answers1

2

At a minimum this should be all you need:

Toolbar = () => <View style={styles.container}>
  <View style={styles.componentContainer}>
    <Text>Icon</Text>
    <Text>Title</Text>
  </View>
  <View style={styles.buttomContainer}>
    <Text>Button1</Text>
    <Text>Button2</Text>
  </View>
</View> 

const styles = StyleSheet.create({
  container: {
    flexDirection: 'row'
  },
  componentContainer: {
    flex: 1,
    flexDirection: 'row'
  },
  buttomContainer: {
    flexDirection: 'row'
  }
});

See this running in Expo

The thing to think about when using flex layouts is; which component should take up the spare space? Give that component a flex: 1 property. (And if multiple component should share the same space, split the flex between them).

In this case you don't want your buttomContainer (typo?) to be any bigger than it needs to be. You want the componentContainer to grow (flex) as big as it can and push the buttomContainer to the right.

Rob Hogan
  • 2,442
  • 19
  • 23
  • It was a good answer, However my code secretly does't work like that. Thanks, I voted up. :) – Queen Nov 03 '17 at 17:14
  • Thanks for the upvote. If you can reproduce the problem you're having in expo I'd be happy to have another look. – Rob Hogan Nov 03 '17 at 17:22
  • That doesn't run (try "tap to play" in snack, or run it on your phone via the expo app) - you'll need to either add some of your other project files or cut out some of the stuff not relevant to the problem. – Rob Hogan Nov 03 '17 at 17:33
  • 1
    According to your templet code it finally works. Thanks a lot. :) – Queen Nov 04 '17 at 11:06