React Native `alignItems: 'flex-end'` hides content in TabBarIOS component

1k views Asked by At

This question is similar to this one however I have different requirements. I have a <TabBarIOS> component that renders a <Camera> from react-native-camera. I need to place a button to take a picture at the bottom of the <Camera> component but above the <TabBarIOS> component.

index.ios.js

import React, { Component } from 'react';
import {
  AppRegistry,
  TabBarIOS,
  ScrollView,
  StyleSheet,
  Text,
  View
} from 'react-native';
import CameraTab from './views/CameraTab.ios.js';
import FilesTab from './views/FilesTab.ios.js';
import Icon from 'react-native-vector-icons/MaterialIcons';

export default class MyApp extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedTab: 'cameraTab'
    };
  };

  _renderContent() {
    switch (this.state.selectedTab) {
      case "filesTab":
        return <FilesTab style={styles.tabContent}></FilesTab>;
      case "cameraTab":
        return <CameraTab style={styles.tabContent}></CameraTab>;
      case "settingsTab":
        return <View style={styles.tabContent}></View>;
      default:
        return <View style={styles.tabContent}></View>;
    }
  };

  render() {
    return (
      <TabBarIOS
        tintColor="#3498db"
        barTintColor="#ecf0f1">
        <Icon.TabBarItemIOS
          title="Files"
          iconName="folder"
          selected={this.state.selectedTab === "filesTab"}
          onPress={() => {
            this.setState({
              selectedTab: "filesTab",
            });
          }}>
          {this._renderContent()}
        </Icon.TabBarItemIOS>
        <Icon.TabBarItemIOS
          title="Camera"
          iconName="photo-camera"
          badge={this.state.notifCount > 0 ? this.state.notifCount : undefined}
          selected={this.state.selectedTab === "cameraTab"}
          onPress={() => {
            this.setState({
              selectedTab: "cameraTab",
              notifCount: this.state.notifCount + 1,
            });
          }}>
          {this._renderContent()}
        </Icon.TabBarItemIOS>
        <Icon.TabBarItemIOS
          title="Settings"
          iconName="settings"
          selected={this.state.selectedTab === 'settingsTab'}
          onPress={() => {
            this.setState({
              selectedTab: "settingsTab",
              presses: this.state.presses + 1
            });
          }}>
          {this._renderContent()}
        </Icon.TabBarItemIOS>
      </TabBarIOS>
    );
  }
}

var styles = StyleSheet.create({
  tabContent: {},
});

AppRegistry.registerComponent('myapp', () => myApp);

CameraTab.ios.js

import React, { Component } from 'react';
import {
  Dimensions,
  StyleSheet,
  Text,
  View
} from 'react-native';
import Camera from 'react-native-camera';

export default class CameraTab extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  };

  render() {
    return (
      <Camera
        ref={(cam) => {
          this.camera = cam;
        }}
        style={styles.preview}
        aspect={Camera.constants.Aspect.fill}>
      </Camera>
    );
  }

  takePicture() {
    this.camera.capture()
      .then((data) => console.log(data))
      .catch(err => console.error(err));
  }
}

var styles = StyleSheet.create({
  preview: {
    flex: 1,
    flexDirection: 'row',
    alignItems: 'flex-end',
    height: Dimensions.get('window').height,
    width: Dimensions.get('window').width
  },
  capture: {
    backgroundColor: '#fff',
    borderRadius: 5,
    color: '#000',
    height: 20
  }
});

module.exports = CameraTab;

I've tried various things but the capture button is always hidden when alignItems: 'flex-end' is in the container component's style.

before

It should look something like this:

enter image description here

Edit: I've discovered this issue that describes a workaround (placing the button component outside of the camera component). According to RN's docs on Height and Width it seems that this solution will work for all screen dimensions. However this doesn't work for me because I want a Subview with icons inside the camera.

1

There are 1 answers

0
rosendin On BEST ANSWER

OK, finally fixed it. I think the problem had to do with the height and width in the preview style. Working code:

import React, { Component } from 'react';
import {
  Dimensions,
  StyleSheet,
  Text,
  TouchableHighlight,
  View
} from 'react-native';
import Camera from 'react-native-camera';
import Icon from 'react-native-vector-icons/Ionicons';

export default class CameraTab extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  };

  render() {
    return (
      <View style={styles.container}>
        <Camera
          ref={(cam) => {
            this._camera = cam;
          }}
          style={styles.preview}
          aspect={Camera.constants.Aspect.fill}
          captureTarget={Camera.constants.CaptureTarget.disk}>
          <TouchableHighlight
              style={styles.cameraButton}
              onPress={this._takePicture.bind(this)}>
              <Icon name="ios-qr-scanner" size={55} color="#95a5a6" />
          </TouchableHighlight>
        </Camera>
      </View>
    );
  }

  _takePicture() {
    this._camera.capture()
      .then((data) => {
        console.log(data)
      })
      .catch((err) => {
        console.error(err)
      });
  }
}

var styles = StyleSheet.create({
  cameraButton: {
    flex: 0,
    flexDirection: 'row',
    marginBottom: 60,
  },
  container: {
    flex: 1,
  },
  preview: {
    flex: 1,
    flexDirection: 'row',
    alignItems: 'flex-end',
    justifyContent: 'space-around'
  },
});

module.exports = CameraTab;