How can I change the text in TabBarIOS in React Native? - react-native

In the react native documentation I cannot find a way to change the bottom words?
<TabBarItemIOS
name="greenTab"
icon={_ix_DEPRECATED('more')}
accessibilityLabel="Green Tab"
selected={this.state.selectedTab === 'greenTab'}
onPress={() => {
this.setState({
selectedTab: 'greenTab',
presses: this.state.presses + 1
});
}}>
{this._renderContent('#21551C', 'Green Tab')}
</TabBarItemIOS>
What is the accessibilityLabel ?

The TabBarItem allows you to use one of the iOS preset icons from UITabBarSystemItem, and in your sample code it's using the "More" icon. Crucially though, the documentation for UITabBarSystemItem states:
The title and image of system tab bar items cannot be changed.
If you set the icon to either a data-uri or a local image, rather than an icon from UITabBarSystemItem, you'll be able to override the text on the item to whatever you want using the title prop.

You can try something like that for your TabBarIOS.Item with a custom icon
import React, { Component } from 'react'
import { AppRegistry, StyleSheet, Text, View, TouchableOpacity, TabBarIOS } from 'react-native'
const base64Icon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAABLCAQAAACSR7JhAAADtUlEQVR4Ac3YA2Bj6QLH0XPT1Fzbtm29tW3btm3bfLZtv7e2ObZnms7d8Uw098tuetPzrxv8wiISrtVudrG2JXQZ4VOv+qUfmqCGGl1mqLhoA52oZlb0mrjsnhKpgeUNEs91Z0pd1kvihA3ULGVHiQO2narKSHKkEMulm9VgUyE60s1aWoMQUbpZOWE+kaqs4eLEjdIlZTcFZB0ndc1+lhB1lZrIuk5P2aib1NBpZaL+JaOGIt0ls47SKzLC7CqrlGF6RZ09HGoNy1lYl2aRSWL5GuzqWU1KafRdoRp0iOQEiDzgZPnG6DbldcomadViflnl/cL93tOoVbsOLVM2jylvdWjXolWX1hmfZbGR/wjypDjFLSZIRov09BgYmtUqPQPlQrPapecLgTIy0jMgPKtTeob2zWtrGH3xvjUkPCtNg/tm1rjwrMa+mdUkPd3hWbH0jArPGiU9ufCsNNWFZ40wpwn+62/66R2RUtoso1OB34tnLOcy7YB1fUdc9e0q3yru8PGM773vXsuZ5YIZX+5xmHwHGVvlrGPN6ZSiP1smOsMMde40wKv2VmwPPVXNut4sVpUreZiLBHi0qln/VQeI/LTMYXpsJtFiclUN+5HVZazim+Ky+7sAvxWnvjXrJFneVtLWLyPJu9K3cXLWeOlbMTlrIelbMDlrLenrjEQOtIF+fuI9xRp9ZBFp6+b6WT8RrxEpdK64BuvHgDk+vUy+b5hYk6zfyfs051gRoNO1usU12WWRWL73/MMEy9pMi9qIrR4ZpV16Rrvduxazmy1FSvuFXRkqTnE7m2kdb5U8xGjLw/spRr1uTov4uOgQE+0N/DvFrG/Jt7i/FzwxbA9kDanhf2w+t4V97G8lrT7wc08aA2QNUkuTfW/KimT01wdlfK4yEw030VfT0RtZbzjeMprNq8m8tnSTASrTLti64oBNdpmMQm0eEwvfPwRbUBywG5TzjPCsdwk3IeAXjQblLCoXnDVeoAz6SfJNk5TTzytCNZk/POtTSV40NwOFWzw86wNJRpubpXsn60NJFlHeqlYRbslqZm2jnEZ3qcSKgm0kTli3zZVS7y/iivZTweYXJ26Y+RTbV1zh3hYkgyFGSTKPfRVbRqWWVReaxYeSLarYv1Qqsmh1s95S7G+eEWK0f3jYKTbV6bOwepjfhtafsvUsqrQvrGC8YhmnO9cSCk3yuY984F1vesdHYhWJ5FvASlacshUsajFt2mUM9pqzvKGcyNJW0arTKN1GGGzQlH0tXwLDgQTurS8eIQAAAABJRU5ErkJggg=='
class ReactNativePlayground extends Component {
constructor(props) {
super(props)
this.state = {
selectedTab: "more",
tabBarItemTitle: "More"
}
}
render() {
return (
<TabBarIOS>
<TabBarIOS.Item selected={this.state.selectedTab === "more"}
title={this.state.tabBarItemTitle}
icon={{uri: base64Icon, scale: 3}}>
<View style={styles.container}>
<TouchableOpacity onPress={ (event) => { this._changeTabItemTitle() } }>
<Text style={styles.button}>Tap to Change Item Title</Text>
</TouchableOpacity>
</View>
</TabBarIOS.Item>
</TabBarIOS>
);
}
_changeTabItemTitle() {
this.setState({ tabBarItemTitle: "New More" })
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
button: {
fontSize: 20,
color: "white",
textAlign: 'center',
backgroundColor: "#1155DD",
borderRadius: 5,
height: 30,
margin: 30,
},
});
AppRegistry.registerComponent('ReactNativePlayground', () => ReactNativePlayground);

Related

How to change only the active button background color [React-Native]

import React, { Component } from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
class App extends Component {
constructor(props){
super(props)
this.state={
selected:null
}
}
handle=()=>{
this.setState({selected:1})
}
render() {
return (
<View>
<TouchableOpacity style={[styles.Btn, {backgroundColor:this.state.selected===1?"green":"white"}]} onPress={this.handle}>
<Text style={styles.BtnText}>Button 1</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.Btn} onPress={this.handle}>
<Text style={styles.BtnText}>Button 2</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.Btn} onPress={this.handle}>
<Text style={styles.BtnText}>Button 3</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
Btn: {
borderWidth: 1,
width: 100,
height: 20,
borderRadius: 8,
margin: 5,
padding: 10,
justifyContent: 'center',
flexDirection: 'row',
alignItems: 'center',
},
BtnText: {
fontSize: 15,
},
});
export default App;
Snack Link : https://snack.expo.dev/U_fX-6Tao-
I want to make it so when I click a button, the active button backgroundColor should change to "green" and text to "white" and the rest of the buttons backgroundColor and textColor should stay "red". But when I click another button then that button should become active and the previous active button should get back to its normal state.
It would be wonderful if you could also explain the logic behind it as I'm a newbie in React Native.
Thank you.
You are always setting the active button to the first one. Also, I would use an array to render the buttons. I would do something like this:
class App extends Component {
constructor(props){
super(props)
this.state = {
selected: null
}
}
handlePress = (item) => {
this.setState({ selected: item })
}
render() {
return (
<View>
{[...Array(3).keys()].map((item) => {
return (
<TouchableOpacity key={item} style={[styles.Btn, {backgroundColor: this.state.selected === item ? "green" : "white" }]} onPress={() => this.handlePress(item)}>
<Text style={styles.BtnText}>Button {item + 1}</Text>
</TouchableOpacity>
)
})}
</View>
);
}
}
I created an Themed component(OK I did not create it. It is there when I create the app with Expo).
import { useState } from 'react';
import { TouchableOpacity as DefaultTouchableOpacity } from 'react-native';
export type TouchableProps = DefaultTouchableOpacity['props'] & { activeBgColor?: string };
export function TouchableOpacity(props: TouchableProps) {
const [active, setActive] = useState(false);
const { style, activeBgColor, ...otherProps } = props;
if (activeBgColor) {
return (
<DefaultTouchableOpacity
style={[style, active ? { backgroundColor: activeBgColor } : {}]}
activeOpacity={0.8}
onPressIn={() => setActive(true)}
onPressOut={() => setActive(false)}
{...otherProps}
/>
);
}
return <DefaultTouchableOpacity style={style} activeOpacity={0.8} {...otherProps} />;
}
Then I use this TouchableOpacity everywhere.
<TouchableOpacity
style={tw`rounded-sm h-10 px-2 justify-center items-center w-1/5 bg-sky-400`}
activeBgColor={tw.color('bg-sky-600')}
>
<Text style={tw`text-white font-bold`}>a Button</Text>
</TouchableOpacity>
Oh I am writing TailwindCSS with twrnc by the way. You will love it.
See the screenshot below.

trying to expand or reduce view within a `Flatlist` when clicking on them based on their current state

I am trying to expand or reduce view within a Flatlist when clicking on them based on their current state. I am using data within mobx and connecting it to a react component. Even though console.log confirms that the state is changing after clicking on the view, it does not expand when clicked upon. It was working when the data was a react state, but I had to move it to mobx due to diverse interactions within the software. I think the action syntax and logic has to be changed or it might something else. Please can anyone help?
mobx code below:
import {observable, action} from 'mobx';
import {LayoutAnimation} from 'react-native'
class StateStorage {
#observable materials = [
{
name: 'RAG',
price: '$',
image: require("./Icons/RAG.jpg"),
expanded: false
},
{
name: 'GRAPE',
price: '$',
image: require("./Icons/GRAPE.jpg"),
expanded: false
},
{
name: 'FLAG',
price: '$',
image: require("./Icons/FLAG.jpg"),
expanded: false
},
#action changeLayout(index) {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
this.materials[index].expanded= !this.materials[index].expanded
console.log(this.materials[index].expanded)
}
#action chooseMaterial(index){
this.selectedMaterial = this.materials[index].name
console.log(this.selectedMaterial)
}
export default new StateStorage();
React-native code below:
import React, { Component } from 'react';
import { View, Text, FlatList, Image, ImageBackground, PixelRatio, Platform, UIManager, TouchableOpacity, LayoutAnimation }
from 'react-native';
import {widthPercentageToDP as wp, heightPercentageToDP as hp} from 'react-native-responsive-screen'
import DropDownItem from 'react-native-drop-down-item';
import StateStorage from './StateStorage';
import {observer} from 'mobx-react';
#observer
class App extends Component {
constructor (props) {
super(props)
this.state ={
}
if (Platform.OS === 'android') {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
}
render() {
return (
<View
style={{
backgroundColor:'#262A2C',
flex:1
}}>
<FlatList
style={{marginTop:80,}}
data={StateStorage.materials}
renderItem={({ item, index }) => (
<View style={{}}>
<TouchableOpacity
onPress={() =>{
StateStorage.chooseMaterial(index)
}}>
<ImageBackground
source={item.image}
//pay FlatIcon or design personal one
style={{
resizeMode: 'contain',
position:'relative',
width: wp('100%'),
left: wp('0%'),
borderBottomWidth: 1,
borderBottomColor: 'grey',
padding: hp('6%'),
}}
>
</ImageBackground>
</TouchableOpacity
<TouchableOpacity activeOpacity={0.8}
onPress={() => {
StateStorage.changeLayout(index)
}}
style={{ padding: 10,
backgroundColor:'black',
left:wp('-10.9%'),
top:hp('0%'),
width: wp('120%'),
height:hp('5%')}}>
<Image
style={{
width:wp('9%'),
height:hp('4.5%'),
tintColor:'white',
left:250,
top:-10
//tintColor:'#81F018'
}}
source={StateStorage.materials[index].expanded ? require('./Icons/arrowDown.png') : require('./Icons/arrowUp.png') }/>
</TouchableOpacity>
<View style={{height: StateStorage.materials[index].expanded ? null : 0,
overflow: 'hidden',
backgroundColor:'black' }}>
<Text
style={{
fontSize: 17,
left:150,
top:-10,
color: 'turquoise',
padding: 10}}>
Specs
</Text>
</View>
</View>
)}
}
export default App
Before the state was moved to mobx, I was using this method to make it work:
changeLayout = ({index}) => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
this.setState(({ materials }) => ({
materials: materials.map((s, idx) =>
idx === index ? {...s, expanded: !StateStorage.materials[index].expanded} : {...s, expanded: false})
}));
console.log(StateStorage.materials[index].expanded)
}
You are searching for accordion :
Please refer to the native base accordion component. This is what you need.
https://docs.nativebase.io/Components.html#accordion-def-headref

how to expand a component on click to full screen width and height with animation in reactnative

I have tried to implement the component expand to full screen in react native by using Layout animation in react-native but it was not good to look. Can any one help me in getting it?
changeLayout = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
this.setState({ expanded: !this.state.expanded });
};
I expect to expand the component on click to full screen and again collapse it on click.
Set the initial value you want through the animation, obtain the screen width and height, and create a click function to execute.
This is an example that I made. Click this link if you want to run it yourself.
import React from 'react';
import { Animated, Text, View,Dimensions,Button } from 'react-native';
const screenwidth = Dimensions.get('screen').width
const screenheight = Dimensions.get('screen').height
class FadeInView extends React.Component {
state = {
fadeAnim: new Animated.Value(50),
fadeAnim2: new Animated.Value(50),
}
componentDidMount() {
}
animatebutton() {
Animated.timing( // Animate over time
this.state.fadeAnim, // The animated value to drive
{
toValue: screenheight,
duration: 10000, // Make it take a while
}
).start();
Animated.timing( // Animate over time
this.state.fadeAnim2, // The animated value to drive
{
toValue: screenwidth,
duration: 10000, // Make it take a while
}
).start(); // Starts the animation
}
render() {
let { fadeAnim,fadeAnim2 } = this.state;
return (
<Animated.View // Special animatable View
style={{
...this.props.style,
height: fadeAnim,
width : fadeAnim2
}}
>
{this.props.children}
</Animated.View>
);
}
}
// You can then use your `FadeInView` in place of a `View` in your components:
export default class App extends React.Component {
constructor(props){
super(props);
this.state={
}
}
animatebutton(){
this.fade.animatebutton();
}
render() {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}} >
<FadeInView style={{backgroundColor: 'powderblue'}} ref={ani => this.fade = ani}>
<Text style={{fontSize: 28, textAlign: 'center', margin: 10}}>Fading in</Text>
</FadeInView>
<Button title="go animate" onPress={() => this.animatebutton()}/>
</View>
)
}
}
OR
You can use LayoutAnimation that you want to use. Look at my example.
import React, {Component} from "react";
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableOpacity,
LayoutAnimation,
} from 'react-native';
class App extends Component {
constructor() {
super();
this.state = {
check: false,
}
}
onPresscheck() {
// Uncomment to animate the next state change.
LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
// Or use a Custom Layout Animation
// LayoutAnimation.configureNext(CustomLayoutAnimation);
this.setState({ check : !this.state.check});
}
render() {
var middleStyle = this.state.check === false ? {width: 20,height:20} : {width: "100%",height:"100%"};
return (
<View style={styles.container}>
<TouchableOpacity style={styles.button} onPress={() => this.onPresscheck()}>
<Text>pressbutton</Text>
</TouchableOpacity>
<View style={[middleStyle, {backgroundColor: 'seagreen'}]}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
button: {
width:"100%",
height: 60,
backgroundColor: 'blue',
alignItems: 'center',
justifyContent: 'center',
margin: 8,
},
});
export default App;
Please refer to this blog :
https://dev-yakuza.github.io/en/react-native/react-native-animatable/
Also, try using this library. Use any animation type you want and render them.
Happy coding :)

React Native done button above keyboard

I want to add a "Done" button above the keyboard, that will hide the keyboard when clicked.
Here's an image demonstrating the desired button:
Is there any existing method or library for that? (I already found this library but it doesn't work).
For numeric and number-pad :
and seems that you don't need any library
returnKeyType='done' works with "number-pad" and "numeric" on v0.47.1
for normal keyboard you may look at this :
https://github.com/ardaogulcan/react-native-keyboard-accessory
and
https://github.com/douglasjunior/react-native-keyboard-manager
Github thread you need to take a look at :
https://github.com/facebook/react-native/issues/1190
and
https://github.com/facebook/react-native/issues/641
Hope it helps
You can use React-native's KeyboardAvoidingView Component as
<KeyboardAvoidingView keyboardVerticalOffset={50}>
//View you want to be moved up when keyboard shows.
</KeyboardAvoidingView>
keyboardVerticalOffset={50}
is the margin between the keyboard and the view, which will be the height of view or button you want. I hope that helps.
Edit: the best and most customizable way I think to do this, is listening to Keyboard events and changing the absolute position of the component you want above the keyboard, according to it.
import {..,Keyboard} from "react-native";
componentDidMount () {
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow',(event)=>this.keyboardDidShow(event) );
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide',(event)=>this.keyboardDidHide(event) );
}
keyboardDidShow = (event) => {
// console.log("keyboard show",event)
this.setState({keyboardShow:true,keyboardHeight:event.endCoordinates.height}) //<<You got the keyboard height
}
keyboardDidHide = (event) => {
// console.log("keyboard hide",event)
this.setState({keyboardShow:false,keyboardHeight:0})
}
componentWillUnmount () {
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
}
now, to show it above the keyboard you can give style to your button component like this
style={{position:"absolute",bottom:this.state.keyboardHeight+20,right:0}}
and if you want to hide it (Done button) just condition the JSX with the keyboardShow state.
I am sharing my style of handling this case :
Code :
import React from 'react'
import { StyleSheet, Platform, View, Text, KeyboardAvoidingView, Keyboard } from 'react-native';
import { TextInput } from 'react-native-gesture-handler';
export default class StripAboveKeyboard extends React.Component {
constructor(props) {
super(props)
this.state = { keyboardHeight: 0 }
}
componentDidMount() {
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', (event) => this.keyboardDidShow(event));
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', (event) => this.keyboardDidHide(event));
}
keyboardDidShow = (event) => this.setState({ keyboardShow: true, keyboardHeight: event.endCoordinates.height > 100 ? (Platform.OS == 'ios' ? event.endCoordinates.height : 0) : 0 })
keyboardDidHide = (event) => this.setState({ keyboardShow: false, keyboardHeight: 0 })
componentWillUnmount() {
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
}
render() {
marginFromBottom = (this.state.keyboardHeight == 0) ? 0 : this.state.keyboardHeight
return (
<KeyboardAvoidingView style={{ flex: 1 }}>
<View style={style.parent}>
<View style={style.upper}>
<TextInput style={style.textInput}>User Name</TextInput>
</View>
<View style={{ ...style.bottomParent, marginBottom: marginFromBottom }}>
<Text style={style.bottom}>Press me</Text>
</View>
</View>
</KeyboardAvoidingView>)
}
}
const style = StyleSheet.create({
parent: {
flex: 1,
padding: 10,
backgroundColor: 'pink',
},
upper: {
paddingTop: 44,
backgroundColor: 'green',
padding: 10,
flex: 1,
marginBottom: 10,
},
textInput: {
height: 40, borderColor: 'gray', borderWidth: 1
},
bottomParent: {
justifyContent: "center",
alignItems: "center",
backgroundColor: 'red',
width: '100%',
height: 40,
},
bottom: {
textAlignVertical: "center", textAlign: "center",
}
})
Screenshots :
ANDROID & IOS
That is not a library or anything special. That is just a view that moves up with the keyboard.
Read this article - https://medium.freecodecamp.org/how-to-make-your-react-native-app-respond-gracefully-when-the-keyboard-pops-up-7442c1535580#.gd37tn1wx
It shows you different ways to make elements respect the keyboard.
Done button will not work for multiples line TextInput. To close keyboard you have to use
KeyboardAvoidingView
that will helpful to close it by touching outside of softkeyboard

React Native render and switch with navigator onPress

I've just started to develop with React Native a week ago.
Can anyone help me with simple render and switch onPress to another view?
I've read tones of examples, but most of them are cutted or not well documents as if on FaceBook Doc pages. There was no totally completed example with Nav.
Here is what was done yet - View that should be rendered 1st:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
TextInput,
TouchableHighlight,
TouchableNativeFeedback,
Platform,
Navigator
} from 'react-native';
export default class SignUp extends Component {
buttonClicked() {
console.log('Hi');
this.props.navigator.push({title: 'SignUp', component:SignUp});
}
render() {
var TouchableElement = TouchableHighlight;
if (Platform.OS === ANDROID_PLATFORM) {
TouchableElement = TouchableNativeFeedback;
}
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to Cross-Profi!
</Text>
<Text style={styles.field_row}>
<TextInput style={styles.stdfield} placeholder="Profession" />
</Text>
<Text style={styles.field_row}>
<TextInput style={styles.stdfield} placeholder="E-mail" />
</Text>
<Text style={styles.field_row}>
<TextInput style={styles.stdfield} secureTextEntry={true} placeholder="Password" />
</Text>
<TouchableElement style={styles.button} onPress={this.buttonClicked.bind(this)}>
<View>
<Text style={styles.buttonText}>Register</Text>
</View>
</TouchableElement>
{/* <Image source={require("./img/super_car.png")} style={{width:120,height:100}} />*/}
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+D or shake for dev menu
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'lightblue',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
color: 'darkred',
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
field_row: {
textAlign: 'center',
color: '#999999',
margin: 3,
},
stdfield: {
backgroundColor: 'darkgray',
height: 50,
width: 220,
textAlign: 'center'
},
button: {
borderColor:'blue',
borderWidth: 2,
margin: 5
},
buttonText: {
fontSize: 18,
fontWeight: 'bold'
}
});
const ANDROID_PLATFORM = 'android';
Navigator class that should render different views:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Platform,
Navigator
} from 'react-native';
var MainActivity = require('./app/MainActivity.js');
var SignUp = require('./app/SignUp.js');
class AwesomeProject extends Component {
/*constructor(props) {
super(props);
this.state = {text: ''};
}*/
render() {
// this.props.navigator.push({title:'SignUp'});
return (
<Navigator initialRoute={{title:'SignUp', component:SignUp}}
configureScene={() => {
return Navigator.SceneConfigs.FloatFromRight;
}}
renderScene={(route, navigator) =>
{
console.log(route, navigator);
if (route.component) {
return React.createElement(route.component, {navigator});
}
}
} />
);
}
}
const ANDROID_PLATFORM = 'android';
const routes = [
{title: 'MainActivity', component: MainActivity},
{title: 'SignUp', component: SignUp},
];
AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);
It doesn't seem to be clear whether there must be require of a class and declaration of class as export default.
There is an error: Element type is invalid: expected a string, ... but got object etc
Help with examples would be great. Thx
In your require call, you should either replace it import statement or use default property of require module i.e:
var MainActivity = require('./app/MainActivity.js').default;
or use
import MainActivity from "./app/MainActivity";
In ES6, require doesn't assign default property of module to variable.
See this blog post for better understanding of require working in es6