Hide the bottom image view when showing keyboard react-native - react-native

How I can hide this picture...
Thank you for any help!

You can use Keyboard in ReactNative to listen for changes of keyboard and hide your image when the keyboard is visible.
check below sample code
import * as React from "react";
import { View, Keyboard, TextInput, Image } from "react-native";
export default class App extends React.Component {
state = {
isKeyboadVisible: false,
text: ""
};
componentDidMount() {
this.keyboardDidShowListener = Keyboard.addListener(
"keyboardDidShow",
this._keyboardDidShow
);
this.keyboardDidHideListener = Keyboard.addListener(
"keyboardDidHide",
this._keyboardDidHide
);
}
componentWillUnmount() {
this.keyboardDidShowListener.remove();
this.keyboardDidHideListener.remove();
}
_keyboardDidShow = () => {
this.setState({
isKeyboadVisible: true
});
};
_keyboardDidHide = () => {
this.setState({
isKeyboadVisible: false
});
};
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<TextInput
style={{
height: 40,
width: "80%",
borderColor: "red",
borderWidth: 1,
marginBottom: 10
}}
onChangeText={text => this.setState({ text })}
value={this.state.text}
/>
{!this.state.isKeyboadVisible && (
<Image
style={{ width: 100, height: 100 }}
source={{ uri: "https://reactnative.dev/img/tiny_logo.png" }}
/>
)}
</View>
);
}
}
Change the above code according to your requirements.
Hope this helps you. Feel free for doubts.

You need to using ScrollView to wrapper your view. Therefore, when you click to input component, keyboard will overlap your picture.
https://reactnative.dev/docs/using-a-scrollview#__docusaurus
Another solution is try to using KeyboardAvoidingView
https://reactnative.dev/docs/keyboardavoidingview

Related

In React Native, is there anything similar to the activeOpacity prop in the new Pressable component?

In TouchableOpacity, it is possible to set the value of the activeOpacity prop to dim the button after it was pressed, so the user had feedback that their touch was registered and does not pressing the same button repeatedly.
Is there anything similar in the new Pressable component? Or any way to easily achieve the same effect?
You can try following example to achieve same functionality:
import React, { useState } from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native';
const App = () => {
const [timesPressed, setTimesPressed] = useState(0);
let textLog = '';
if (timesPressed > 1) {
textLog = timesPressed + 'x onPress';
} else if (timesPressed > 0) {
textLog = 'onPress';
}
return (
<View style={styles.container}>
<Pressable
onPress={() => {
setTimesPressed((current) => current + 1);
}}
style={({ pressed }) => [
{
backgroundColor: 'gray',
opacity: pressed ? 0.2 : 1
},
styles.wrapperCustom
]}>
{({ pressed }) => (
<Text style={styles.text}>
{pressed ? 'Pressed!' : 'Press Me'}
</Text>
)}
</Pressable>
<View style={styles.logBox}>
<Text testID="pressable_press_console">{textLog}</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
},
text: {
fontSize: 16
},
wrapperCustom: {
borderRadius: 8,
padding: 6
},
logBox: {
padding: 20,
margin: 10,
borderWidth: StyleSheet.hairlineWidth,
borderColor: '#f0f0f0',
backgroundColor: '#f9f9f9'
}
});
export default App;

react native spinner doesn't display on bottom

So I got this piece of code, and I want to display the Spinner on the bottom of the screen, just right after the FlatList, but when the function displaySpinner is called nothing displays after the flatlist. I've tried many things like putting trying to display the Spinner on the top of the view and then give it a Top but it's not what I'm looking for.
By the way I'm new in the programming world and more on React Native so I hope everything makes sense to understand my problem
import React, { Component } from 'react';
import { FlatList, StyleSheet, View, Text, Image } from 'react-native';
import axios from 'axios';
import moment from 'moment';
import Card from './Card';
import CardSection from './CardSection';
import Spinner from './Spinner';
class ArticleList extends Component {
state = { articles: [],
refreshing: false,
isLoading: false,
};
componentWillMount() {
this.loadArticles();
}
currentOffset = 0;
reloadContent() {
this.setState({
isLoading: true
});
this.currentOffset += 20;
console.log(this.currentOffset);
this.loadArticles();
}
loadArticles = () => {
const { articles } = this.state;
console.log(this.currentOffset);
axios.get(`https://sportsoftheday.com/wp-json/wp/v2/posts?per_page=20&offset=${this.currentOffset}`)
.then(res =>
this.setState({
articles: this.currentOffset === 0 ? res.data : [...articles, ...res.data],
isLoading: false,
}))
.catch(err => {
console.error(err);
});
};
displaySpinner() {
if (this.state.isLoading === true) {
return <Spinner size='large' />;
}
}
//Apply removeClippedSubviews for eliminating useless data on the screen
render() {
const { articles } = this.state;
this.date = this.date;
this.fimg_url = this.fimg_url;
return (
<View>
<FlatList
data={articles}
renderItem={({ item }) => (
<Card>
<CardSection>
<View style={styles.thumbnailContainerStyle}>
<Image
style={styles.thumbnailStyle}
source={{
uri: item.fimg_url,
cache: 'only-if-cached'
}}
/>
</View>
<View style={styles.headerContentStyle}>
<Text style={{ color: '#B2B2B2' }}>
{moment(item.date).format('dddd, Do MMMM YYYY')}</Text>
<Text
numberOfLines={3}
style={styles.headerTextStyle}
>
{item.title.rendered}
</Text>
</View>
</CardSection>
</Card>
)}
keyExtractor={i => i.id}
onEndReached={this.reloadContent.bind(this)}
onEndReachedThreshold={0.1}
/>
{this.displaySpinner()}
</View>
);
}
}
const styles = StyleSheet.create({
headerContentStyle: {
flexDirection: 'column',
justifyContent: 'space-around',
flex: 1
},
headerTextStyle: {
textAlign: 'justify',
fontSize: 18,
color: 'black',
marginRight: 15
},
thumbnailStyle: {
height: 70,
width: 70
},
thumbnailContainerStyle: {
justifyContent: 'center',
alignItems: 'center',
marginLeft: 10,
marginRight: 10
},
imageStyle: {
height: 300,
flex: 1,
width: null
},
});
export default ArticleList;
First things first, you should always avoid rendering a view/component directly in the renderItem = { } prop of your FlatList. Always send a function that is bounded to your current context that returns a component renderItem = {this._renderItem.bind(this)} or renderItem = {() => renderItem()}. This is not an issue but a usual practice that keeps the code clean and professional. Just a suggestion since you mentioned you're new to RN.
Coming to your question, the spinner shall show up once you wrap your Spinner inside a View component. You can do this either by wrapping your function call <View> {this.displaySpinner()} </View> or return a component that is already wrapped in a View <View> <Spinner/> </View>.
To make this even more effective, wrap everything including your flatlist but excluding your Header if you have one (Obviously) inside a View and give it a style of flex flex: 1 with a direction of column 'flexDirection: 'column'. Now you can justify your content with justifyContent: 'space-around' or 'space-between' whichever works for you.
Final point I'd like to make is again a suggestion. I've been working on RN for a while now but I still find designing the UI one of the most tedious tasks. Hot Reloading helps but not much. To track your UI changes on the screen, you can give the style borderColor: 'red', borderWidth: 1 to your views. This will help you a lot. It sure helps me.
I hope this helps.
Best of luck
Wrap that spinner in a view like View style = {{ position: "absolute", bottom: 0, width: '100%'}}
{this.displaySpinner()}
Close View

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

Prompt event occurs from eveywhere in the screen when taped

I am new in React Native. My problem occurred when prompt the event by clicking the Image icon. I want the prompt event occur from the image button only. But when i click or tap anywhere in the screen, it opens.What can be done to solve this issue ? In stylesheet, marginBottom and marginRight also doesn't work, so I use marginTop and marginLeft. What can be done to solve this also ?
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
TouchableHighlight
} from 'react-native';
import ToolbarAndroid from 'ToolbarAndroid';
import Prompt from 'react-native-prompt';
class DevForm extends Component {
constructor(props) {
super(props);
this.state = {
message: '',
promptVisible: false
};
}
render() {
return (
<View style = {styles.container}>
<ToolbarAndroid style = {styles.toolbar}>
<Text style = {styles.titleText}> Data Collector </Text>
</ToolbarAndroid>
<TouchableHighlight
onPress={() => this.setState({ promptVisible: true })}
>
<Image
source = {require('./icon_container/ic_plus_circle_add_new_form.png')}
style = {styles.addButton}
/>
</TouchableHighlight>
<View style = {{ flex: 1, justifyContent: 'center' }}>
<Text style = {{ fontSize: 20 }}>
{this.state.message}
</Text>
</View>
<Prompt
title = "Write title of form "
placeholder = "Your title is here"
visible = {this.state.promptVisible}
onCancel = {() => this.setState({ promptVisible: false, message: 'You cancel it !!!'})}
onSubmit={(value) => this.setState({ promptVisible: false, message: `You title is "${value}"` })}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCFF',
},
toolbar: {
height: 56,
backgroundColor: '#3F51B5'
},
titleText: {
fontSize: 16,
fontWeight: 'bold',
color: '#fff'
},
addButton: {
marginLeft: 270,
marginTop: 420,
height: 50,
width: 50
}
});
AppRegistry.registerComponent('DevForm', () => DevForm);
So What I could figure out after running the code is that prompt dialog only appears in the area covered by marginLeft and marginTop not the complete screen if you didn't have marginLeft and marginTop it would have been difficult to reproduce this bug. There might be a bug in the npm library "react-native-prompt" that you are using in this example other than that I am not sure what's actually going wrong.

How can I change the text in TabBarIOS in 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);