unable to apply flex to imported styled component - react-native

Im importing a styled component into another component and trying to move it by putting it in a View and using flex to push it to the bottom of the screen. Though in doing so the "styled component is not acting like a child of the View I place it in. This is limiting the reusability of my styled components. I'm questioning the use of styled-components now.
import React, {useContext} from 'react';
import styled from 'styled-components';
import ThemeContext from '../../../providers/ThemeProvider';
import {TouchableOpacity, Text} from 'react-native';
const Button = styled.TouchableOpacity`
display: flex;
height: 50px;
width: 90%;
background-color: ${props=> props.theme.primaryColor};
border-radius: 12px;
justify-content: center;
align-items: center;
margin: auto;
`;
export const AuthButton = props => {
return (
<Button onPress={() => props.onPress()}>
<Text style={{fontSize: 20, color: '#fff'}}>{props.text}</Text>
</Button>
);
};
<Wrapper>
<View style={{borderColor:'lime', borderWidth: 1, flex: 1, justifyContent: 'flex-end'}}>
<AuthButton text="Logout" onPress={()=> logoutUser()}/>
</View>
</Wrapper>

Im not sure but you need to use flexdirection before justify-content.
Example:
<View style={{
flex: 1,
flexDirection: 'column',
justifyContent: 'space-between',
}}>
in your case you should use:
<Wrapper>
<View style={{borderColor:'lime', borderWidth: 1, flex: 1, flexDirection: 'row',justifyContent: 'center' }}>
<AuthButton text="Logout" onPress={()=> logoutUser()}/>
</View>
</Wrapper>

For what ever reason flex properties aren't working for child components that are nested inside a View tag, so I'm using top instead.
<Wrapper style={{flex: 1,borderColor:'lime', borderWidth: 1}}>
<View style={{top: '85%'}}>
<AuthButton text="Logout" onPress={()=> logoutUser()}/>
</View>
</Wrapper>

Related

Body become Scrollable in React Native

i have small issue with scrollview.
i want to the title become sticky and the after the title means the messageBody become scrollable.
i have tried below one for this implementation.
HelpComponentContainer:---
<View style={{ height: "100%" }}>
<ScrollView
style={{ flexGrow: 0 }}
>
<View>
<Title>{messageTitle}</Title>
<MessageBody>{messageBody}</MessageBody>
</View>
</ScrollView>
</View>
const MessageBody = styled(Text)`
color: #2d3e58;
text-align: right;
align-self: center;
width: 90%;
`;
i am using this component in
message-widget-card:--
<RBSheet
ref={helpSheet}
closeOnDragDown={true}
closeOnPressMask={true}
height={hp(60)}
customStyles={{
wrapper: {
backgroundColor: "rgba(52,52,52,0.8)",
},
draggableIcon: {
backgroundColor: "#d3d6dc",
},
container: {
borderRadius: 15,
},
}}
>
<Container>
<HelpComponentContainer
isHelpForMessage={true}
messageTitle={helpMessageTitle}
messageBody={helpMessage}
/>
</Container>
</RBSheet>
i have tried this one.
But the scroll is not working.
just i want the Blue color title should be sticky and the body become scrollable.
How can i resolve this issue?
Thanks!!
Try to implement like this keep the title outside ScrollView.
const HelpComponentContainer = () => {
return (
<View style={{flex: 1}}>
<Title>{messageTitle}</Title>
<ScrollView style={{flex: 1}}>
<MessageBody>{messageBody}</MessageBody>
</ScrollView>
</View>
);
};
export default HelpComponentContainer;

How to achieve drop-shadow with no blur in React Native

I'm new using React Native and I'm trying to map the following component (made in web) but for React Native with no success:
Elevation and shadow properties does not do the trick because they add some blur to the resulting shadow. Which would be the proper way to handle this?
Regards
Use react-native-cardview
import React, { Component } from 'react';
import {
View,
ScrollView,
TextInput,
} from 'react-native';
import CardView from 'react-native-cardview';
import styles from './styles';
export default class Signup extends Component {
render() {
return (
<View style={{ flex: 1, backgroundColor: colors.whiteColor }}>
<ScrollView contentContainerStyle={styles.signupContainer}>
<View style={styles.signupInputs}>
<CardView
style={styles.cardStyle}
cardElevation={2}
cardMaxElevation={2}
cornerRadius={5}
>
<TextInput
underlineColorAndroid="transparent"
style={[styles.signupInput, styles.commonsignupStyle]}
placeholder="Nom *"
placeholderTextColor={colors.primaryColor}
/>
</CardView>
<CardView
style={styles.cardStyle}
cardElevation={2}
cardMaxElevation={2}
cornerRadius={5}
>
<TextInput
underlineColorAndroid="transparent"
style={[styles.signupInput, styles.commonsignupStyle]}
placeholder="Prénom *"
placeholderTextColor={colors.primaryColor}
/>
</CardView>
</View>
</ScrollView>
</View>
);
}
}
Edit:
For dynamic height, two lines or more of text, as asked for in the comments, I had to use another workaround.
https://snack.expo.io/7bVXvbmE0
const Label = () => {
return <View style={{width: 100, height: 50}}>
<View style={styles.topView}>
<Text>Hello world</Text>
<Text>Hi world</Text>
</View>
<View style={styles.shadowView} >
<Text style={{color: 'transparent'}}>Hello world</Text>
<Text style={{color: 'transparent'}}>Hi world</Text>
</View>
</View>;
}
Whatever dynamic text you have on the label, duplicate for the shadow label, but make it transparent. That way you are guaranteed that the shadow follows the top view.
Also, get rid of the hardcoded heights in the styles. For both top view and shadow view, their heights are informed by the text input, and the wrapper container's height is informed by the two views.
Lastly, change shadow view style's top to be just a few points above 0 to make sure you it peeks from under topview. You can adjust borderRadius of the shadow view to fit your preferences.
const styles = StyleSheet.create({
topView: {
width: '100%',
position: 'absolute',
top: 0, backgroundColor: 'white',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 25,
},
shadowView: {
position: 'absolute',
top: 3,
width: '100%',
zIndex: -10,
borderRadius: 17,
backgroundColor: '#ddd'}
});
Previous Post
A little bit hacky, but you can do this if you absolutely don't want any blur.
https://snack.expo.io/pWyPplcm3
const Label = () => {
return <View style={{width: 100, height: 30}}>
<View style={styles.topView}>
<Text>Hello world</Text>
</View>
<View style={styles.shadowView} />
</View>;
}
styles:
const styles = StyleSheet.create({
topView: {
height: 25,
width: '100%',
position: 'absolute',
top: 0, backgroundColor: 'white',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 15,
},
shadowView: {
position: 'absolute',
top: 0,
height: 28,
width: '100%',
zIndex: -10,
borderRadius: 13,
backgroundColor: '#ddd'}
});

TextInput got hides behind keyboard in react-native

I am creating chat UI in react native in which I want the first section (where the messages are shown) should be scrollable.
The TextInput should be at the bottom of screen and keyboard should be after it.
The UI is similar to WhatsApp chat screen. But I'm unable to re-create that UI.
I have also tried KeyboardAvoidingView from react-native but it doesn't works for me like it do.
App.js
import React, { useEffect, useState } from "react";
import {
ScrollView,
View,
Text,
Alert,
Dimensions,
Platform,
KeyboardAvoidingView,
TextInput,
TouchableOpacity,
} from "react-native";
import { Ionicons } from "#expo/vector-icons";
const App = () => {
const [message, setMessage] = useState([]);
return (
<View
style={{
display: "flex",
flex: 1,
justifyContent: "space-evenly",
alignItems: "center",
height: Dimensions.get("window").height,
width: Dimensions.get("window").width,
}}
>
<View
style={{
height: Dimensions.get("window").height * 0.8,
backgroundColor: "lightgrey",
width: Dimensions.get("window").width,
}}
>
<ScrollView></ScrollView>
</View>
<View
style={{
height: Dimensions.get("window").height * 0.2,
width: Dimensions.get("window").width,
display: "flex",
flexDirection: "row",
justifyContent: "space-evenly",
alignItems: "center",
padding: 25,
}}
>
<View style={{ flex: 4 }}>
<TextInput placeholder="Type Message ....." />
</View>
<TouchableOpacity>
<Ionicons name="md-send" size={30} color="#0af" />
</TouchableOpacity>
</View>
</View>
);
};
export default App;
I have added my code on expo snack.
I have run into this issue several times while working on react-native projects. I always find the native KeyboardAvoidingView module glitchy. So I use another package to make it work. I have tested it on your snack and it works fine.
The package is called react-native-keyboard-aware-scroll-view. It's
a lightweight package with an unpacked size of just 10kB.
It has several useful props that you can use to adjust the component. Check it out here.
Here is a link to the snack that I used to test your code.
import React, { useEffect, useState } from "react";
import {
ScrollView,
View,
Text,
Alert,
Dimensions,
Platform,
TextInput,
TouchableOpacity,
} from "react-native";
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'
import { Ionicons } from "#expo/vector-icons";
const App = () => {
const [message, setMessage] = useState([]);
return (
<KeyboardAwareScrollView
style={{
display: "flex",
flex: 1,
justifyContent: "space-evenly",
alignItems: "center",
height: Dimensions.get("window").height,
width: Dimensions.get("window").width,
}}
>
<View
style={{
height: Dimensions.get("window").height * 0.8,
backgroundColor: "lightgrey",
width: Dimensions.get("window").width,
}}
>
<ScrollView></ScrollView>
</View>
<View
style={{
height: Dimensions.get("window").height * 0.2,
width: Dimensions.get("window").width,
display: "flex",
flexDirection: "row",
justifyContent: "space-evenly",
alignItems: "center",
padding: 25,
}}
>
<View style={{ flex: 4 }}>
<TextInput placeholder="Type Message ....." />
</View>
<TouchableOpacity>
<Ionicons name="md-send" size={30} color="#0af" />
</TouchableOpacity>
</View>
</KeyboardAwareScrollView>
);
};
export default App;
use npm i react-native-keyboard-aware-scroll-view --save
import react-native-keyboard-aware-scroll-view
and then ..
<KeyboardAwareScrollView
contentContainerStyle={{
height: Dimensions.get("window").height * 2.25,
width: '100%'
}}
>
you can change *2.25 to change height

React-Native WebView Prevents onPress on Parent TouchableOpacity

i can expect, that in normal use you would want the touch events on a WebView to stay within the WebView, but in my case, i am using the WebView to draw some text with css (because i am unable to achieve this with the react-native stylesheet).
The Problem
in this code the WebView component is commented out, and when i press on the "hello world" text, the function console.log('onPress called.') is called; but if i uncomment the WebView, the touch event is never called.
is there a way to prevent the WebView from taking the onPress event?
import React, { Component } from 'react';
import { Text, TouchableOpacity, WebView } from 'react-native';
...
<TouchableOpacity
onPress={() => console.log('onPress called.')}
>
{/* <WebView
source={{
html: `
<h1
style="
font-family: 'Impact';
color: white;
font-size: 25px;
text-align: center;
letter-spacing: 1px;
-webkit-text-stroke-width: 1px;
-webkit-text-stroke-color: black;
"
>
HELLO WORLD from this
</h1>
`
}}
style={{
// position: 'absolute',
backgroundColor: 'transparent',
width: 200,
height: 100
}}
/> */}
<Text
style={{
position: 'absolute',
backgroundColor: 'transparent',
top: 100,
width: 200,
height: 100
}}
>hello world</Text>
</TouchableOpacity>
Update:
i have tried to prevent pointer events as suggested by user ValdaXD.
in this example when pointerEventsNone is set to false, the text will be clickable, but if pointerEventsNone is true, it will render the WebView and clicking on the WebView will not call the parent onPress event.
<TouchableWithoutFeedback
onPress={() => console.log({ isEditing: !isEditing })}
>
{!!pointerEventsNone ? (<View pointerEvents="none" style={{ height: 100, width: 200 }}>
<WebView
javaScriptEnabled={true}
injectedJavaScript={`document.body.addEventListener('click',
function(e){
window.postMessage("Message from WebView","*");
console.log(e);
})`}
onMessage={e => console.log("message", e)}
source={{
html: `
<html>
<body>
<h1
style="
font-family: 'Impact';
color: white;
font-size: 25px;
text-align: center;
letter-spacing: 1px;
-webkit-text-stroke-width: 1px;
-webkit-text-stroke-color: black;
"
>
HELLO WORLD from this
</h1>
</body>
</html>
`
}}
useWebKit
style={{
backgroundColor: 'transparent',
width: 200,
height: 100,
flex: 1
}}
/>
</View>)
: (<Text>hello world</Text>)
}
</TouchableWithoutFeedback>
I faced the same issue, what I did is replaced the TouchableOpacity with TouchableWithoutFeedback and created a view using the same style as a parent have and just added extra position: 'absolute' and used a state and touchable methods like below:
<TouchableWithoutFeedback onPress={() => {
}} onPressIn={()=>{
this.setState({boolState:true})
}} onPressOut={()=>{
this.setState({boolState:false})
}}
>
<View style={parentStyle}>
{boolState && <View style={[parentStyle,{
alignItems: 'center',
backgroundColor:'rgba(0,0,0,0.48)',
justifyContent: 'center',
position: 'absolute',
left: 0,
top: 0,
bottom:0,
right:0,
marginTop:0,
padding:0}]}/>}
-------------------------
-------------------------
</View>
</View>
</TouchableWithoutFeedback>
Yeah, you should wrap the webview in a view with pointerEvents ='none'
<View style={{...}} pointerEvents="none">
<WebView .../>
</View>

Align a component to right in react native

In my application, I want to align a component (searchBar) to the right corner of my screen.
The mainWrapper has flexDirection RIGHT, so I tried to use justifyContent: "flex-end". But it did not work. What am I doing wrong here?
import React from "react";
import { View, Text, StyleSheet, Dimensions } from "react-native";
import { DefaultButton , ClickableIcon} from "../../mixing/UI";
import { Search } from "../../config/images";
const width = Dimensions.get("window").width;
const chooseWorkoutHeader = props => (
<View style={styles.mainWrapper}>
<View style={styles.buttonWrapper}>
<DefaultButton
buttonText={styles.buttonText}
width={width * 0.3}
backgroundColor="white"
onPress={() => props.onClickPlaylists}>
Playlists
</DefaultButton>
<DefaultButton
buttonText={styles.buttonText}
width={width * 0.3}
backgroundColor="white"
onPress={() => props.onClickSortBy}>
Sort By
</DefaultButton>
</View>
{/* <View style={styles.searchBar}> */}
<ClickableIcon
source={Search}
height={35}
width={35}
style={styles.searchBar}
// onIconPressed={() => {
// navigation.navigate("mainfeed");
// }}
/>
{/* </View> */}
</View>
);
const styles = StyleSheet.create({
mainWrapper: {
borderWidth: 3,
flexDirection: "row",
padding: 10,
width: width,
backgroundColor: "white"
},
buttonWrapper: {
flexDirection: "row",
justifyContent: "space-between",
width: width * 0.62
},
buttonText: {
fontSize: 18,
textAlign: "center",
color: "gray"
},
searchBar: {
borderWidth: 1,
padding: 1,
justifyContent: 'flex-end'
}
});
export default chooseWorkoutHeader;
I tried alignSelf as well. But none of them worked. How to move the ClickableIcon which has styles as "searchBar" to the right of the screen?
You can achive this by putting flex: 1 for buttonWrapper
buttonWrapper: {
flexDirection: "row",
justifyContent: "space-between",
width: width * 0.62,
flex: 1, // Add this line
}
You have two component inside mainWrapper (buttonWrapper and ClickableIcon). flex: 1 will expand maximum with of buttonWrapper and leave space for ClickableIcon in right side.
Do you tried adding this to your "mainWrapper":
display: "flex"
As far as i know "flex" only workings when you also set the display attribute