create a customized scrollable top Tab bar using react-navigation-tab? - react-native

i need to create a customized scrollable top tab bar using react navigation tabs and tabBarComponent without using any other third party library.
const TopTabBar = createMaterialTopTabNavigator({
Home: HomePage,
Entertainment: EntertainmentNews,
Business: BusinessStack,
Music: MusicStack,
Politics: PoliticsStack,
Sports: SportsStack,
Technology: TechnologyStack,
WorldNews: WorldNewsStack
}, {
tabBarComponent: (props) => <TopTabBarComponent {...props}/>
})
In this with tab bar component i am able to create the top bar but it does not scroll when the screen are swiped ?
import React , { Component } from 'react'
import { Text, View, StyleSheet, FlatList, TouchableOpacity, Animated, Dimensions} from 'react-native'
interface Props {
navigation?: any
}
interface State {
//
}
export class TopTabBarComponent extends Component <Props, State>{
flatListRef
constructor(props: Props, state: State){
super(props, state)
}
onPressItem = (index) => {
const { navigation } = this.props
navigation.navigate( this.props.navigation.state.routes[index].routeName )
// this.onScrollIndex(index)
}
renderTopBar = (item, index) => {
const routes = this.props.navigation.state.routes
const activeIndex = this.props.navigation.state.index
return (
<TouchableOpacity style = {{
alignItems: 'center' ,
height: 50,
justifyContent: 'center',
borderBottomWidth: activeIndex === index ? 2 : 0,
borderColor: 'green',
paddingHorizontal: 5
}} onPress = {() => this.onPressItem(index)}>
<Text style = {{ fontSize: 20, color: 'blue'}}>{item.routeName}</Text>
</TouchableOpacity>
)
}
render() {
// reactotron.log('this.props', this.props.navigation)
console.warn('this.props.navigation.state.index', this.props.navigation.state.index)
return(
<View style = {{ marginHorizontal: 5}}>
<FlatList
initialScrollIndex = { this.props.navigation.state.index }
ref = {(ref) => { this.flatListRef = ref}}
// style = {{ paddingHorizontal: 20}}
horizontal
showsHorizontalScrollIndicator = {false}
data = {this.props.navigation.state.routes}
renderItem = {({item , index}) => this.renderTopBar(item, index) }
ItemSeparatorComponent = {() => <View style = {{ paddingRight: 40}}/>}
/>
</View>
)
}
}
This is top tab bar component code ? So how can i make the top tab scroll automatically when the screens are swiped ?

This is a sample to my tab bar that I quickly edited for your test case.
function MyTabBar({ state, descriptors, navigation, position }) {
const scrollViewRef = useRef(null)
useEffect(() => {
scrollViewRef.current.scrollTo({ x: state.index * 50, y: 0, animated: true })
}, [state.index])
return (
<View style={styles.tabContainer}>
<ScrollView ref={list => scrollViewRef.current = list} contentContainerStyle={{ flexDirection: 'row', alignItems: 'center'}} horizontal>
{state.routes.map((route, index) => {
const { options } = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;
const isFocused = state.index === index;
const onPress = () => {
const event = navigation.emit({
type: 'tabPress',
target: route.key,
});
if (!isFocused && !event.defaultPrevented) {
navigation.navigate(route.name);
}
};
const onLongPress = () => {
navigation.emit({
type: 'tabLongPress',
target: route.key,
});
};
let focusStyle = { }; //style object to append to the focussed tab
let tintColor = { };
let fontColor = { };
isFocused ? focusStyle = { backgroundColor: 'darkgray' } : focusStyle = { };
isFocused ? tintColor = { tintColor: 'black' } : tintColor = { tintColor: 'lightgray' }; // TODO: change this with proper fontColor codes
isFocused ? fontColor = { color: 'black' } : fontColor = { color: 'lightgray' };
//below controls the rendered tab
return (
<TouchableWithoutFeedback
key={index}
onPress={onPress}
onLongPress={onLongPress}
style={[styles.tabItem, focusStyle]}
>
<View style={styles.tabIconContainer}>
<LearnTabIcon title={route.name} color={tintColor} />
</View>
<Text style={[styles.labelStyle, fontColor]}>
{label}
</Text>
</TouchableWithoutFeedback>
);
})}
</ScrollView>
<View style={styles.tabBarIndicator}>
{ state.routes.map((route, index) => {
const isFocused = state.index === index;
let selectedStyle = { };
isFocused ? selectedStyle = { backgroundColor: 'darkgray'} : { }; // TODO: change this coloring to actual color codes
return (
<View
style={[styles.tabIndicators, selectedStyle]}
key={index}
>
</View>
);
})}
</View>
</View>
);
}
I'm using functional components for everything so it will look a bit different but in your custom tab bar grab the state.index on each index change and then use scrollToOffset to control where the scroll view is centered on screen. I put in a sample 50px offset scale just for simplicity.
I also wasn't using TypeScript but you seem to have most the boiler plate already ready to go anyway.

import React from 'react'
import {StatusBar} from 'react-native'
import {NavigationContainer} from '#react-navigation/native'
import {GestureHandlerRootView} from 'react-native-gesture-handler'
import {createMaterialTopTabNavigator} from '#react-navigation/material-top-tabs'
import HomeScreen from './screens/HomeScreen'
import LivingRoom from './screens/LivingRoom'
import Fav from './screens/Fav'
import Settings from './screens/Settings'
const Tab = createMaterialTopTabNavigator()
const AppRoot = () => {
return (
<GestureHandlerRootView className="flex-1">
<StatusBar hidden />
<NavigationContainer>
<Tab.Navigator
screenOptions={{
tabBarScrollEnabled: true,
tabBarIndicator: () => null,
tabBarStyle: {
backgroundColor: '#000',
},
tabBarItemStyle: {
width: 'auto',
alignItems: 'flex-start',
},
tabBarLabelStyle: {
fontSize: 30,
fontFamily: 'Satoshi-Black',
color: '#fff',
textTransform: 'capitalize',
},
}}
sceneContainerStyle={{backgroundColor: '#000'}}>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Living Room" component={LivingRoom} />
<Tab.Screen name="Fav" component={Fav} />
<Tab.Screen name="Settings" component={Settings} />
</Tab.Navigator>
</NavigationContainer>
</GestureHandlerRootView>
)
}
export default AppRoot

Related

how do I style my react native top tab navigation to have a background color and icons

I am a bit new to react native and I am having a bit of difficulty styling my top tab navigation
how do I style my react native top tab navigation to have a background color and icons
See code to my top tab navigation in react native
I have tried all I know, nothing seems to be working
see how I want it to look
see how it looks
see my code below
import "react-native-gesture-handler"
import React from "react"
import { DefaultTheme } from "#react-navigation/native"
import { AppearanceProvider, useColorScheme } from "react-native-appearance"
import { createMaterialTopTabNavigator } from "#react-navigation/material-top-tabs"
import { PersonalSetupScreen } from "./tabs/personal-setup"
import { CompanySetupScreen } from "./tabs/company-setup"
import { Images } from "../../config"
const Tab = createMaterialTopTabNavigator()
const MyDarkTheme = {
// Ovverride dark theme with your theme
dark: true,
colors: {
primary: "rgb(255, 255, 255)",
background: "rgb(33, 20, 122)",
card: "rgb(255, 255, 255)",
text: "rgb(255, 255, 255)",
border: "rgb(199, 199, 204)",
notification: "rgb(255, 69, 58)",
},
}
export default function HomeTabs() {
const scheme = useColorScheme()
return (
<Tab.Navigator >
<Tab.Screen
name="PersonalSetup"
component={PersonalSetupScreen}
options={({ navigation }) => ({
tabBarLabel: "Personal Details",
activeTintColor: "#21147a",
inactiveTintColor: "21147a",
activeBackgroundColor: "#21147a",
inactiveBackgroundColor: "#21147a",
style: {
backgroundColor: "#21147a",
},
})}
/>
<Tab.Screen
name="CompanySetup"
component={CompanySetupScreen}
options={({ navigation }) => ({
tabBarLabel: "Company Details",
activeTintColor: "#21147a",
inactiveTintColor: "21147a",
activeBackgroundColor: "#21147a",
inactiveBackgroundColor: "#21147a",
style: {
backgroundColor: "#21147a",
},
})}
/>
</Tab.Navigator>
)
}
import { createMaterialTopTabNavigator } from '#react-navigation/material-top-tabs';
const TopTab = createMaterialTopTabNavigator();
const Tab = () => {
return (
<TopTab.Navigator
screenOptions={{
tabBarActiveTintColor:'white',
tabBarIndicatorStyle: {
backgroundColor: 'white',
height: 2
},
tabBarScrollEnabled: true,
tabBarLabelStyle: {fontSize: 20},
tabBarItemStyle: { width: 150, },
tabBarStyle: {
height: 40,
backgroundColor: '#c21a0c',
},
}}
>
<TopTab.Screen name ='PERSONAL DETAILS' component={Personal} Options={{
tabBarIcon: () => (
<MaterialCommunityIcons name="search-web" size={24} />
)}} />
<TopTab.Screen name ='COMPANY DETAILS' component = {Company} />
<TopTab.Screen name ='CONTACT DETAILS' component = {FOX} />
<TopTab.Screen name ='PROFILE' component = {Google} />
</TopTab.Navigator>
)
}
According to the documentation here: Material Top Tab Navigator
You can pass in a tabBarIcon.
You can also pass your own custom component as a TabBar Button that you can style however you want (Text + Icon + BackgroundColor ...)
you might have already found out the solution.
Here is the complete example from reactnavigation.org.
import { Animated, View, TouchableOpacity } from 'react-native';
function MyTabBar({ state, descriptors, navigation, position }) {
return (
<View style={{ flexDirection: 'row' }}>
{state.routes.map((route, index) => {
const { options } = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;
const isFocused = state.index === index;
const onPress = () => {
const event = navigation.emit({
type: 'tabPress',
target: route.key,
canPreventDefault: true,
});
if (!isFocused && !event.defaultPrevented) {
// The `merge: true` option makes sure that the params inside the tab screen are preserved
navigation.navigate({ name: route.name, merge: true });
}
};
const onLongPress = () => {
navigation.emit({
type: 'tabLongPress',
target: route.key,
});
};
const inputRange = state.routes.map((_, i) => i);
const opacity = position.interpolate({
inputRange,
outputRange: inputRange.map(i => (i === index ? 1 : 0)),
});
return (
<TouchableOpacity
accessibilityRole="button"
accessibilityState={isFocused ? { selected: true } : {}}
accessibilityLabel={options.tabBarAccessibilityLabel}
testID={options.tabBarTestID}
onPress={onPress}
onLongPress={onLongPress}
style={{ flex: 1 }}
>
<Animated.Text style={{ opacity }}>
{label}
</Animated.Text>
</TouchableOpacity>
);
})}
</View>
);
}
// ...
<Tab.Navigator tabBar={props => <MyTabBar {...props} />}>
{...}
</Tab.Navigator>
Reference: https://reactnavigation.org/docs/material-top-tab-navigator/#tabbar
For more information, please go through this link.

Searchable flat list react native

I am trying to search items in a flatlist, whenever i type in the search bar it only take one letter and closes the keyboard and the value inside the search bar disappear,
example when i type "george" it only takes the letter g and re-render a list of names containing the letter g and delete what's inside the search bar
how can i fix this ?
import React, { useState, useEffect } from 'react';
import { ScrollView } from 'react-native';
import { View, Text, FlatList, ActivityIndicator, SafeAreaView, TouchableOpacity } from 'react-native';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { Divider, SearchBar } from 'react-native-elements'
const Item = ({ name, lastName }) => (
<View>
<Text style={{ fontSize: 17, color: '#666', marginBottom: 10 }}>Full name: {name} {lastName}</Text>
</View>);
function Clients({ navigation }) {
const [isLoading, setLoading] = useState(true);
const usersApi = 'https://reqres.in/api/users'
const [users, setUsers] = useState([]);
const [search, setSearch] = useState("");
const [masterData, setMasterData] = useState("");
const fetchJson = async (userApi) => {
const response = await fetch(userApi);
return response.json()
}
useEffect(() => {
fetchJson(usersApi)
.then((users) => {
setUsers(users.data);
setMasterData(users.data);
})
.catch((error) => (alert(error)))
.finally(() => setLoading(false));
}, []);
const itemSeparator = () => {
return (
<Divider style={{ width: "105%", marginVertical: 3, alignSelf: 'center' }} />
)
}
const renderHeader = () => {
return (
<SearchBar
placeholder="Type Here..."
lightTheme
round
onChangeText={text => searchFilterFunction(text)}
autoCorrect={false}
/>
);
};
const searchFilterFunction = text => {
setSearch(text);
const newData = masterData.filter(item => {
const itemData = `${item.first_name.toUpperCase()} ${item.last_name.toUpperCase()}`;
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
setUsers(newData);
};
const renderItem = ({ item }) => (
<TouchableOpacity style={{
flex: 1,
padding: 10
}}
onPress={() => { navigation.navigate('Client', { item: item }); }}
underlayColor='#ccc'
activeOpacity={0.1} >
<Item name={item.first_name} lastName={item.last_name} />
</TouchableOpacity>
);
console.log(search)
console.log(users)
return (
<SafeAreaProvider>
<SafeAreaView>
<Text style={{ color: '#666', margin: 15, fontSize: 20 }}>Clients actuels</Text>
<View style={{
width: '96%',
backgroundColor: 'white',
borderRadius: 5,
alignSelf: 'center',
marginTop: 20,
}}>
<View style={{ margin: 15 }}>
{isLoading ? <ActivityIndicator size="large" /> :
<FlatList
data={users}
renderItem={renderItem}
ItemSeparatorComponent={itemSeparator}
ListHeaderComponent={renderHeader}
keyExtractor={item => item.id.toString()}
value={search}
/>}
</View>
</View>
</SafeAreaView>
</SafeAreaProvider>
);
}
export default Clients;

How to call Parent component function inside custom drawer

I am beginner in React Native. I am getting stuck in one issue. I have one Parent component Home.js in which there is Tab navigator on click of tab 3 child components replace based on selected key. In same page, I have custom drawer.Now, I want to change tabs on click of custom drawer's option & same thing when my 1st tab selected 1st option of drawer also set selected. How can i achieve this.
Here is my navigation Drawer :
export default MyDrawerNavigator = DrawerNavigator({
Page1: {
screen: props => <Home {...props} />,
}
},
{
contentComponent: props => (<CustomSideMenu {...props} />),
drawerWidth: (getScreenWidth() * 2.5) / 3,
}
);
Here is my Home class I want to access goToNextTab() inside Custom drawer
export class Home extends React.Component {
static navigationOptions = hidenavigation;
constructor(props) {
super(props);
}
apply_header = (val) => {
this.props.navigation.setParams({ Title: val });
}
goToNextTab = (tabName) => {
this.setState({ activeTab: tabName });
}
openDrawer() {
this.props.navigation.openDrawer();
}
tabs = [{
key: 'Dashboard',
icon: 'speedometer',
label: 'Dashboard',
pressColor: 'rgba(255, 255, 255, 0.16)'
},
{
key: 'Add Diamond',
icon: 'plus-circle-outline',
label: 'Add Diamond',
pressColor: 'rgba(255, 255, 255, 0.16)'
},
{
key: 'Diamond',
icon: 'diamond-stone',
label: 'Diamond',
pressColor: 'rgba(255, 255, 255, 0.16)'
}]
state = {
activeTab: 'Dashboard',
showFooter: true
};
renderIcon = icon => ({ isActive }) => (
<Icon size={24} color={isActive ? COLOR.action_bar : COLOR.tab_deselected_text_color} name={icon} />
)
renderTab = ({ tab, isActive }) => (
<FullTab isActive={isActive} key={tab.key} label={tab.label} labelStyle={isActive ? style.activeText : style.deactiveText} renderIcon={this.renderIcon(tab.icon)} />
)
render() {
const propsForChild = {
goToNextTab: (tabName) => this.goToNextTab(tabName),
openDrawer: () => this.openDrawer()
};
const propsForNav = {
nav: this.props,
openDrawer: () => this.openDrawer()
};
const addDimPropsForChild = {
openDrawer: () => this.openDrawer()
}
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
{
this.state.activeTab === 'Add Diamond' ? <Add_Dimond_Stack screenProps={addDimPropsForChild} /> : this.state.activeTab === 'Diamond' ? <Dimond_List_stack screenProps={propsForNav} /> : <Dashboard_Stack screenProps={propsForChild} />
}
</View>
{
this.state.showFooter ?
<BottomNavigation activeTab={this.state.activeTab} renderTab={this.renderTab} tabs={this.tabs} onTabPress={newTab => { this.setState({ activeTab: newTab.key }); }} />
: null
}
</View>
);
}
componentWillMount() {
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow.bind(this));
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide.bind(this));
}
componentWillUnmount() {
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
}
_keyboardDidShow() {
//alert('Keyboard Shown');
this.setState({ showFooter: false })
}
_keyboardDidHide() {
//alert('Keyboard Hidden');
this.setState({ showFooter: true })
}
componentDidMount() {
printLogs('call', 'componentDidMount')
const { setParams } = this.props.navigation;
setParams({ myProps: 'test' });
}
}
Here is my Custom Drawer in which i want to access setSelectedPos() from Home tab click
export default class Custom_Side_Menu extends React.Component {
static navigationOptions = { hidenavigation };
state = {
current_selected: 0
}
setSelectedPos(pos) {
this.setState({ current_selected: pos });
}
closeNavigationPanel(pos) {
if (pos != 3) {
this.props.navigation.closeDrawer();
}
}
redirectToProfile() {
new NavigationRedirection().goToNextScreen('profile', this.props);
}
selectedColor(pos) {
if (this.state.current_selected === pos) {
return COLOR.input_text_color;
} else {
return COLOR.input_hint_color;
}
}
render() {
return (
<ScrollView>
<View style={stylePage.bg}>
{/* */}
<View style={{ flex: 1 }}>
<View style={{ padding: 10, alignContent: 'center', flexDirection: 'row', alignItems: 'center' }}>
<TouchableOpacity onPress={() => { this.closeNavigationPanel() }}>
<Icon name="arrow-left" size={30} color={COLOR.input_text_color} />
</TouchableOpacity>
<Text style={stylePage.menu_title}>Menu</Text>
</View>
<TouchableWithoutFeedback onPress={() => {
this.redirectToProfile();
}}>
<View>
<Image style={stylePage.profileImage} source={{ uri: 'https://uinames.com/api/photos/female/22.jpg' }} />
<Text style={stylePage.name}>Ruth McCoy</Text>
<Text style={stylePage.email}>ruth.mccoy#example.com</Text>
</View>
</TouchableWithoutFeedback>
<View style={stylePage.line_seprator} />
<View style={stylePage.menu_options}>
<Text style={[stylePage.menu_text, { color: this.selectedColor(0) }]} onPress={() => this.setCurrentSelection(0)}>Dashboard</Text>
<Text style={[stylePage.menu_text, { color: this.selectedColor(1) }]} onPress={() => this.setCurrentSelection(1)}>Diamonds List</Text>
<Text style={[stylePage.menu_text, { color: this.selectedColor(2) }]} onPress={() => this.setCurrentSelection(2)}>Add diamonds</Text>
<Text style={[stylePage.menu_text, { color: this.selectedColor(3) }]} onPress={() => this.setCurrentSelection(3)}>Profile</Text>
<Text style={[stylePage.menu_text, { color: this.selectedColor(4) }]} onPress={() => this.setCurrentSelection(4)}>Change Password</Text>
</View>
</View>
<TouchableOpacity style={{ alignSelf: 'baseline' }} onPress={() => clearAllData(this.props)}>
<View style={stylePage.logout_btn}>
<IconAnt name="logout" size={25} color={COLOR.white} />
<Text style={stylePage.logout_title}>Logout</Text>
</View>
</TouchableOpacity>
<RBSheet
closeOnDragDown={true}
closeOnPressMask={false}
ref={ref => { this.RBSheet = ref }}
height={getScreenHeight() / 2} duration={250} customStyles={{
container: { padding: 10, borderTopLeftRadius: 20, borderTopRightRadius: 20 },
}}>
<ChangePassword {...this.props} RBSheet={this.RBSheet} />
</RBSheet>
</View>
</ScrollView>
);
}
setCurrentSelection(pos) {
this.closeNavigationPanel(pos);
this.setSelectedPos(pos);
if (pos === 3) {
this.redirectToProfile();
} else if (pos === 4) {
this.RBSheet.open();
} else {
printLogs('props', this.props.navigation)
}
}
}
There are two problems.
Click on drawer options to change the navigation tab
On tab change set the option as active
using redux as global store
There is an easy way out if you need redux as your global store.
first connect your components with react-redux connect
manage the activeTab state in store instead of component state
then on click of drawer option change the state in redux for your activetab
this way you are able to solve the problem 1
Also make sure you check activetab from store if matched you can update the styling for active option in drawer . So here is solution for problem 2
Using tab navigator from react-navigation
another option is using tabNavigator from react-navigation itself that way you only need to call navigator function for changing tab
and getting the active tab from navigation state
* alternate to redux *
you can use react context apis for managing your parent state if you are not using redux

How to stick the comment input box on top of keyboard [duplicate]

So I need to align a button Which is not at bottom om screen by design should be at middle of screen but it should align to be on top of the keyboard for all devices.
If you check this screenshot :
for Some devices I mange to do it, but in some others is not really aligned :
how can I manage this to work in all?
this is what I did so far :
<Padding paddingVertical={isKeyboardOpen ? Spacing.unit : Spacing.small}>
<Button
variant="solid"
label='Next'
style={styles.submitBtn}
/>
</Padding>
And isKeyboardOpen is just a method which will create a listner based on the platform return true if keyboard is open :
Keyboard.addListener(
Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow',
true
);
And submitBrn css class is :
submitBtn: {
margin: Spacing.base,
},
First import this packages
import {
Button,
ScrollView,
KeyboardAvoidingView,
TextInput,
} from 'react-native';
Render method
<KeyboardAvoidingView
{...(Platform.OS === 'ios' ? { behavior: 'padding' } : {})}
style={styles.container}>
<ScrollView style={styles.scrollView}>
<TextInput style={styles.input} placeholder="Tap here" />
</ScrollView>
<Button title="Next" />
</KeyboardAvoidingView>
This are the styles
const styles = StyleSheet.create({
container: {
flex: 1,
},
scrollView: {
paddingHorizontal: 20,
},
input: {
marginBottom: 20,
borderBottomWidth: 2,
borderColor: '#dbdbdb',
padding: 10,
},
});
Make sure the button is outside the scrollview.
NOTE: You may need to adjust the offset prop of KeyboardAvoidingView if the keyboard has got autocomplete enabled.
Stick button at the bottom of the screen demo
In case anyone is still looking for a solution to this I am posting a working example from October 2021 along with the react native documentation. This example is for a text input that when focused has a button labeled 'Scanner' above the keyboard. React native documentation refers to what we are creating here as a 'toolbar'.
Please see this for further details https://reactnative.dev/docs/next/inputaccessoryview
import {
Button,
ScrollView,
TextInput,
StyleSheet,
InputAccessoryView,
Text,
View,
} from "react-native";
import { MaterialCommunityIcons } from "#expo/vector-icons";
import { BarCodeScanner } from "expo-barcode-scanner";
import { useFocusEffect } from "#react-navigation/native";
function CreateSearchBar() {
const inputAccessoryViewID = "uniqueID";
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
const [showScanner, setShowScanner] = useState(false);
useEffect(() => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === "granted");
})();
}, []);
useFocusEffect(
React.useCallback(() => {
// Do something when the screen is focused
return () => {
// Do something when the screen is unfocused
// Useful for cleanup functions
setShowScanner(false);
};
}, [])
);
onChangeSearch = (search) => {};
setScannerShow = (show) => {
setShowScanner(show);
};
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true);
setShowScanner(false);
alert(`Bar code with type ${type} and data ${data} has been scanned!`);
};
if (hasPermission === null) {
return <Text>Requesting for camera permission</Text>;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
if (showScanner) {
return (
<View style={styles.scanner}>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
style={StyleSheet.absoluteFillObject}
/>
{scanned && (
<Button
title={"Tap to Scan Again"}
onPress={() => setScanned(false)}
/>
)}
</View>
);
}
return (
<>
<ScrollView keyboardDismissMode="interactive">
<View style={styles.input}>
<MaterialCommunityIcons name="magnify" size={24} color="black" />
<TextInput
onChangeText={onChangeSearch}
inputAccessoryViewID={inputAccessoryViewID}
placeholder="Find items or offers"
/>
<MaterialCommunityIcons
name="barcode"
size={30}
color="black"
onPress={() => setScannerShow(true)}
/>
</View>
</ScrollView>
<InputAccessoryView nativeID={inputAccessoryViewID}>
<Button onPress={() => setScannerShow(true)} title="Scanner" />
</InputAccessoryView>
</>
);
}
const styles = StyleSheet.create({
input: {
height: 40,
margin: 12,
borderWidth: 1,
padding: 10,
flexDirection: "row",
justifyContent: "space-between",
},
scanner: {
height: "50%",
},
});
export default CreateSearchBar;
YOu can use react native modal
<KeyboardAvoidingView
keyboardVerticalOffset={Platform.OS == "ios" ? 10 : 0}
behavior={Platform.OS == "ios" ? "padding" : "height"} style={{ flex: 1 }} >
<Modal>
<ScrollView>
<Content><-------Your content------></Content>
</ScrollView>
<BottomButton />
</Modal>
</KeyboardAvoidingView>

How to change the color of active tab ? (tab is custom)

I am using react-navigation in RN v 0.46.1 project
I have used customTabs from example directory of react-navigation.
I want to change the color of the tab when active .
I've tried to pass ans use navigationOptions but no success.
Also , Tabs are displayed at top , I want them at bottom.
import React, { Component } from "react";
import { AppRegistry, Button,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View } from "react-native";
import { createNavigator,
createNavigationContainer,
TabRouter,
addNavigationHelpers } from 'react-navigation'
import Chats from './Chats'
import Contacts from './Contacts'
const MyNavScreen = ({ navigation, banner }) => (
<ScrollView>
<Text>banner</Text>
<Button
onPress={() => {
navigation.goBack(null);
}}
title="Go back"
/>
</ScrollView>
);
const MySettingsScreen = ({ navigation }) => (
<MyNavScreen banner="Settings Screen" navigation={navigation} />
);
const CustomTabBar = ({ navigation }) => {
const { routes } = navigation.state;
return (
<View style={styles.tabContainer}>
{routes.map(route => (
<TouchableOpacity
onPress={() => navigation.navigate(route.routeName)}
style={styles.tab}
key={route.routeName}
>
<Text>{route.routeName}</Text>
</TouchableOpacity>
))}
</View>
);
};
const CustomTabView = ({ router, navigation }) => {
const { routes, index } = navigation.state;
const ActiveScreen = router.getComponentForState(navigation.state);
const routeNav = addNavigationHelpers({
...navigation,
state: routes[index],
});
const routeOptions = router.getScreenOptions(routeNav, 'tabBar');
console.log(routeOptions.headerTintColor);
return (
<View style={styles.container}>
<CustomTabBar navigation={navigation} />
<ActiveScreen
navigation={addNavigationHelpers({
...navigation,
state: routes[index],
})}
/>
</View>
);
};
const CustomTabRouter = TabRouter(
{
Friends: {
screen: Chats,
path: '',
},
Status: {
screen: Contacts,
path: 'notifications',
},
Other: {
screen: MySettingsScreen,
path: 'settings',
},
},
{
initialRouteName: 'Friends',
},
);
const CustomTabs = createNavigationContainer(
createNavigator(CustomTabRouter)(CustomTabView)
);
const styles = StyleSheet.create({
container: {
marginTop: Platform.OS === 'ios' ? 20 : 0,
},
tabContainer: {
flexDirection: 'row',
height: 48,
},
tab: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
margin: 4,
borderWidth: 1,
borderColor: '#ddd',
borderRadius: 4,
backgroundColor:'white'
},
});
export default CustomTabs;
AppRegistry.registerComponent('awsm', () => CustomTabs);
Compare the active tab's routeName in map and add style like
style={[(this.props.activeRouteName == route.routeName) ? styles.activeTab : styles.tab]}
For styling tabs at bottom you can use ScrollView in parent view and then your tabs so, it will be something like this
<View style={flex:1}>
<ScrollView>
// your page content
</ScrollView>
<Tabs/>
</View>
By using scrollview you will be able to force the tabs at bottom.
Can't you achieve what you want with the default TabNavigator ?
In the docs you can pass a TabBarComponent to the TabNavigator and set tabBarPosition - position of the tab bar, can be 'top' or 'bottom' to bottom so your tabBar will be at the bottom.
If you still want to do all that yourself, I guess :
To align the TabBar on the bottom, you could put { position: 'absolute', bottom: 0 } on the TabBar style
To change the color of your focused Tab, you could do:
const CustomTabBar = ({ navigation }) => {
const { routes, index } = navigation.state;
const isFocused = routes[index].routeName == route.routeName; // Not totally sure about the condition there, but you get the idea?
return (
<View style={styles.tabContainer}>
{routes.map(route => (
<TouchableOpacity
onPress={() => navigation.navigate(route.routeName)}
style={[styles.tab, isFocused ? styles.focusedTab : null]}
key={route.routeName}
>
<Text>{route.routeName}</Text>
</TouchableOpacity>
))}
</View>
);
};
?