Flatlist data not showing up on screen - react-native

Trying to make a simple to-do list. My AddTodo component works fine and I don't believe it is causing the issue but my Flatlist does not show the data. I have no idea why as there are no errors. The issue appears with or without the scroll view.
I've tried messing around with the width and height of the items and the list itself but nothing seems to do the trick.
my mainTodo file:
import React, { Component } from 'react';
import { Text, View, StyleSheet, FlatList, ScrollView } from 'react-native';
import AddTodo from './AddTodo';
import TodoItem from './TodoItem';
class MainTodo extends Component {
constructor() {
super();
this.state = {
textInput: '',
todos: [
{ id: 0, title: 'walk rocky', completed: false },
{ id: 1, title: 'pickup dinner', completed: false }
]
};
}
addNewTodo() {
let todos = this.state.todos;
todos.unshift({
id: todos.length + 1,
todo: this.state.textInput,
completed: false
});
this.setState({
todos,
textInput: ''
});
}
render() {
return (
<View style={{ flex: 1 }}>
<AddTodo
textChange={textInput => this.setState({ textInput })}
addNewTodo={() => this.addNewTodo()}
textInput={this.state.textInput}
/>
<ScrollView>
<FlatList
style={{ flex: 1 }}
data={this.state.todos}
extraData={this.state}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => {
return (
<TodoItem todoItem={item} />
);
}}
/>
</ScrollView>
</View>
);
}
}
export default MainTodo;
my TodoItem file:
import React, { Component } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
class TodoItem extends Component {
render() {
const todoItem = this.props.todoItem;
return (
<View>
<TouchableOpacity style={styles.todoItem}>
<Text style={(todoItem.completed) ? { color: '#aaaaaa' } : { color: '#313131' }}>
{todoItem.title}
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
todoItem: {
width: 40,
height: 40,
borderBottomColor: '#DDD',
borderBottomWidth: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingLeft: 15
}
});
export default TodoItem;
Under my addtodo component nothing shows up, it's just a blank screen.

In the maintodo file you are rendering the AddTodo component but i didn't see your AddTodo component. So you can update your code accordingly.
In the TodoItem remove the style applied to TouchableOpacity so that your code looks like
import React, { Component } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
class TodoItem extends Component {
render() {
const todoItem = this.props.todoItem;
return (
<View>
<TouchableOpacity style={styles.todoItem}>
<Text style={(todoItem.completed) ? { color: '#aaaaaa' } : { color: '#313131' }}>
{todoItem.title}
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
});
export default TodoItem;
And in the MainTodo
update your addNewTodo function as
addNewTodo = () => {
const todo = {
id: this.state.todos.length,
title: this.state.textInput,
completed: false
}
this.setState({todos: [...this.state.todos, todo ], textInput: ""})
}
create the TextInput and Button with parent View as flexDirection: "row" and so when TextInput is changed it's value is set in the textInput and when Button is pressed it will create new object and add it to the todos and set the value of TextInput to empty.
and final code can be as
import React, { Component } from 'react';
import { Text, View, StyleSheet, FlatList, ScrollView, TextInput, Button } from 'react-native';
import TodoItem from './TodoItem';
class MainTodo extends Component {
constructor() {
super();
this.state = {
textInput: '',
todos: [
{ id: 0, title: 'walk rocky', completed: false },
{ id: 1, title: 'pickup dinner', completed: false }
]
};
}
addNewTodo = () => {
const todo = {
id: this.state.todos.length,
title: this.state.textInput,
completed: false
}
this.setState({todos: [...this.state.todos, todo ], textInput: ""})
}
render() {
return (
<View style={{ flex: 1, marginTop: 30, paddingHorizontal: 20 }}>
<View style={{flexDirection: "row", alignItems: "center", justifyContent: "space-between"}}>
<TextInput style={{borderWidth: 1, borderColor: "black"}} onChangeText={textInput => this.setState({textInput})} placeholder="Enter todo text" value={this.state.textInput} />
<Button onPress={this.addNewTodo} title="Add todo" />
</View>
<FlatList
contentContainerStyle={{flexGrow: 1}}
data={this.state.todos}
extraData={this.state.todos}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => {
return (
<TodoItem todoItem={item} />
);
}}
/>
</View>
);
}
}
export default MainTodo;

use the code
mainTodo file:
import React, { Component } from 'react';
import { Text, View, StyleSheet, FlatList, ScrollView } from 'react-native';
import AddTodo from './AddTodo';
import TodoItem from './TodoItem';
class MainTodo extends Component {
constructor() {
super();
this.state = {
textInput: '',
todos: [
{ id: 0, title: 'walk rocky', completed: false },
{ id: 1, title: 'pickup dinner', completed: false }
]
};
}
addNewTodo() {
let todos = this.state.todos;
todos.unshift({
id: todos.length + 1,
todo: this.state.textInput,
completed: false
});
this.setState({
todos,
textInput: ''
});
}
render() {
return (
<View style={{ flex: 1 }}>
<AddTodo
textChange={textInput => this.setState({ textInput })}
addNewTodo={() => this.addNewTodo()}
textInput={this.state.textInput}
/>
<ScrollView>
<FlatList
style={{ flex: 1 }}
data={this.state.todos}
extraData={this.state}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => {
return (
<TodoItem todoItem={item} />
);
}}
/>
</ScrollView>
</View>
);
}
}
export default MainTodo;
TodoItem file:
import React, { Component } from 'react';
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
class TodoItem extends Component {
render() {
const todoItem = this.props.todoItem;
return (
<View>
<TouchableOpacity style={styles.todoItem}>
<Text style={(todoItem.completed) ? { color: '#aaaaaa' } : { color: '#313131' }}>
{todoItem.title}
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
todoItem: {
width: 40,
height: 40,
borderBottomColor: '#DDD',
borderBottomWidth: 1,
backgroundColor:'red',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingLeft: 15
}
});
export default TodoItem;

Related

How to use Redux in my React native Application

Here Home.js is Shows the both screen names
And Here Student.js screen is show only student contact numbers and Teacher.js
This is my full code..
And I have used navigation version 4
Navigation.js
import { createAppContainer } from 'react-navigation'
import { createStackNavigator } from 'react-navigation-stack'
import Home from '../screens/Home'
import Teacher from '../screens/Teacher'
import Student from '../screens/Student'
const StackNavigator = createStackNavigator(
{
Student: {
screen: Student
},
Home: {
screen: Home
},
Teacher: {
screen: Teacher
}
},
{
initialRouteName: 'Home',
headerMode: 'none',
mode: 'modal'
}
)
export default createAppContainer(StackNavigator)
Home.js
import React from 'react';
import { Text, View, TouchableOpacity, StyleSheet } from 'react-native';
export default class Home extends React.Component {
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ marginTop: 50, fontSize: 25 }}>Home!</Text>
<View
style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<TouchableOpacity
style={styles.button}
onPress={() => this.props.navigation.navigate('Teacher')}>
<Text>Teacher Numbers</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={() => this.props.navigation.navigate('Student')}>
<Text>Student Numbers</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10,
width: 300,
marginTop: 16,
},
});
Student.js
import React, { useState } from 'react'
import { StyleSheet, View, Button, FlatList } from 'react-native'
import { Text, FAB, List, IconButton, Colors, TextInput } from 'react-native-paper'
import { useSelector, useDispatch } from 'react-redux'
import { addnumber, deletenumber } from './../store/actions/studentList'
import Header from '../components/Header'
function StudentNumber({ navigation }) {
const [studentNumber, setStudentNumber] = useState('')
const snumbers = useSelector(state => state)
const dispatch = useDispatch()
const addNumber = number => dispatch(adbnumber(number))
const deleteNumber = id => dispatch(deletenumber(id))
function onSaveNumber() {
addNumber({studentNumber})
}
function FlatListItemSeparator () {
return (
//Item Separator
<View style={{height: 0.5, width: '100%', backgroundColor: '#C8C8C8'}}/>
);
};
function GetItem(item) {
//Function for click on an item
Alert.alert(item);
}
return (
<>
<View style={styles.container}>
<Button title="Go back" onPress={() => navigation.goBack()} />
<TextInput
label='Add a Number Here'
value={studentNumber}
mode='outlined'
onChangeText={setStudentNumber}
style={styles.title}
/>
{bnumbers.length === 0 ? (
<View style={styles.titleContainer}>
<Text style={styles.title}>You do not have any student numbers</Text>
</View>
) : (
<FlatList
data={snumbers}
ItemSeparatorComponent={FlatListItemSeparator}
renderItem={({ item }) => (
<List.Item
title={item.number.studentNumber}
descriptionNumberOfLines={1}
titleStyle={styles.listTitle}
onPress={() => deletestudentNumber(item.bid)}
/>
)}
keyExtractor={item => item.id.toString()}
/>
)}
<FAB
style={styles.fab}
small
icon='plus'
label='Add new number'
onPress={() => onSaveNumber()}
/>
</View>
</>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
paddingHorizontal: 10,
paddingVertical: 20
},
titleContainer: {
alignItems: 'center',
justifyContent: 'center',
flex: 1
},
title: {
fontSize: 20
},
fab: {
position: 'absolute',
margin: 20,
right: 0,
bottom: 10
},
listTitle: {
fontSize: 20
}
})
export default Student
Teacher.js
import React, { useState } from 'react'
import { StyleSheet, View, Button, FlatList } from 'react-native'
import { Text, FAB, List, IconButton, Colors, TextInput } from 'react-native-paper'
import { useSelector, useDispatch } from 'react-redux'
import { addnumber, deletenumber } from './../store/actions/teacherList'
import Header from '../components/Header'
function Teacher({ navigation }) {
const [teacherNumber, setTeacherNumber] = useState('')
const numbers = useSelector(state => state)
const dispatch = useDispatch()
const addNumber = number => dispatch(addnumber(number))
const deleteNumber = id => dispatch(deletenumber(id))
function onSaveNumber() {
addNumber({ teacherNumber})
}
function FlatListItemSeparator () {
return (
//Item Separator
<View style={{height: 0.5, width: '100%', backgroundColor: '#C8C8C8'}}/>
);
};
function GetItem(item) {
//Function for click on an item
Alert.alert(item);
}
return (
<>
<View style={styles.container}>
<Button title="Go back" onPress={() => navigation.goBack()} />
<TextInput
label='Add a Number Here'
value={teacherNumber}
mode='outlined'
onChangeText={setTeacherNumber}
style={styles.title}
/>
{numbers.length === 0 ? (
<View style={styles.titleContainer}>
<Text style={styles.title}>You do not have any teacher numbers</Text>
</View>
) : (
<FlatList
data={numbers}
ItemSeparatorComponent={FlatListItemSeparator}
renderItem={({ item }) => (
<List.Item
title={item.number.teacherNumber}
descriptionNumberOfLines={1}
titleStyle={styles.listTitle}
onPress={() => deleteNumber(item.id)}
/>
)}
keyExtractor={item => item.id.toString()}
/>
)}
<FAB
style={styles.fab}
small
icon='plus'
label='Add new number'
onPress={() => onSaveNumber()}
/>
</View>
</>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
paddingHorizontal: 10,
paddingVertical: 20
},
titleContainer: {
alignItems: 'center',
justifyContent: 'center',
flex: 1
},
title: {
fontSize: 20
},
fab: {
position: 'absolute',
margin: 20,
right: 0,
bottom: 10
},
listTitle: {
fontSize: 20
}
})
export default Teacher
studentStore.js
import { createStore } from 'redux'
import studentReducer from '../actions/studentList'
const studentStore = createStore(studentReducer)
export default studentStore
teacherStore.js
import { createStore } from 'redux'
import teacherReducer from '../actions/teacherList'
const teacherStore = createStore(teacherReducer)
export default teacherStore
teacherReducer.js
import remove from 'lodash.remove'
export const ADD_NUMBER = 'ADD_NUMBER'
export const DELETE_NUMBER = 'DELETE_NUMBER'
let numberID = 0
export function addnumber(number) {
return {
type: ADD_NUMBER,
id: numberID++,
number
}
}
export function deletenumber(id) {
return {
type: DELETE_NUMBER,
payload: id
}
}
const initialState = []
function teacherReducer(state = initialState, action) {
switch (action.type) {
case ADD_NUMBER:
return [
...state,
{
id: action.id,
number: action.number
}
]
case DELETE_NUMBER:
const deletedNewArray = remove(state, obj => {
return obj.id != action.payload
})
return deletedNewArray
default:
return state
}
}
export default teacherReducer
studetnReducer.js
import remove from 'lodash.remove'
export const ADD_NUMBER = 'ADD_NUMBER'
export const DELETE_NUMBER = 'DELETE_NUMBER'
let numberID = 0
export function addnumber(number) {
return {
type: ADD_NUMBER,
id: numberID++,
number
}
}
export function deletenumber(id) {
return {
type: DELETE_NUMBER,
payload: id
}
}
const initialState = []
function studentReducer(state = initialState, action) {
switch (action.type) {
case ADD_NUMBER:
return [
...state,
{
id: action.id,
number: action.number
}
]
case DELETE_NUMBER:
const deletedNewArray = remove(state, obj => {
return obj.id != action.payload
})
return deletedNewArray
default:
return state
}
}
export default studentReducer
I Have tried this but is working only for Teachers not for both..

React-native: how to store input value and data using AsyncStorage?

I have a form with a TextInput imported from react-native and DatePicker imported from native-base. I want to store their values on submit of the form using AsyncStorage.
I am getting an error: ReferenceError: ReferenceError:Input is not defined
This is component:
import React, { Component } from 'react';
import { View,StyleSheet, AsyncStorage, TextInput } from 'react-native';
import {
Form,
Button, Icon,
DatePicker, Text
} from 'native-base';
import PropTypes from 'prop-types';
class Reminder extends Component {
constructor(props) {
super(props);
this.state = {
input: '',
chosenDate: new Date(),
};
this.setDate = this.setDate.bind(this);
}
setDate(newDate) {
this.setState({
chosenDate: newDate
});
}
handleChangeInput = (text) => {
this.setState({input:text});
}
//On application loads, this will get the already saved data and set the state true when it's true.
componentDidMount() {
AsyncStorage.getItem("this.state.text").then((value) => {
this.setState({'this.state.text':value});
});
}
//save the input
saveData(value) {
console.log('value', value);
AsyncStorage.setItem("this.state", value);
this.setState({'this.state':value});
}
render() {
return (
<View>
<Form style={styles.formContainer}>
<View style={styles.formView}>
< TextInput
placeholder = "Set your reminder"
onChangeText={this.handleChangeInput}
value={input}
/>
<DatePicker
defaultDate={new Date()}
minimumDate={new Date(2018, 1, 1)}
maximumDate={new Date(2019, 12, 31)}
locale={"en"}
timeZoneOffsetInMinutes={undefined}
modalTransparent={false}
animationType={"fade"}
androidMode={"default"}
placeHolderText="Select date"
textStyle={{ color: "green" }}
placeHolderTextStyle={{ color: "#d3d3d3" }}
onDateChange={this.setDate}
/>
<Text style={styles.datePicker}>
{this.state.chosenDate.toString().substr(4, 12)}
</Text>
</View>
<View style={styles.footer}>
<Button block success style={styles.saveBtn}
onPress={ () =>
{this.saveData(value)
console.log('save data', value);}
}
>
<Icon type='MaterialIcons' name='done' />
</Button>
</View>
</Form>
</View>
);
}
}
const styles = StyleSheet.create({
formContainer: {
marginTop: 10,
padding: 10,
},
editIcon:{
color: '#28F1A6',
fontSize: 26,
},
editBtn:{
flex: 1,
alignSelf: 'flex-end',
},
datePicker:{
alignSelf: 'auto',
paddingLeft: 10
},
footer:{
position: 'relative',
top: 350
},
saveBtn: {
position:'relative',
marginTop: 35,
}
});
export default Reminder;
This is my screen:
import React, { Component } from 'react';
import { View, StatusBar } from 'react-native';
import PropTypes from 'prop-types';
import Reminder from '../components/Reminder';
const ReminderScreen = ({navigation}) => (
<View >
<Reminder navigation={navigation} >
<StatusBar backgroundColor = "#28F1A6" />
</Reminder >
</View>
);
Reminder.propTypes = {
navigation: PropTypes.object.isRequired
}
export default ReminderScreen;
I am fairly new to react-native. I am obviously doing missing out something, but not sure exactly what?
This is because in your TextInput component you set the props value to input instead of this.state.input
Or you can add this line before your return statement
const { input } = this.state;

Refresh to get new items in FlatList

I have this app.js to render many cards from Card.js,but only 3 cards to show at a time. In app.js I have refresh button that when I pressed will hide currently show cards (3 cards) and show 3 new cards.
App.js
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
StatusBar,
Linking,
FlatList
} from 'react-native';
import Card from './Card'
const data = [
{key: 'Devin'},
{key: 'Jackson'},
{key: 'James'},
{key: 'Joel'},
{key: 'John'},
{key: 'Jillian'},
{key: 'Jimmy'},
{key: 'Julie'}
]
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
itemsCount: 3,
hide: false
};
}
renderNewItem = () => {
if (this.state.itemsCount < data.length) {
this.setState((prevState) => ({ itemsCount: (prevState.itemsCount + 1) }));
}
}
renderCard = ({item}) => {
return (
<Card
text={item.key}
onPress={this.renderNewItem}
hide={this.state.hide}
/>
)
}
refreshItem = () => {
this.setState({hide: true})
if (this.state.itemsCount < data.length) {
this.setState((prevState) => ({ itemsCount: (prevState.itemsCount + 3) }));
}
}
render() {
return (
<View style={styles.container}>
<Text
style={{margin: 30, alignSelf: 'center'}}
onPress={this.refreshItem}
>
REFRESH ITEMS
</Text>
<FlatList
data={data.slice(0, this.state.itemsCount)}
keyExtractor={(item, index) => item.key}
renderItem={this.renderCard}
/>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center'
},
text: {
textAlign: 'center',
lineHeight: 30
}
});
Card.js
import React from 'react'
import {
Text,
View
} from 'react-native'
export default class Card extends React.Component {
render () {
if (this.props.hide) {
return null
}
return (
<View style={styles.viewStyle}>
<Text onPress={this.props.onPress}>{this.props.text}</Text>
</View>
)
}
}
const styles = {
viewStyle: {
height: 100,
width: 300,
justifyContent: 'center',
alignItems: 'center',
borderWidth: 2,
borderColor: 'black'
}
}
The problem is when I press refresh button, all cards disappear.
What I want is only currently showing cards to be disappeared and next 3 cards appear.

React Native : Access to component ref child in FlatList

I'm not able to access to component ref child in FlatList. On componentDidMount method, I've only one ref for the FlatList.
Here is my code in case you want to reproduce it:
import React, { Component } from "react";
import {
AppRegistry,
FlatList,
StyleSheet,
Text,
View
} from "react-native";
export default class touchable extends Component {
render() {
return (
<View style={styles.container}>
<FlatList
ref="REF-FLATLIST"
data={[{ key: "a" }, { key: "b" }]}
renderItem={({ item }) =>
<Text ref={`REF-FLATLIST${item.key}`}>
{item.key}
</Text>}
/>
</View>
);
}
componentDidMount() {
console.log(this.refs);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#F5FCFF"
}
});
AppRegistry.registerComponent("touchable", () => touchable);
I'm using React Native v0.45.1.
you can set it the ref using the ref callback this way:
import React, { Component } from "react";
import {
AppRegistry,
FlatList,
StyleSheet,
Text,
View
} from "react-native";
export default class touchable extends Component {
render() {
return (
<View style={styles.container}>
<FlatList
ref="REF-FLATLIST"
data={[{ key: "a" }, { key: "b" }]}
renderItem={({ item }) =>
<Text ref={(ref) => this.textRef = {...this.textRef, [`REF-FLATLIST${item.key}`]: ref}}>
{item.key}
</Text>}
/>
</View>
);
}
componentDidMount() {
console.log(this.refs, this.textRef);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#F5FCFF"
}
});

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

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.
It should look something like this:
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.
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;